A function called only from an anonymous func_literal at package level — a
cobra `RunE: func(){…}` handler, a goroutine literal, a callback closure
stored in a `var` — had its call leak to the FILE node, because the Go
var-initializer walk ran with an empty scope. So `callers`/`impact` showed
the function with a file (or no meaningful) caller, unlike JS/TS where an
arrow-in-const becomes a named node whose calls attribute correctly.
Scope the Go top-level var/const initializer walk to the declared symbol, so
a call nested in any func_literal initializer (struct field, slice/map,
nested closure) attributes to the enclosing var. EXTRACTION_VERSION 3->4
(re-index to pick up the corrected attribution).
Validated on cli/cli (858 Go files): node/edge counts identical, file-level
dependents byte-identical (no regression), and 62 top-level-closure calls
correctly moved from file-attributed to var-attributed.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
35b44e242c
commit
5b3f5e36db
@@ -21,4 +21,4 @@
|
||||
* turns the re-index hint into noise — keep it honest (see CLAUDE.md, "Honesty
|
||||
* in the product is load-bearing").
|
||||
*/
|
||||
export const EXTRACTION_VERSION = 3;
|
||||
export const EXTRACTION_VERSION = 4;
|
||||
|
||||
@@ -1499,13 +1499,14 @@ export class TreeSitterExtractor {
|
||||
|
||||
for (const spec of specs) {
|
||||
const nameNode = spec.namedChild(0);
|
||||
let varNode: Node | null = null;
|
||||
if (nameNode && nameNode.type === 'identifier') {
|
||||
const name = getNodeText(nameNode, this.source);
|
||||
const valueNode = spec.namedChildCount > 1 ? spec.namedChild(spec.namedChildCount - 1) : null;
|
||||
const initValue = valueNode ? getNodeText(valueNode, this.source).slice(0, 100) : undefined;
|
||||
const initSignature = initValue ? `= ${initValue}${initValue.length >= 100 ? '...' : ''}` : undefined;
|
||||
|
||||
this.createNode(node.type === 'const_declaration' ? 'constant' : 'variable', name, spec, {
|
||||
varNode = this.createNode(node.type === 'const_declaration' ? 'constant' : 'variable', name, spec, {
|
||||
docstring,
|
||||
signature: initSignature,
|
||||
});
|
||||
@@ -1515,8 +1516,16 @@ export class TreeSitterExtractor {
|
||||
// implementations) or `var c = pkg.New()` are extracted as
|
||||
// instantiates/calls dependencies — the body walker only covers
|
||||
// initializers inside functions, not these top-level declarations.
|
||||
// Scope the walk to the declared symbol so a call inside an anonymous
|
||||
// func_literal initializer — a cobra `RunE: func(){…}` handler, a
|
||||
// goroutine or callback closure — attributes to the var instead of
|
||||
// leaking to the file node (which reads as "no caller"), issue #693.
|
||||
const valueField = getChildByField(spec, 'value');
|
||||
if (valueField) this.visitFunctionBody(valueField, '');
|
||||
if (valueField) {
|
||||
if (varNode) this.nodeStack.push(varNode.id);
|
||||
this.visitFunctionBody(valueField, varNode?.id ?? '');
|
||||
if (varNode) this.nodeStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle short_var_declaration (:=)
|
||||
|
||||
Reference in New Issue
Block a user