What
The generic function_name() helper in crates/codegraph-core/src/ast_analysis/engine.rs (used by the NAPI-exposed analyzeComplexity/buildCfgAnalysis standalone entry points) resolves a function's display name via:
fn function_name(node: &Node, source: &[u8]) -> String {
node.child_by_field_name("name")
.map(|n| n.utf8_text(source).unwrap_or("<anonymous>").to_string())
.unwrap_or_else(|| "<anonymous>".to_string())
}
This only checks a direct name field on the function node itself. It silently falls back to "<anonymous>" for any language whose function name is nested deeper in the tree rather than a direct field — which is true for:
- Julia:
function_definition has no name field; the name is nested under signature → call_expression → child(0) (see extractors/julia.rs's signature_call helper, which already handles this correctly for the main extraction path).
- R:
function_definition also has no name field; the name comes from the enclosing binary_operator's LHS (see extractors/r_lang.rs and the comment on dataflowR in src/ast-analysis/rules/b3.ts).
Both languages' main extractors (JuliaExtractor, and R's extractor) already implement the correct, non-trivial name resolution — but the generic standalone-analysis helper doesn't reuse that logic, so native.analyzeComplexity(source, path, 'julia') / 'r' returns correct complexity/halstead metrics but name: "<anonymous>" for every function.
Impact
- Direct callers of the NAPI
analyzeComplexity/buildCfgAnalysis functions for Julia/R source get an unusable name field.
- The JS-side native-standalone-analysis fallback path (
src/ast-analysis/engine.ts's runNativeAnalysis → storeNativeComplexityResults/storeNativeCfgResults) matches native results back onto Definitions primarily by line number, with name only as a tie-breaker when multiple functions share a line — so this particular fallback path is NOT visibly broken in practice today, but any other consumer relying on the standalone functions' own name field is.
Where discovered
Found while implementing issue #2312 (Julia/Solidity complexity + Halstead rules). Solidity's function_definition DOES have a direct name field, so Solidity is unaffected — this is a Julia/R-only gap, pre-existing and unrelated to #2312's fixes, out of scope for that PR.
Suggested fix
Give function_name() a small per-language override table (or a generic "look inside signature/enclosing binary_operator" fallback chain) mirroring what extractors/julia.rs/extractors/r_lang.rs already do, so analyze_complexity_standalone/build_cfg_standalone report real names for these two languages too.
What
The generic
function_name()helper incrates/codegraph-core/src/ast_analysis/engine.rs(used by the NAPI-exposedanalyzeComplexity/buildCfgAnalysisstandalone entry points) resolves a function's display name via:This only checks a direct
namefield on the function node itself. It silently falls back to"<anonymous>"for any language whose function name is nested deeper in the tree rather than a direct field — which is true for:function_definitionhas nonamefield; the name is nested undersignature→call_expression→child(0)(seeextractors/julia.rs'ssignature_callhelper, which already handles this correctly for the main extraction path).function_definitionalso has nonamefield; the name comes from the enclosingbinary_operator's LHS (seeextractors/r_lang.rsand the comment ondataflowRinsrc/ast-analysis/rules/b3.ts).Both languages' main extractors (
JuliaExtractor, and R's extractor) already implement the correct, non-trivial name resolution — but the generic standalone-analysis helper doesn't reuse that logic, sonative.analyzeComplexity(source, path, 'julia')/'r'returns correctcomplexity/halsteadmetrics butname: "<anonymous>"for every function.Impact
analyzeComplexity/buildCfgAnalysisfunctions for Julia/R source get an unusablenamefield.src/ast-analysis/engine.ts'srunNativeAnalysis→storeNativeComplexityResults/storeNativeCfgResults) matches native results back ontoDefinitions primarily by line number, withnameonly as a tie-breaker when multiple functions share a line — so this particular fallback path is NOT visibly broken in practice today, but any other consumer relying on the standalone functions' ownnamefield is.Where discovered
Found while implementing issue #2312 (Julia/Solidity complexity + Halstead rules). Solidity's
function_definitionDOES have a directnamefield, so Solidity is unaffected — this is a Julia/R-only gap, pre-existing and unrelated to #2312's fixes, out of scope for that PR.Suggested fix
Give
function_name()a small per-language override table (or a generic "look insidesignature/enclosingbinary_operator" fallback chain) mirroring whatextractors/julia.rs/extractors/r_lang.rsalready do, soanalyze_complexity_standalone/build_cfg_standalonereport real names for these two languages too.