Repository navigation
fix(explore): a symbol written with its package resolves, like refresh.Discovery.refresh - #2750
Merged
Merged
Conversation
…sh.Discovery.refresh` Explore's token resolution, codegraph_node's lookup and the callers, callees and impact lookups dropped every Go symbol written the way Go code names it: `refresh.Discovery.refresh`, `storage.Queryable.Querier` and `gin.Context.Next` resolved to nothing, and so did `binding.Default`. Three gaps: - A qualified name was matched against the qualifiedName, which holds the type and not the package, or entirely against the path, which holds the package and not the type, never as a package followed by a type. A new matcher stage reads `pkg.Type.method` as leading qualifiers that name the package by path segment and trailing ones that end the node's scope. A Python `pkg.mod.Class.method` and a Rust `module::Type::method` read the same way. - A module's root package has no directory: gin's `context.go` is `package gin`. A Go package qualifier now also matches the package the file declares, read from its `package` clause (src/graph/go-package.ts). That covers versioned `v2/` directories and generated packages like prometheus's `io_prometheus_client` as well. The clause is read last and only where it can decide, a top-level function or a node whose scope already ends with the written type, so a common name's hundreds of definitions cost no file reads. - Explore and codegraph_node took a qualified token's matches from the full-text search's top 50 only, and for gin's `binding.Default` those were three `binding/default_validator*.go` files. Through one shared helper they now fall back to the exact-name index when the search has no match; the CLI's lookup already started there. The new stage runs only after the existing ones fail, and the search keeps its order, so a name that resolved before keeps its result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up found while validating #2748. Explore's token resolution,
codegraph_node's lookup andcodegraph_callers/codegraph_callees/codegraph_impactdropped every Go symbol written the way Go code names it:refresh.Discovery.refresh,storage.Queryable.Querierandgin.Context.Nextresolved to nothing, and so didbinding.Default;That's also why the orchestrator's prometheus check (
Discovery.refresh hetzner.refresher.refresh hcloudDiscovery.refresh) could never list robotDiscovery:hetzner.refresher.refreshnamed no symbol.On current main:
With this PR both render the full call path. The hetzner query's links now open with
refresher.refresh → robotDiscovery.refresh @discovery/hetzner/robot.go:73.Three gaps
matchesSymbolstage 3 readspkg.Type.methodas leading qualifiers that name the package (path segments, as stage 2 does) and trailing ones that end the node's scope.pkg.mod.Class.methodand a Rustmodule::Type::methodread the same way.context.goispackage gin.packageclause, read by the newsrc/graph/go-package.ts.v2/dirs and generated packages like prometheus'sio_prometheus_client.gin.New), or a node whose scope already ends with the written type. A common name's hundreds of definitions cost no file reads; an earlier version without that guard added 40 ms totargetgroup.Group.String.codegraph_nodetook a qualified token's matches from the full-text search's top 50 only. For gin'sbinding.Default, those were threebinding/default_validator*.gofiles.qualifiedSymbolMatches, which keeps the search order and falls back to the exact-name index when the search has no match. The CLI'slookupSymbolNodesalready started at the exact-name index.Every surface passes the same Go package reader, so they agree. The surfaces are:
codegraph_node;Validation
Tests:
__tests__/symbol-lookup-go-packages.test.ts(11 tests; unit plus an indexed Go fixture)The fixture holds:
context.go,package gin);binding.Defaultbesidebinding/default_validator.go, so the search answers with other nodes (asserted as a precondition);Discovery.refresh.pkg.Type.methodToken resolution: base = main, fix = this PR, one index per repo (both arms read it)
For every method and function, the spellings an agent writes, sampled (≤300 each):
Type.method: the control;<dir>.Type.method;<file stem>.Type.method;<dir>.Func;<package clause>.…where the clause isn't the directory.Each runs through explore's resolver,
codegraph_node's and the CLI's. The table shows how often the symbol the token was written from is found, explore's resolver, main → this PR:Type.method(control)dir.Type.methodstem.Type.methoddir.Funcdir.Func(it starts at the exact-name index); explore andcodegraph_nodenow match it.prompb.Sample.Stringand ripgrepsrc.RegexMatcher.new: the qualifier fits several definitions (twoprompbtrees; every crate'ssrc/).Explore, real queries (main → this PR)
gin.Engine.ServeHTTP gin.Engine.handleHTTPRequest gin.Context.Next: no Flow →ServeHTTP → handleHTTPRequest → Next, plus the middleware-chain links.gin.Context.ShouldBindWith binding.Binding.Bind binding.formBinding.Bind binding.mapForm: no Flow →ShouldBindWith → Binding.Bind → formBinding.Bind → mapForm.promql.Engine.execEvalStmt storage.Queryable.Querier storage.fanout.Querier storage.NewMergeQuerier: no Flow →execEvalStmt → Queryable.Querier → fanout.Querier → NewMergeQuerier.Discovery.refresh hetzner.refresher.refresh hcloudDiscovery.refresh: the links now open withrefresher.refresh → robotDiscovery.refresh.Controls and cost
Type.method/ bare names, produce byte-identical Flow text (0 differ).client.init:initis declared in many Go packages, and each candidate file's clause is read once.Suites
Full suite on this commit over main fc293f0, on Windows, with the kernel built,
CODEGRAPH_KERNEL_EXPECT=1and--maxWorkers=4 --minWorkers=1:Follow-up found (next PR)
In the precise hetzner query (
refresh.Discovery.refresh hetzner.refresher.refresh hcloudDiscovery.refresh), every link weighs the same. The generic refresher's 28 func-field targets come first in edge order and fill all six lines before hetzner's robotDiscovery. Interleaving links across the named symbols they hang from would list each named symbol's dispatch. That's the #2748 section's ordering, so it goes in its own PR.🤖 Generated with Claude Code