fix(extract): descend past a Nix file's root function so its bindings are reached

A Nix library or module file's root expression is normally itself a function —
`{ pkgs, lib, ... }: <body>` — the near-universal header for the ecosystem.
That node matches nix_func_types, so walk_defs handed it to extract_func_def,
which resolved no name for it (the Nix resolver requires the function's parent
to be a `binding`; the root lambda's parent is the file root, `source_code`) and
minted nothing. walk_defs then hit `if (!descend_into_func) continue;` and
abandoned the whole subtree, so no binding below the header was ever visited.

The effect was total for the dominant file shape, and invisible for the rest:
a file opening with a bare `let` or attrset was walked normally, so the language
looked supported. Measured on a 320-file Nix repository, 253 of whose files
carry a function header:

              before   after
  Function        48     1900
  CALLS           56     1443
  files w/defs     8      258

Adding CBM_LANG_NIX to descend_into_func is sufficient. Descending does not
over-mint from curried lambdas: in `f = a: b: ...` the inner `b:` has a
function_expression parent, resolves no name, and stays out. Checked clean for
over-minting on map/foldl' arguments, `with` bodies, `inherit`, and
parenthesized lambdas; rec attrsets, nested attrsets, `let` inside a function
body, and factory-returned attrsets all mint correctly.

Call attribution is unaffected. CALLS scope is computed by a separate traversal
(push_boundary_scopes -> compute_func_qn) that calls the same shared
cbm_resolve_func_name this path uses, so definition names and call-scope names
agree by construction, and a scope is pushed only when that name resolves
non-NULL. The edge-count rise is previously-dropped edges being written, not
re-attributed ones: before the fix those edges named a source node that did not
exist.

The change is gated on ctx->language, so no other language's walk is affected.

Signed-off-by: Jason Bowman <jason@json64.dev>
This commit is contained in:
Jason Bowman
2026-07-27 17:14:39 -07:00
parent d90986b218
commit bf883308b4
+7 -1
View File
@@ -6758,10 +6758,16 @@ static void walk_defs(CBMExtractCtx *ctx, TSNode root, const CBMLangSpec *spec,
// Ada subprograms nest (a procedure body's declarative part can
// contain inner subprogram bodies); descend so the nested defs
// are captured and same-file calls to them resolve to a CALLS edge.
// Nix: a library/module file's ROOT expression is normally itself a
// function_expression (`{ pkgs, lib, ... }: <body>`), so stopping here
// abandons the entire file — every binding in it is lost. Descend so
// the body's `name = args: ...` bindings are reached. Inner curried
// lambdas (`f = a: b: ...`) resolve no name and mint nothing, so the
// extra descent adds defs without adding noise.
bool descend_into_func =
(ctx->language == CBM_LANG_WOLFRAM || ctx->language == CBM_LANG_TYPESCRIPT ||
ctx->language == CBM_LANG_JAVASCRIPT || ctx->language == CBM_LANG_TSX ||
ctx->language == CBM_LANG_ADA);
ctx->language == CBM_LANG_ADA || ctx->language == CBM_LANG_NIX);
if (!descend_into_func) {
continue;
}