MCPcopy
hub / github.com/colbymchenry/codegraph / findSymbolMatches

Method findSymbolMatches

src/mcp/tools.ts:4318–4363  ·  view source on GitHub ↗

* Find ALL definitions matching a name, ranked, so codegraph_node can return * every overload instead of guessing one (the wrong guess → a Read). Keepers * rank before generated stubs (.pb.go etc.); stable within a group preserves * FTS order. Returns [] when nothing matches; a qualified lo

(cg: CodeGraph, symbol: string)

Source from the content-addressed store, hash-verified

4316 * bare name with no exact match falls back to the single top fuzzy result.
4317 */
4318 private findSymbolMatches(cg: CodeGraph, symbol: string): Node[] {
4319 const isQualified = /[.\/]|::/.test(symbol);
4320
4321 // For a bare name, enumerate EVERY exact-name definition via the direct index
4322 // (not FTS, which caps + ranks): tokio's `poll` has 50+ defs and the one the
4323 // caller wants (`Harness::poll` at harness.rs:153) ranks below any search cut,
4324 // so it could be neither rendered nor pinned by the file/line disambiguator —
4325 // and the agent Read it. With the full set, the multi-overload render + the
4326 // file/line filter can both reach it.
4327 if (!isQualified) {
4328 const exact = cg.getNodesByName(symbol);
4329 if (exact.length > 0) {
4330 return [...exact].sort((a, b) => (isGeneratedFile(a.filePath) ? 1 : 0) - (isGeneratedFile(b.filePath) ? 1 : 0));
4331 }
4332 // No exact match — use the single top fuzzy result (e.g. a file basename).
4333 const fuzzy = cg.searchNodes(symbol, { limit: 10 });
4334 return fuzzy[0] ? [fuzzy[0].node] : [];
4335 }
4336
4337 // Qualified lookup (`Session.request`, `stage_apply::run`): FTS + matchesSymbol.
4338 const limit = 50;
4339 let results = cg.searchNodes(symbol, { limit });
4340
4341 // FTS strips colons, so `stage_apply::run` searches the literal
4342 // `stage_applyrun` and finds nothing. Re-search by the bare last part and
4343 // let `matchesSymbol` filter by qualifier.
4344 if (isQualified && results.length === 0) {
4345 const tail = lastQualifierPart(symbol);
4346 if (tail && tail !== symbol) results = cg.searchNodes(tail, { limit });
4347 }
4348
4349 if (results.length === 0) return [];
4350
4351 const exactMatches = results.filter((r) => this.matchesSymbol(r.node, symbol));
4352 if (exactMatches.length === 0) {
4353 // No exact match — a qualified lookup must not fall back to a fuzzy file
4354 // hit (#173); a bare name may use the single top fuzzy result.
4355 return isQualified ? [] : results[0] ? [results[0].node] : [];
4356 }
4357
4358 // Down-rank generated files (.pb.go, .pulsar.go, _grpc.pb.go, …) so a flow
4359 // query prefers the keeper implementation over the protobuf-generated stub.
4360 return [...exactMatches]
4361 .sort((a, b) => (isGeneratedFile(a.node.filePath) ? 1 : 0) - (isGeneratedFile(b.node.filePath) ? 1 : 0))
4362 .map((r) => r.node);
4363 }
4364
4365 /**
4366 * Find ALL symbols matching a name. Used by callers/callees/impact to aggregate

Callers 1

handleNodeMethod · 0.95

Calls 5

matchesSymbolMethod · 0.95
isGeneratedFileFunction · 0.90
lastQualifierPartFunction · 0.85
getNodesByNameMethod · 0.65
searchNodesMethod · 0.45

Tested by

no test coverage detected