mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-27 21:55:14 +08:00
fix(extraction): a Go method carries the exportedness of its name
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>
This commit is contained in:
committed by
Colby Mchenry
co-authored by
Claude Opus 5.5
parent
8f8f04b7fc
commit
90c5dc6fc9
@@ -2790,10 +2790,20 @@ export class TreeSitterExtractor {
|
||||
// on every ordinary method (breaks kernel↔wasm parity JSON equality).
|
||||
const isAbstract = this.extractor.isAbstract?.(node) ? true : undefined;
|
||||
const returnType = this.extractor.getReturnType?.(node, this.source);
|
||||
// A method that is a top-level declaration (Go: `func (r *T) Name()`) has
|
||||
// the same exportedness rule as a function — the name's case — and a
|
||||
// consumer asking "can another package name this?" needs it on methods
|
||||
// too. Class members keep the flag unset: their reachability is the
|
||||
// class's, and the languages whose isExported walks the parent chain
|
||||
// (JS/TS) would otherwise re-mark every member of an exported class.
|
||||
const isExported = this.extractor.methodsAreTopLevel
|
||||
? this.extractor.isExported?.(node, this.source)
|
||||
: undefined;
|
||||
const extraProps: Partial<Node> = {
|
||||
docstring,
|
||||
signature,
|
||||
visibility,
|
||||
isExported,
|
||||
isAsync,
|
||||
isStatic,
|
||||
isAbstract,
|
||||
|
||||
@@ -3935,7 +3935,9 @@ function findGoPackageMember(
|
||||
if (pkgDir == null) return null;
|
||||
for (const node of context.getNodesByName(memberName)) {
|
||||
if (node.language !== 'go') continue;
|
||||
if (!node.isExported) continue;
|
||||
// A method is no member of its package: `pkg.Infof` is the package's
|
||||
// function, never a method `(*Logger).Infof` declared beside it.
|
||||
if (!node.isExported || node.kind === 'method') continue;
|
||||
if (path.posix.dirname(node.filePath.replace(/\\/g, '/')) === pkgDir) {
|
||||
return {
|
||||
original: ref,
|
||||
|
||||
@@ -3370,7 +3370,7 @@ function isSfcPrivate(n: Node, context: ResolutionContext): boolean {
|
||||
* Whether Go lets `ref`'s file name the Go declaration `candidate`: an
|
||||
* exported name from anywhere, an unexported one only inside its own package,
|
||||
* which is a directory. By the name's first letter, not the extractor's flag:
|
||||
* the flag is unset for every Go method, exported or not.
|
||||
* an index built before Go methods carried the flag has it unset on every one.
|
||||
*
|
||||
* A package's external tests (`package a_test` beside `package a`) share its
|
||||
* directory but are a package of their own: a name one of them declares at
|
||||
@@ -3412,8 +3412,8 @@ function isGoNameVisible(candidate: Node, ref: UnresolvedRef, context: Resolutio
|
||||
* files its `part` directives name — so another file of the library names
|
||||
* it, and a file of another library never does (#2466).
|
||||
* - **Go**: an unexported (lowercase) identifier is package-local, and a
|
||||
* package is a directory. Judged by the name's case: the extractor's
|
||||
* `isExported` is unset for every Go method.
|
||||
* package is a directory. Judged by the name's case, which an older index's
|
||||
* Go methods don't carry in `isExported`.
|
||||
* - **Rust**: a non-`pub` item is visible to its module and that module's
|
||||
* descendants, never to a sibling module or another crate — `.count()` on
|
||||
* an iterator resolved onto a `fn count` in a different crate. A method in
|
||||
|
||||
Reference in New Issue
Block a user