fix(go): field-chain calls resolve via validated type inference, never bare-name guessing (#1316)
target.conn.Exec("insert") with `conn *sql.DB` emitted a BARE `Exec`
ref (the receiver chain was dropped for non-identifier receivers), and
exact-match then bound it to the only local `Exec` — an unrelated
interface's method — fabricating an internal dependency (#1276).
Extraction now keeps Go 2-hop selector chains (`base.field.Method`),
and a dedicated matcher resolves them EXCLUSIVELY via two inference
hops: base's type from the enclosing scope (#1108 machinery), field's
declared type from the struct's own declaration lines (comment-
stripped, per-line — chi's "the tree router" doc comment otherwise
donates a phantom type). resolveMethodOnType validates the target.
Package-qualified field types are followed only when the package is
in-module — `handler http.Handler` must not bind a same-named local
decoy. Failure at any hop leaves the ref unresolved: chained Go
receivers never fall through to the bare-name strategies (they were
never emitted before, so no prior recall depends on that path).
chi before/after: node count stable (1,181); 8 correct field-chain
edges gained (mx.tree.FindRoute/InsertRoute/routes, validated,
including the unexported `node` type); the removed edges are the
prior bare-name guesses on external receivers.
Fixes #1276
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
2ec877b08c
commit
41c2029798
@@ -4431,6 +4431,21 @@ export class TreeSitterExtractor {
|
||||
// scope keywords: such calls previously emitted a bare method
|
||||
// name, which either failed to resolve or resolved ambiguously.
|
||||
calleeName = `${getNodeText(receiver, this.source)}.${methodName}`;
|
||||
} else if (
|
||||
this.language === 'go' &&
|
||||
receiver &&
|
||||
receiver.type === 'selector_expression' &&
|
||||
/^[A-Za-z_]\w*\.[A-Za-z_]\w*$/.test(getNodeText(receiver, this.source).replace(/\s+/g, ''))
|
||||
) {
|
||||
// Go 2-hop field chain `target.conn.Exec(...)`: keep the
|
||||
// receiver chain so resolution can infer `conn`'s declared type
|
||||
// from the Target struct. Previously this emitted the bare
|
||||
// method name, and when the field's type is EXTERNAL (sql.DB)
|
||||
// the bare name exact-matched an unrelated same-named local
|
||||
// method — a fabricated internal dependency (#1276). Chained
|
||||
// Go receivers resolve strictly via validated field-hop
|
||||
// inference (see matchGoFieldChainCall) or stay unresolved.
|
||||
calleeName = `${getNodeText(receiver, this.source).replace(/\s+/g, '')}.${methodName}`;
|
||||
} else {
|
||||
calleeName = methodName;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user