fix(go): a project package named like a standard-library package is not the standard library

A Go reference written through a package qualifier was dropped as a
standard-library reference whenever the qualifier matched a name in
the built-in list (errors, log, types, parser, encoding, template, ...).
The check looked at the name alone, never at what the file imports
under that name, so a project with its own package of such a name lost
nearly every call into it: harbor's errors.New(...) through its
lib/errors, prometheus's parser.Inspect(...) through promql/parser.

What the file imports now decides before the name does. A qualifier
the file imports, by its last path segment, the name goimports assumes
for an unaliased import, or an alias, from a package of one of the
project's own modules is a project package, and the reference goes on
to normal resolution. A file that imports the standard library's
package of that name, and a qualifier the file doesn't import at all,
are skipped as before.

Validation: the new test file has 7 cases, 4 of which fail on main;
all pass here, with the native kernel and with CODEGRAPH_KERNEL=0.
A/B against main: harbor 296f304 (its Go tree, 1,611 Go files) +2,889
edges, prometheus a2fda0e +454, 0 removed and 0 retargeted on both,
nodes unchanged. Every added edge was checked against its source: the
line spells qualifier.Name and the file imports the target's package
directory under that qualifier from inside the module (3,343 of
3,343), and a sample of 10 was read by eye. gin and cobra, and the
controls express and flask, are byte-identical. Index CPU on harbor,
median of 3 interleaved: 40.0 s on main, 39.9 s here.

Original PR #2368 by @danusha2345.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
danusha2345
2026-10-23 18:11:55 +00:00
committed by Colby Mchenry
co-authored by Claude Opus 5.5
parent 449eefa7da
commit 16f2d357bc
3 changed files with 186 additions and 1 deletions
+13 -1
View File
@@ -3307,6 +3307,16 @@ export class ReferenceResolver {
!PYTHON_BUILT_IN_TYPES.has(ref.referenceName.slice(0, dot));
}
/**
* True when the Go file imports `qualifier` — by its last path segment or
* an alias — from a package of one of the project's own modules.
*/
private isGoProjectPackage(ref: UnresolvedRef, qualifier: string): boolean {
return this.context
.getImportMappings(ref.filePath, ref.language)
.some((imp) => imp.localName === qualifier && this.context.getGoPackageDir?.(imp.source, ref.filePath) != null);
}
/**
* Check if reference is to a built-in or external symbol
*/
@@ -3401,7 +3411,9 @@ export class ReferenceResolver {
// Go standard library packages — refs like "fmt.Println", "http.ListenAndServe", etc.
if (ref.language === 'go') {
const dotIdx = name.indexOf('.');
if (dotIdx > 0) {
// What the file imports decides before the name does: a project package
// may be called `errors`, `log` or `types` too.
if (dotIdx > 0 && !this.isGoProjectPackage(ref, name.substring(0, dotIdx))) {
const pkg = name.substring(0, dotIdx);
// Not a local bound from a type assertion that is named like one:
// grpc-go's `parser.ParseConfig(…)` after `parser, ok :=