Optimize reference resolution with in-memory caches

The resolving refs phase stalled on large projects (3400+ files, 38k+ nodes)
because matchFuzzy loaded ALL functions/methods/classes per ref, import
mappings were re-extracted per ref, and fileExists hit disk every call.

Add kindCache, lowerNameCache, importMappingCache, and knownFiles set to
warmCaches(). Rewrite matchFuzzy to use O(1) lowercase index lookup instead
of 3x getNodesByKind scans. Cache import mappings per file. Pre-build file
existence set from the index for O(1) fileExists checks.
This commit is contained in:
Colby McHenry
2026-02-10 18:14:26 -06:00
parent df937ceca1
commit acd9713632
4 changed files with 82 additions and 33 deletions
+8 -27
View File
@@ -197,43 +197,24 @@ export function matchFuzzy(
ref: UnresolvedRef,
context: ResolutionContext
): ResolvedRef | null {
// Try case-insensitive match
const allNodes = [
...context.getNodesByKind('function'),
...context.getNodesByKind('method'),
...context.getNodesByKind('class'),
];
const lowerName = ref.referenceName.toLowerCase();
// Exact case-insensitive match
const caseInsensitive = allNodes.filter(
(n) => n.name.toLowerCase() === lowerName
);
// Use pre-built lowercase index for O(1) lookup instead of scanning all nodes
const candidates = context.getNodesByLowerName(lowerName);
if (caseInsensitive.length === 1) {
// Filter to callable kinds only (function, method, class)
const callableKinds = new Set(['function', 'method', 'class']);
const callableCandidates = candidates.filter((n) => callableKinds.has(n.kind));
if (callableCandidates.length === 1) {
return {
original: ref,
targetNodeId: caseInsensitive[0]!.id,
targetNodeId: callableCandidates[0]!.id,
confidence: 0.5,
resolvedBy: 'fuzzy',
};
}
// Try prefix match (e.g., "get" matches "getUser")
const prefixMatches = allNodes.filter((n) =>
n.name.toLowerCase().startsWith(lowerName)
);
if (prefixMatches.length === 1) {
return {
original: ref,
targetNodeId: prefixMatches[0]!.id,
confidence: 0.3,
resolvedBy: 'fuzzy',
};
}
return null;
}