Context
Discovered while fixing #1783 (cross-language false-positive consumer attribution via the global-by-name call-resolution fallback in resolveByGlobal/resolveByReceiver/resolveReceiverEdge).
Description
buildClassHierarchyEdges in src/domain/graph/builder/stages/build-edges.ts (mirrored by the extends/implements block in crates/codegraph-core/src/domain/graph/builder/stages/build_edges.rs) resolves a class's extends/implements target purely by symbol name, with no file/import scoping and no language-consistency check:
const targetRows = (ctx.nodesByName.get(cls.extends) || []).filter((n) =>
EXTENDS_TARGET_KINDS.has(n.kind),
);
Unlike the calls/receiver edge fallbacks (now fixed in #1783 via isSameLanguageFamily/is_same_language_family), this lookup has no computeConfidence gate and no language check at all — a class Foo extends Bar can link to any same-named Bar class/struct/trait/record anywhere in the codebase, in any language, at confidence 1.0 (the maximum possible value).
The codebase's own code is already aware this is unscoped: src/domain/analysis/exports.ts explicitly excludes extends/implements edges from the codegraph exports consumer computation, with the comment:
"extends/implements edges are deliberately NOT included here: they are resolved by symbol name only, with no file/import scoping (see buildClassHierarchyEdges), so they can link same-named declarations across unrelated files — crediting them as consumers would surface false positives instead of fixing false negatives."
That's a workaround for one consumer (codegraph exports), not a fix at the source — any other query that reads extends/implements edges directly (class hierarchy analysis, CHA subclass-override expansion, codegraph query, graph export/visualization) still sees the corrupted edges.
Suggested fix
Apply the same isSameLanguageFamily/is_same_language_family guard (added in #1783) to buildClassHierarchyEdges's target lookup, and consider whether a computeConfidence-style proximity threshold should apply here too (currently hardcoded to confidence 1.0 regardless of file distance).
Source
Found during: fix for #1783 (cross-language false-positive consumer attribution)
Context
Discovered while fixing #1783 (cross-language false-positive consumer attribution via the global-by-name call-resolution fallback in
resolveByGlobal/resolveByReceiver/resolveReceiverEdge).Description
buildClassHierarchyEdgesinsrc/domain/graph/builder/stages/build-edges.ts(mirrored by theextends/implementsblock incrates/codegraph-core/src/domain/graph/builder/stages/build_edges.rs) resolves a class'sextends/implementstarget purely by symbol name, with no file/import scoping and no language-consistency check:Unlike the
calls/receiveredge fallbacks (now fixed in #1783 viaisSameLanguageFamily/is_same_language_family), this lookup has nocomputeConfidencegate and no language check at all — a classFoo extends Barcan link to any same-namedBarclass/struct/trait/record anywhere in the codebase, in any language, at confidence 1.0 (the maximum possible value).The codebase's own code is already aware this is unscoped:
src/domain/analysis/exports.tsexplicitly excludesextends/implementsedges from thecodegraph exportsconsumer computation, with the comment:That's a workaround for one consumer (
codegraph exports), not a fix at the source — any other query that readsextends/implementsedges directly (class hierarchy analysis, CHA subclass-override expansion,codegraph query, graph export/visualization) still sees the corrupted edges.Suggested fix
Apply the same
isSameLanguageFamily/is_same_language_familyguard (added in #1783) tobuildClassHierarchyEdges's target lookup, and consider whether acomputeConfidence-style proximity threshold should apply here too (currently hardcoded to confidence 1.0 regardless of file distance).Source
Found during: fix for #1783 (cross-language false-positive consumer attribution)