( ref: UnresolvedRef, context: ResolutionContext )
| 2148 | * Fuzzy match - last resort with lower confidence |
| 2149 | */ |
| 2150 | export function matchFuzzy( |
| 2151 | ref: UnresolvedRef, |
| 2152 | context: ResolutionContext |
| 2153 | ): ResolvedRef | null { |
| 2154 | const lowerName = ref.referenceName.toLowerCase(); |
| 2155 | |
| 2156 | // Use pre-built lowercase index for O(1) lookup instead of scanning all nodes |
| 2157 | const candidates = context.getNodesByLowerName(lowerName); |
| 2158 | |
| 2159 | // Filter to callable kinds only (function, method, class) |
| 2160 | const callableKinds = new Set(['function', 'method', 'class']); |
| 2161 | const callableCandidates = applyLanguageGate(candidates.filter((n) => callableKinds.has(n.kind)), ref); |
| 2162 | |
| 2163 | // Prefer same-language matches |
| 2164 | const sameLanguageCandidates = callableCandidates.filter(n => n.language === ref.language); |
| 2165 | const finalCandidates = sameLanguageCandidates.length > 0 ? sameLanguageCandidates : callableCandidates; |
| 2166 | |
| 2167 | if (finalCandidates.length === 1) { |
| 2168 | const isCrossLanguage = finalCandidates[0]!.language !== ref.language; |
| 2169 | return { |
| 2170 | original: ref, |
| 2171 | targetNodeId: finalCandidates[0]!.id, |
| 2172 | confidence: isCrossLanguage ? 0.3 : 0.5, |
| 2173 | resolvedBy: 'fuzzy', |
| 2174 | }; |
| 2175 | } |
| 2176 | |
| 2177 | return null; |
| 2178 | } |
| 2179 | |
| 2180 | /** |
| 2181 | * Match all strategies in order of confidence |
no test coverage detected