diff --git a/src/flow.js b/src/flow.js index 5260ae74..6c8fa559 100644 --- a/src/flow.js +++ b/src/flow.js @@ -7,7 +7,7 @@ import { openReadonlyOrFail } from './db.js'; import { paginateResult } from './paginate.js'; -import { findMatchingNodes, kindIcon } from './queries.js'; +import { CORE_SYMBOL_KINDS, findMatchingNodes, kindIcon } from './queries.js'; import { outputResult } from './result-formatter.js'; import { FRAMEWORK_ENTRY_PREFIXES } from './structure.js'; import { isTestFile } from './test-filter.js'; @@ -100,13 +100,15 @@ export function flowData(name, dbPath, opts = {}) { const maxDepth = opts.depth || 10; const noTests = opts.noTests || false; - // Phase 1: Direct LIKE match on full name - let matchNode = findMatchingNodes(db, name, opts)[0] ?? null; + // Phase 1: Direct LIKE match on full name (use all 10 core symbol kinds, + // not just FUNCTION_KINDS, so flow can trace from interfaces/types/structs/etc.) + const flowOpts = { ...opts, kinds: opts.kind ? [opts.kind] : CORE_SYMBOL_KINDS }; + let matchNode = findMatchingNodes(db, name, flowOpts)[0] ?? null; // Phase 2: Prefix-stripped matching — try adding framework prefixes if (!matchNode) { for (const prefix of FRAMEWORK_ENTRY_PREFIXES) { - matchNode = findMatchingNodes(db, `${prefix}${name}`, opts)[0] ?? null; + matchNode = findMatchingNodes(db, `${prefix}${name}`, flowOpts)[0] ?? null; if (matchNode) break; } } diff --git a/src/queries.js b/src/queries.js index 6dd02f83..a1f8094e 100644 --- a/src/queries.js +++ b/src/queries.js @@ -135,7 +135,7 @@ function resolveMethodViaHierarchy(db, methodName) { * Scoring: exact=100, prefix=60, word-boundary=40, substring=10, plus fan-in tiebreaker. */ export function findMatchingNodes(db, name, opts = {}) { - const kinds = opts.kind ? [opts.kind] : FUNCTION_KINDS; + const kinds = opts.kind ? [opts.kind] : opts.kinds?.length ? opts.kinds : FUNCTION_KINDS; const rows = findNodesWithFanIn(db, `%${name}%`, { kinds, file: opts.file });