A Go method's QN was the flat package form (proj.pkg.method) — the
receiver was ignored, so every same-name method in a package collided
on one QN and the graph upsert kept exactly one node. Measured on a
real Go repo: 20 Process/Name methods across 15 files kept 2 nodes;
9 different Task() methods fused into one chimera node carrying all
nine bodies' call edges; 19 structs pointed DEFINES_METHOD at a single
shared method node; a _test.go mock Close outranked the production
Close in the dedupe tie-break. The upsert's own comment calls
kind-disambiguated QNs 'the real cure'.
Qualify the QN with the receiver type (proj.pkg.Recv.method), the same
shape as Go interface members and the C++ out-of-line method path
right below it in extract_func_def:
- extract_defs.c: def.qualified_name = parent_class + name whenever
the receiver type resolves; go_receiver_type_name becomes the shared
cbm_go_receiver_type_name (exported via helpers.h) so both sides of
the contract use one formula.
- extract_unified.c (compute_func_qn): mirror branch for
method_declaration, so method-body calls keep exact source
attribution instead of degrading to File-node fallback
(calls_find_source).
- Consumers already agree: pxc_build_lsp_def passes the def QN and
parent_class (receiver_type) verbatim into the Go LSP registries,
and check_go_class_implements explicitly supports class-qualified
method QNs (its path (b)).
Side effect: resolve_same_module's exact module.name hash no longer
matches concrete methods, which kills the conf-0.9 false edges where
an interface-typed call bound to an unrelated same-package method.
Fixes#1909
Signed-off-by: Ilya Brykau <ilya.brykau@orca.security>