Skip to content

fix(resolution): Go cross-package qualified calls resolve via go.mod (#388)#469

Merged
colbymchenry merged 1 commit into
mainfrom
fix/388-go-cross-pkg-callers
May 26, 2026
Merged

fix(resolution): Go cross-package qualified calls resolve via go.mod (#388)#469
colbymchenry merged 1 commit into
mainfrom
fix/388-go-cross-pkg-callers

Conversation

@colbymchenry
Copy link
Copy Markdown
Owner

Summary

pkga.FuncX(...) cross-package calls in any Go monorepo were dropping through the import resolver and falling back to name-matching's path-proximity scoring, which on a layered codebase (handler/service/domain/dao) picks one accidental candidate per call site (~<1% recall — see issue #388's 5,303-vs-1 figure).

Root cause: isExternalImport(go) flagged any import without /internal/ as third-party, because the resolver had no idea what the project's own module path was. codegraph_callers, _callees, _impact, and _trace all silently degraded to near-empty on real Go codebases.

What changed

  • src/resolution/go-module.ts (new) — parses the module ... directive from project-root go.mod, exposed via getGoModule() on ResolutionContext.
  • isExternalImport(go) — treats <module-path>/... imports as in-module; existing /internal/ escape hatch preserved.
  • resolveViaImport — dedicated Go cross-package branch strips the module prefix to a directory and resolves the qualified member by getNodesByName(member) filtered to that exact directory + isExported=true. Sub-packages don't collide with parents; same-name funcs in different packages don't false-merge.
  • go.ts extractor — sets isExported from the identifier's first character (Go's universal uppercase=exported convention). The resolver needs this flag to filter candidates.

Measured impact

Validated on gRPC-Go (1,031 .go files, layered packages):

Metric Without fix With fix Δ
Total calls edges 23,803 34,105 +43%
Cross-pkg calls 10,880 19,929 +83%
fmt.* / stdlib false-resolves 0 0 clean

Also validated:

  • Same-name Convert funcs in two packages — only the imported one resolves
  • Aliased imports (import alias "github.com/.../pkg") — resolve via alias
  • No regression on /internal/ packages (still resolve under both old and new path)
  • 1010 existing tests pass; 3 new Go regression tests added

Test plan

Closes #388.

🤖 Generated with Claude Code

…388)

`pkga.FuncX(...)` calls in any non-`/internal/` Go package were dropping
through the import resolver because `isExternalImport` flagged every
non-relative, non-`/internal/` Go import as third-party — the resolver
had no idea what the project's own module path was. The remaining
candidates fell through to name-matching's path-proximity scoring, which
on a layered handler/service/domain/dao codebase picks one accidental
candidate per call site (~<1% recall, per issue #388's 5303-vs-1 figure).

- New `src/resolution/go-module.ts` parses the `module ...` directive
  from the project-root `go.mod` and exposes it via `getGoModule()` on
  the resolution context.
- `isExternalImport(go)` now returns `false` for imports that start
  with `<module-path>/` (or equal it). The existing `/internal/`
  escape hatch is preserved for projects without a parsed go.mod.
- `resolveViaImport` gets a dedicated Go cross-package branch that
  strips the module prefix to a project-relative directory and resolves
  the qualified member by looking up `getNodesByName(member)` filtered
  to that exact directory and `isExported=true`. Sub-packages don't
  collide with their parents.
- Go extractor now sets `isExported` from the identifier's first
  character (uppercase = exported, Go's universal convention). The
  resolver depends on this to filter candidates.

Validation on gRPC-Go (1,031 .go files, layered package tree):
  total `calls` edges:    23,803 -> 34,105 (+43%)
  cross-pkg `calls`:      10,880 -> 19,929 (+83%)
  fmt/strconv/etc. stdlib calls: stay external (no false positives)

Tests cover the three failure modes: in-module disambiguation with
same-name funcs in two packages, aliased imports, and stdlib calls
not being false-resolved to in-project nodes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Go: codegraph_callers severely under-reports cross-package qualified calls (pkg.Func(...)) — <1% recall on a large Go monorepo

1 participant