Skip to content

fix(extraction): a Go method carries the exportedness of its name - #1734

Closed
danusha2345 wants to merge 1 commit into
colbymchenry:mainfrom
danusha2345:fix/go-method-exported
Closed

danusha2345 wants to merge 1 commit into
colbymchenry:mainfrom
danusha2345:fix/go-method-exported

Conversation

@danusha2345

@danusha2345 danusha2345 commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Standalone off main (b9ca4b7), one commit, both extraction arms. The extractor defect noted in #1731.

What

extractMethod never set isExported, so every Go method was indexed as unexported whatever the case of its name — 148 of 148 on a 42-file tree, func (w *rotatingLogWriter) Close() included — while plain functions carried the flag. codegraph-kernel/src/go.rs mirrored the omission literally (// extractMethod passes no isExported).

A method that is a top-level declaration (methodsAreTopLevel — Go is the only such extractor) now receives the extractor's isExported exactly as a function does, and go.rs sets is_exported from the same name-case rule in extract_method. Class members in other languages keep the flag unset on purpose: their reachability is the class's, and the JS/TS isExported walks the parent chain, so applying it to methods would re-mark every member of an exported class and diverge the tsjs kernel walker.

Measured

Same Go/Kotlin/JS tree, kernel rebuilt from this checkout and confirmed loaded with CODEGRAPH_KERNEL_DEBUG=1:

Go methods base this
exported 0 41
unexported 148 107

Close / String → exported, close → not. Functions unchanged (135 / 175). The wasm arm (CODEGRAPH_KERNEL=0) gives the same flags.

Tests

extraction.test.ts: a four-symbol Go file (Close, flush, Open, helper) asserting the flag on both methods and both functions; passes on the wasm arm and with the kernel loaded. kernel-scaffold, kernel-deep-nesting, kernel-grammar-parity: 31 passed with the rebuilt kernel.

Relationship to #1732: that PR judges Go visibility by the name's case precisely because this flag was unusable; with this in, the flag and the case agree, and #1732's rule can later read the flag.

Note after the rebase onto 6421644. Two comments in src/resolution/name-matcher.ts (from #1745, in isVisibleAcrossFiles and its Go branch) say the extractor's isExported is unset for every Go method. With this PR the flag is set from the name's case, so those comments become stale; the code there stays correct, because it judges by the first letter, which gives the same answer. This PR does not touch that file.

🤖 Generated with Claude Code

@danusha2345

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (2f1a99d): head 38d2b25. Conflicts were only the CHANGELOG and the neighbouring #1729 tests in extraction.test.ts. Kernel rebuilt; the Go test passes on both arms. Once this lands, the by-name-case rule #1745 carries for Go can read the flag instead.

@danusha2345
danusha2345 force-pushed the fix/go-method-exported branch 2 times, most recently from 7208d3e to 18b4b30 Compare September 8, 2026 14:07
@danusha2345

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (b715eb6): head 18b4b30, one commit. CHANGELOG was the only conflict. Kernel rebuilt; the Go extraction tests pass on both arms (kernel and CODEGRAPH_KERNEL=0).

@danusha2345
danusha2345 force-pushed the fix/go-method-exported branch 4 times, most recently from c8a372f to 8458233 Compare October 10, 2026 11:33
@danusha2345
danusha2345 force-pushed the fix/go-method-exported branch 5 times, most recently from cb49849 to ce91105 Compare October 21, 2026 18:04
extractMethod never set isExported, so every Go method was indexed as
unexported — 148 of 148 on a 42-file tree, `func (w *rotatingLogWriter)
Close()` included — while plain functions carried the flag from the name's
case. The kernel's go.rs mirrored the omission ("extractMethod passes no
isExported").

A method that is a top-level declaration (methodsAreTopLevel — Go is the
only such extractor) now gets the extractor's isExported like a function
does; go.rs sets is_exported from the same name-case rule in extract_method.
Class members elsewhere keep the flag unset on purpose: their reachability
is the class's, and the JS/TS isExported walks the parent chain, so applying
it to methods would re-mark every member of an exported class and diverge
the tsjs kernel walker.

Same tree, kernel arm: methods 41 exported / 107 unexported (was 0 / 148);
wasm arm identical. kernel-scaffold, kernel-deep-nesting and
kernel-grammar-parity pass with the rebuilt kernel loaded.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@danusha2345
danusha2345 force-pushed the fix/go-method-exported branch from ce91105 to 4434ab0 Compare October 22, 2026 10:54
colbymchenry pushed a commit that referenced this pull request Oct 23, 2026
Every Go method was indexed as unexported, whatever the case of its
name, in both engines: extractMethod never set isExported, and the
kernel's go.rs mirrored the omission. Plain functions carried the flag,
so dead-code results listed exported methods like Close as dead.

A method that is a top-level declaration (methodsAreTopLevel, only Go)
now gets the extractor's isExported, as a function does, and go.rs sets
is_exported from the same name-case rule in extract_method.

Added on top of the contributor's change: findGoPackageMember, which
resolves pkg.Name through a project import, matched any exported node
of that name in the package's directory, and methods stayed out only
because none was exported. With the flag set, a package-level call
like harbor's log.Errorf(...) went to the method Logger::Errorf
declared beside the function, and prometheus's embedded
storage.Appender resolved to a method named Appender, which dropped
its implements edges. A method is no member of its package, so it is
now skipped there. Two comments in name-matcher.ts that said the flag
is unset on every Go method now say why the name's case is still read.

Validation: the contributor's test fails on main and passes here, and
the new package-call test fails with the PR as first written and
passes here and on main, in both engines. A/B against main on harbor
296f304, prometheus a2fda0e, gin 0f09c3a and cobra adbc881: nodes
differ only in is_exported 0 -> 1 on uppercase Go methods (5,704,
3,880, 391 and 141). Edges are identical on prometheus and cobra; 22
retargets remain, all name-only guesses between an interface's method
declaration and the struct method implementing it, which now win: gin's
engine().GET and its siblings reach RouterGroup's methods, and harbor's
jobservice routes reach DefaultHandler's. The PR as first written had
retargeted 1,384 harbor calls and removed 60 prometheus implements and
dispatch sites. The dead-code report lists 3 Go symbols on harbor
instead of 167, and 0 on prometheus instead of 11. Kernel parity: 2,493
of 2,493 Go files byte-identical. The controls express and flask are
byte-identical. Index CPU on harbor, median of 5 interleaved: 40.8 s on
main, 39.8 s here. EXTRACTION_VERSION stays: main already moved it to
28 after 1.6.2, so 1.6.2 indexes get the re-index hint anyway.

Original PR #1734 by @danusha2345.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@colbymchenry

Copy link
Copy Markdown
Owner

Thanks @danusha2345! Go methods finally carry their exportedness, so the dead-code report no longer lists exported methods (harbor went from 167 listed Go symbols to 3).

We landed it in #2857, with you as the author, plus one fix. Once methods were flagged exported, a call through a package name like log.Errorf(...) could resolve to a same-named method declared beside the function (1,384 call sites on harbor). Go never reaches a method through the package name, so that lookup now skips methods, with a test for it. Thanks also for pointing out the stale comments; we updated those. Closing this in favor of #2857, which is now merged.

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.

2 participants