lsp-intelligence 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/README.md +48 -15
  2. package/dist/analysis/pattern/collectSearchFiles.d.ts +6 -0
  3. package/dist/analysis/pattern/collectSearchFiles.js +38 -0
  4. package/dist/analysis/pattern/collectSearchFiles.js.map +1 -0
  5. package/dist/analysis/pattern/runPatternSearch.d.ts +17 -0
  6. package/dist/analysis/pattern/runPatternSearch.js +65 -0
  7. package/dist/analysis/pattern/runPatternSearch.js.map +1 -0
  8. package/dist/analysis/ts/extractDeclarations.d.ts +7 -0
  9. package/dist/analysis/ts/extractDeclarations.js +93 -0
  10. package/dist/analysis/ts/extractDeclarations.js.map +1 -0
  11. package/dist/analysis/ts/extractUsages.d.ts +7 -0
  12. package/dist/analysis/ts/extractUsages.js +139 -0
  13. package/dist/analysis/ts/extractUsages.js.map +1 -0
  14. package/dist/analysis/ts/parseSourceFile.d.ts +11 -0
  15. package/dist/analysis/ts/parseSourceFile.js +24 -0
  16. package/dist/analysis/ts/parseSourceFile.js.map +1 -0
  17. package/dist/analysis/ts/reactState.d.ts +9 -0
  18. package/dist/analysis/ts/reactState.js +57 -0
  19. package/dist/analysis/ts/reactState.js.map +1 -0
  20. package/dist/analysis/ts/snippets.d.ts +14 -0
  21. package/dist/analysis/ts/snippets.js +29 -0
  22. package/dist/analysis/ts/snippets.js.map +1 -0
  23. package/dist/analysis/ts/structuralPredicates.d.ts +10 -0
  24. package/dist/analysis/ts/structuralPredicates.js +199 -0
  25. package/dist/analysis/ts/structuralPredicates.js.map +1 -0
  26. package/dist/ast/diffDeclarationShapes.d.ts +16 -0
  27. package/dist/ast/diffDeclarationShapes.js +179 -0
  28. package/dist/ast/diffDeclarationShapes.js.map +1 -0
  29. package/dist/ast/extractExportDeclarations.d.ts +21 -0
  30. package/dist/ast/extractExportDeclarations.js +218 -0
  31. package/dist/ast/extractExportDeclarations.js.map +1 -0
  32. package/dist/ast/findNodeAtPosition.d.ts +12 -0
  33. package/dist/ast/findNodeAtPosition.js +75 -0
  34. package/dist/ast/findNodeAtPosition.js.map +1 -0
  35. package/dist/ast/parseFile.d.ts +11 -0
  36. package/dist/ast/parseFile.js +46 -0
  37. package/dist/ast/parseFile.js.map +1 -0
  38. package/dist/engine/LspEngine.js +23 -1
  39. package/dist/engine/LspEngine.js.map +1 -1
  40. package/dist/engine/waitForDiagnostics.d.ts +7 -0
  41. package/dist/engine/waitForDiagnostics.js +16 -0
  42. package/dist/engine/waitForDiagnostics.js.map +1 -0
  43. package/dist/git/getBaseFileContent.d.ts +6 -0
  44. package/dist/git/getBaseFileContent.js +23 -0
  45. package/dist/git/getBaseFileContent.js.map +1 -0
  46. package/dist/git/getChangedFiles.d.ts +5 -0
  47. package/dist/git/getChangedFiles.js +27 -0
  48. package/dist/git/getChangedFiles.js.map +1 -0
  49. package/dist/git/getChangedHunks.d.ts +14 -0
  50. package/dist/git/getChangedHunks.js +56 -0
  51. package/dist/git/getChangedHunks.js.map +1 -0
  52. package/dist/git/getGitRoot.d.ts +15 -0
  53. package/dist/git/getGitRoot.js +33 -0
  54. package/dist/git/getGitRoot.js.map +1 -0
  55. package/dist/git/getMergeBase.d.ts +5 -0
  56. package/dist/git/getMergeBase.js +23 -0
  57. package/dist/git/getMergeBase.js.map +1 -0
  58. package/dist/index.js +10 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/resolve/searchScope.d.ts +17 -0
  61. package/dist/resolve/searchScope.js +64 -0
  62. package/dist/resolve/searchScope.js.map +1 -0
  63. package/dist/resolve/targetResolver.d.ts +33 -0
  64. package/dist/resolve/targetResolver.js +84 -0
  65. package/dist/resolve/targetResolver.js.map +1 -0
  66. package/dist/search/adapters/config.d.ts +5 -0
  67. package/dist/search/adapters/config.js +56 -0
  68. package/dist/search/adapters/config.js.map +1 -0
  69. package/dist/search/adapters/http.d.ts +6 -0
  70. package/dist/search/adapters/http.js +58 -0
  71. package/dist/search/adapters/http.js.map +1 -0
  72. package/dist/search/adapters/react.d.ts +12 -0
  73. package/dist/search/adapters/react.js +92 -0
  74. package/dist/search/adapters/react.js.map +1 -0
  75. package/dist/search/adapters/registry.d.ts +6 -0
  76. package/dist/search/adapters/registry.js +20 -0
  77. package/dist/search/adapters/registry.js.map +1 -0
  78. package/dist/search/adapters/types.d.ts +5 -0
  79. package/dist/search/adapters/types.js +2 -0
  80. package/dist/search/adapters/types.js.map +1 -0
  81. package/dist/search/debug/trace.d.ts +6 -0
  82. package/dist/search/debug/trace.js +25 -0
  83. package/dist/search/debug/trace.js.map +1 -0
  84. package/dist/search/expand/graphExpansion.d.ts +16 -0
  85. package/dist/search/expand/graphExpansion.js +168 -0
  86. package/dist/search/expand/graphExpansion.js.map +1 -0
  87. package/dist/search/families/behaviorFamilies.d.ts +22 -0
  88. package/dist/search/families/behaviorFamilies.js +90 -0
  89. package/dist/search/families/behaviorFamilies.js.map +1 -0
  90. package/dist/search/fileKinds.d.ts +13 -0
  91. package/dist/search/fileKinds.js +74 -0
  92. package/dist/search/fileKinds.js.map +1 -0
  93. package/dist/search/index/configIndex.d.ts +6 -0
  94. package/dist/search/index/configIndex.js +196 -0
  95. package/dist/search/index/configIndex.js.map +1 -0
  96. package/dist/search/index/declarationIndex.d.ts +6 -0
  97. package/dist/search/index/declarationIndex.js +13 -0
  98. package/dist/search/index/declarationIndex.js.map +1 -0
  99. package/dist/search/index/docIndex.d.ts +7 -0
  100. package/dist/search/index/docIndex.js +116 -0
  101. package/dist/search/index/docIndex.js.map +1 -0
  102. package/dist/search/index/types.d.ts +1 -0
  103. package/dist/search/index/types.js +2 -0
  104. package/dist/search/index/types.js.map +1 -0
  105. package/dist/search/index/usageIndex.d.ts +6 -0
  106. package/dist/search/index/usageIndex.js +13 -0
  107. package/dist/search/index/usageIndex.js.map +1 -0
  108. package/dist/search/index/workspaceIndex.d.ts +14 -0
  109. package/dist/search/index/workspaceIndex.js +127 -0
  110. package/dist/search/index/workspaceIndex.js.map +1 -0
  111. package/dist/search/query/compileEffectiveSearchSpec.d.ts +24 -0
  112. package/dist/search/query/compileEffectiveSearchSpec.js +67 -0
  113. package/dist/search/query/compileEffectiveSearchSpec.js.map +1 -0
  114. package/dist/search/query/parseQuery.d.ts +10 -0
  115. package/dist/search/query/parseQuery.js +284 -0
  116. package/dist/search/query/parseQuery.js.map +1 -0
  117. package/dist/search/query/phraseRules.d.ts +10 -0
  118. package/dist/search/query/phraseRules.js +58 -0
  119. package/dist/search/query/phraseRules.js.map +1 -0
  120. package/dist/search/query/planQuery.d.ts +10 -0
  121. package/dist/search/query/planQuery.js +91 -0
  122. package/dist/search/query/planQuery.js.map +1 -0
  123. package/dist/search/ranking/assessConfidence.d.ts +6 -0
  124. package/dist/search/ranking/assessConfidence.js +31 -0
  125. package/dist/search/ranking/assessConfidence.js.map +1 -0
  126. package/dist/search/ranking/candidateIdentity.d.ts +21 -0
  127. package/dist/search/ranking/candidateIdentity.js +29 -0
  128. package/dist/search/ranking/candidateIdentity.js.map +1 -0
  129. package/dist/search/ranking/coalesceCandidates.d.ts +9 -0
  130. package/dist/search/ranking/coalesceCandidates.js +48 -0
  131. package/dist/search/ranking/coalesceCandidates.js.map +1 -0
  132. package/dist/search/ranking/fieldedTextRanker.d.ts +26 -0
  133. package/dist/search/ranking/fieldedTextRanker.js +79 -0
  134. package/dist/search/ranking/fieldedTextRanker.js.map +1 -0
  135. package/dist/search/ranking/mergeCandidates.d.ts +13 -0
  136. package/dist/search/ranking/mergeCandidates.js +85 -0
  137. package/dist/search/ranking/mergeCandidates.js.map +1 -0
  138. package/dist/search/ranking/rankCandidates.d.ts +12 -0
  139. package/dist/search/ranking/rankCandidates.js +106 -0
  140. package/dist/search/ranking/rankCandidates.js.map +1 -0
  141. package/dist/search/retrievers/behaviorRetriever.d.ts +7 -0
  142. package/dist/search/retrievers/behaviorRetriever.js +86 -0
  143. package/dist/search/retrievers/behaviorRetriever.js.map +1 -0
  144. package/dist/search/retrievers/configRetriever.d.ts +7 -0
  145. package/dist/search/retrievers/configRetriever.js +46 -0
  146. package/dist/search/retrievers/configRetriever.js.map +1 -0
  147. package/dist/search/retrievers/docRetriever.d.ts +7 -0
  148. package/dist/search/retrievers/docRetriever.js +46 -0
  149. package/dist/search/retrievers/docRetriever.js.map +1 -0
  150. package/dist/search/retrievers/identifierRetriever.d.ts +7 -0
  151. package/dist/search/retrievers/identifierRetriever.js +67 -0
  152. package/dist/search/retrievers/identifierRetriever.js.map +1 -0
  153. package/dist/search/retrievers/structuralRetriever.d.ts +9 -0
  154. package/dist/search/retrievers/structuralRetriever.js +104 -0
  155. package/dist/search/retrievers/structuralRetriever.js.map +1 -0
  156. package/dist/search/retrievers/textPatternRetriever.d.ts +7 -0
  157. package/dist/search/retrievers/textPatternRetriever.js +90 -0
  158. package/dist/search/retrievers/textPatternRetriever.js.map +1 -0
  159. package/dist/search/structural/locators/callLocator.d.ts +6 -0
  160. package/dist/search/structural/locators/callLocator.js +57 -0
  161. package/dist/search/structural/locators/callLocator.js.map +1 -0
  162. package/dist/search/structural/locators/declarationLocator.d.ts +6 -0
  163. package/dist/search/structural/locators/declarationLocator.js +57 -0
  164. package/dist/search/structural/locators/declarationLocator.js.map +1 -0
  165. package/dist/search/structural/locators/statementLocator.d.ts +6 -0
  166. package/dist/search/structural/locators/statementLocator.js +65 -0
  167. package/dist/search/structural/locators/statementLocator.js.map +1 -0
  168. package/dist/search/structural/locators/types.d.ts +12 -0
  169. package/dist/search/structural/locators/types.js +2 -0
  170. package/dist/search/structural/locators/types.js.map +1 -0
  171. package/dist/search/structural/selectLocators.d.ts +7 -0
  172. package/dist/search/structural/selectLocators.js +21 -0
  173. package/dist/search/structural/selectLocators.js.map +1 -0
  174. package/dist/search/types.d.ts +191 -0
  175. package/dist/search/types.js +11 -0
  176. package/dist/search/types.js.map +1 -0
  177. package/dist/tools/composites/apiGuard.d.ts +1 -0
  178. package/dist/tools/composites/apiGuard.js +172 -0
  179. package/dist/tools/composites/apiGuard.js.map +1 -0
  180. package/dist/tools/composites/explainError.js +3 -2
  181. package/dist/tools/composites/explainError.js.map +1 -1
  182. package/dist/tools/composites/findCode.d.ts +1 -0
  183. package/dist/tools/composites/findCode.js +145 -0
  184. package/dist/tools/composites/findCode.js.map +1 -0
  185. package/dist/tools/composites/findPattern.d.ts +5 -0
  186. package/dist/tools/composites/findPattern.js +41 -0
  187. package/dist/tools/composites/findPattern.js.map +1 -0
  188. package/dist/tools/composites/rootCauseTrace.d.ts +1 -0
  189. package/dist/tools/composites/rootCauseTrace.js +213 -0
  190. package/dist/tools/composites/rootCauseTrace.js.map +1 -0
  191. package/dist/tools/composites/semanticDiff.js +24 -77
  192. package/dist/tools/composites/semanticDiff.js.map +1 -1
  193. package/dist/tools/live/clearIndex.d.ts +1 -0
  194. package/dist/tools/live/clearIndex.js +19 -0
  195. package/dist/tools/live/clearIndex.js.map +1 -0
  196. package/dist/tools/live/liveDiagnostics.js +3 -2
  197. package/dist/tools/live/liveDiagnostics.js.map +1 -1
  198. package/dist/tools/primitives/callHierarchy.js +1 -1
  199. package/dist/tools/primitives/callHierarchy.js.map +1 -1
  200. package/dist/tools/primitives/diagnostics.js +2 -2
  201. package/dist/tools/primitives/diagnostics.js.map +1 -1
  202. package/dist/tools/registry.d.ts +10 -2
  203. package/dist/tools/registry.js +7 -2
  204. package/dist/tools/registry.js.map +1 -1
  205. package/package.json +11 -5
  206. package/dist/tools/primitives/typeHierarchy.d.ts +0 -1
  207. package/dist/tools/primitives/typeHierarchy.js +0 -55
  208. package/dist/tools/primitives/typeHierarchy.js.map +0 -1
@@ -0,0 +1,67 @@
1
+ import { buildSnippetFromFile } from '../../analysis/ts/snippets.js';
2
+ /**
3
+ * Retrieve usage-oriented candidates based on exact identifier matching.
4
+ * Uses the compiled spec's identifiers (merged from parser + recipes).
5
+ */
6
+ export function retrieveIdentifierCandidates(ir, scope, index, spec) {
7
+ const candidates = [];
8
+ const exactIds = spec?.exactIdentifiers ?? ir.exactIdentifiers;
9
+ const dottedIds = spec?.dottedIdentifiers ?? ir.dottedIdentifiers;
10
+ if (exactIds.length === 0 && dottedIds.length === 0)
11
+ return [];
12
+ for (const usage of index.usages) {
13
+ let score = 0;
14
+ const evidence = [];
15
+ // Exact identifier match
16
+ for (const id of exactIds) {
17
+ if (usage.identifier === id || usage.normalizedIdentifier === id) {
18
+ score += 10;
19
+ evidence.push(`exact-identifier: ${id}`);
20
+ }
21
+ }
22
+ // Dotted identifier match (Promise.all, React.useEffect)
23
+ for (const id of dottedIds) {
24
+ if (usage.identifier === id) {
25
+ score += 10;
26
+ evidence.push(`dotted-identifier: ${id}`);
27
+ }
28
+ else if (usage.identifier.endsWith(id.split('.').pop() ?? '')) {
29
+ score += 5;
30
+ evidence.push(`dotted-partial: ${id}`);
31
+ }
32
+ }
33
+ if (score === 0)
34
+ continue;
35
+ // Usage kind bonus
36
+ if (usage.kind === 'call' || usage.kind === 'member-call') {
37
+ score += 2;
38
+ evidence.push(`usage-kind: ${usage.kind}`);
39
+ }
40
+ else if (usage.kind === 'import') {
41
+ score += 1;
42
+ evidence.push('usage-kind: import');
43
+ }
44
+ // Enclosing symbol context
45
+ if (usage.enclosingSymbol) {
46
+ evidence.push(`enclosing: ${usage.enclosingSymbol}`);
47
+ }
48
+ const { snippet, context } = buildSnippetFromFile(usage.filePath, usage.line, 1);
49
+ candidates.push({
50
+ candidateType: 'usage',
51
+ filePath: usage.filePath,
52
+ line: usage.line,
53
+ column: usage.column,
54
+ matchedIdentifier: usage.identifier,
55
+ enclosingSymbol: usage.enclosingSymbol,
56
+ enclosingKind: usage.enclosingKind,
57
+ kind: 'usage',
58
+ snippet,
59
+ context,
60
+ score,
61
+ evidence,
62
+ sources: ['identifier'],
63
+ });
64
+ }
65
+ return candidates.sort((a, b) => b.score - a.score);
66
+ }
67
+ //# sourceMappingURL=identifierRetriever.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identifierRetriever.js","sourceRoot":"","sources":["../../../src/search/retrievers/identifierRetriever.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { QueryIR, SearchScope, WorkspaceIndex, CodeCandidate } from '../types.js';
2
+ import type { EffectiveSearchSpec } from '../query/compileEffectiveSearchSpec.js';
3
+ /**
4
+ * Retrieve candidates using structural predicate evaluation.
5
+ *
6
+ * When an EffectiveSearchSpec is provided, uses its merged predicates/identifiers
7
+ * (which include recipe contributions). Falls back to raw IR otherwise.
8
+ */
9
+ export declare function retrieveStructuralCandidates(ir: QueryIR, scope: SearchScope, index: WorkspaceIndex, spec?: EffectiveSearchSpec): CodeCandidate[];
@@ -0,0 +1,104 @@
1
+ import { parseSourceFile } from '../../analysis/ts/parseSourceFile.js';
2
+ import { evaluateStructuralPredicates } from '../../analysis/ts/structuralPredicates.js';
3
+ import { buildSnippetFromFile } from '../../analysis/ts/snippets.js';
4
+ import { selectLocators } from '../structural/selectLocators.js';
5
+ import ts from 'typescript';
6
+ /**
7
+ * Retrieve candidates using structural predicate evaluation.
8
+ *
9
+ * When an EffectiveSearchSpec is provided, uses its merged predicates/identifiers
10
+ * (which include recipe contributions). Falls back to raw IR otherwise.
11
+ */
12
+ export function retrieveStructuralCandidates(ir, scope, index, spec) {
13
+ const predicates = spec?.structuralPredicates ?? ir.structuralPredicates;
14
+ const exactIds = spec?.exactIdentifiers ?? ir.exactIdentifiers;
15
+ const dottedIds = spec?.dottedIdentifiers ?? ir.dottedIdentifiers;
16
+ if (predicates.length === 0)
17
+ return [];
18
+ const candidates = [];
19
+ const maxFiles = 80;
20
+ let filesChecked = 0;
21
+ const locators = selectLocators(ir);
22
+ if (locators.length === 0)
23
+ return [];
24
+ // Determine which files to check
25
+ const targetFiles = new Set();
26
+ if (exactIds.length > 0 || dottedIds.length > 0) {
27
+ // If we have identifiers, only check files with matching usages
28
+ const allIds = [...exactIds, ...dottedIds];
29
+ for (const usage of index.usages) {
30
+ if (allIds.some((id) => usage.identifier === id || usage.normalizedIdentifier === id)) {
31
+ targetFiles.add(usage.filePath);
32
+ }
33
+ }
34
+ }
35
+ else {
36
+ // No specific identifier — check indexed files (capped)
37
+ for (const file of index.files.keys()) {
38
+ targetFiles.add(file);
39
+ if (targetFiles.size >= maxFiles)
40
+ break;
41
+ }
42
+ }
43
+ // For each file, run all selected locators and evaluate predicates
44
+ for (const filePath of targetFiles) {
45
+ if (filesChecked >= maxFiles)
46
+ break;
47
+ filesChecked++;
48
+ const sf = parseSourceFile(filePath);
49
+ if (!sf)
50
+ continue;
51
+ for (const locator of locators) {
52
+ const nodes = locator.locate(sf, ir);
53
+ for (const { node, identifier, line } of nodes) {
54
+ const { matched, evidence } = evaluateStructuralPredicates(sf, node, predicates);
55
+ if (matched.length === 0)
56
+ continue;
57
+ const score = matched.length * 5 + (matched.length === predicates.length ? 5 : 0);
58
+ const { snippet, context } = buildSnippetFromFile(filePath, line, 2);
59
+ const enclosing = findEnclosingDeclaration(node);
60
+ candidates.push({
61
+ candidateType: 'usage',
62
+ filePath,
63
+ line,
64
+ column: sf.getLineAndCharacterOfPosition(node.getStart(sf)).character,
65
+ matchedIdentifier: identifier,
66
+ enclosingSymbol: enclosing?.name,
67
+ enclosingKind: enclosing?.kind,
68
+ kind: 'usage',
69
+ snippet,
70
+ context,
71
+ score,
72
+ evidence: [
73
+ `structural-match: ${matched.join(', ')}`,
74
+ `predicates: ${matched.length}/${ir.structuralPredicates.length}`,
75
+ `locator: ${locator.kind}`,
76
+ ...evidence,
77
+ ],
78
+ sources: ['structural'],
79
+ });
80
+ }
81
+ }
82
+ }
83
+ return candidates.sort((a, b) => b.score - a.score);
84
+ }
85
+ function findEnclosingDeclaration(node) {
86
+ let current = node.parent;
87
+ while (current) {
88
+ if (ts.isFunctionDeclaration(current) && current.name) {
89
+ return { name: current.name.text, kind: 'function' };
90
+ }
91
+ if (ts.isVariableDeclaration(current) && ts.isIdentifier(current.name)) {
92
+ return { name: current.name.text, kind: 'variable' };
93
+ }
94
+ if (ts.isMethodDeclaration(current) && ts.isIdentifier(current.name)) {
95
+ return { name: current.name.text, kind: 'method' };
96
+ }
97
+ if (ts.isClassDeclaration(current) && current.name) {
98
+ return { name: current.name.text, kind: 'class' };
99
+ }
100
+ current = current.parent;
101
+ }
102
+ return undefined;
103
+ }
104
+ //# sourceMappingURL=structuralRetriever.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structuralRetriever.js","sourceRoot":"","sources":["../../../src/search/retrievers/structuralRetriever.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { QueryIR, SearchScope, WorkspaceIndex, CodeCandidate } from '../types.js';
2
+ import type { EffectiveSearchSpec } from '../query/compileEffectiveSearchSpec.js';
3
+ /**
4
+ * Retrieve candidates by running compiled regex specs over scoped files.
5
+ * Uses the compiled spec's merged regexes (from all adapter recipes).
6
+ */
7
+ export declare function retrieveTextPatternCandidates(ir: QueryIR, scope: SearchScope, index: WorkspaceIndex, spec?: EffectiveSearchSpec): CodeCandidate[];
@@ -0,0 +1,90 @@
1
+ import * as fs from 'fs';
2
+ import { buildSnippetFromFile } from '../../analysis/ts/snippets.js';
3
+ /**
4
+ * Retrieve candidates by running compiled regex specs over scoped files.
5
+ * Uses the compiled spec's merged regexes (from all adapter recipes).
6
+ */
7
+ export function retrieveTextPatternCandidates(ir, scope, index, spec) {
8
+ // Use compiled spec regexes if available, otherwise collect from raw recipes
9
+ const regexSpecs = spec?.regexes ?? [];
10
+ if (regexSpecs.length === 0) {
11
+ for (const recipe of ir.recipes) {
12
+ if (recipe.regexes)
13
+ regexSpecs.push(...recipe.regexes);
14
+ }
15
+ }
16
+ if (regexSpecs.length === 0)
17
+ return [];
18
+ const compiled = regexSpecs.map((spec) => ({
19
+ spec,
20
+ regex: new RegExp(spec.pattern, spec.flags ?? 'g'),
21
+ }));
22
+ const candidates = [];
23
+ const maxFiles = 200;
24
+ let filesChecked = 0;
25
+ for (const [filePath] of index.files) {
26
+ if (filesChecked >= maxFiles)
27
+ break;
28
+ filesChecked++;
29
+ let content;
30
+ try {
31
+ content = fs.readFileSync(filePath, 'utf-8');
32
+ }
33
+ catch {
34
+ continue;
35
+ }
36
+ const lines = content.split('\n');
37
+ for (const { spec, regex } of compiled) {
38
+ // Reset regex state
39
+ regex.lastIndex = 0;
40
+ let match;
41
+ while ((match = regex.exec(content)) !== null) {
42
+ // Find the line number of this match
43
+ let charCount = 0;
44
+ let lineNum = 1;
45
+ for (let i = 0; i < lines.length; i++) {
46
+ charCount += lines[i].length + 1; // +1 for newline
47
+ if (charCount > match.index) {
48
+ lineNum = i + 1;
49
+ break;
50
+ }
51
+ }
52
+ const { snippet, context } = buildSnippetFromFile(filePath, lineNum, 1);
53
+ const enclosing = findEnclosingFunctionName(lines, lineNum - 1);
54
+ candidates.push({
55
+ candidateType: 'pattern',
56
+ filePath,
57
+ line: lineNum,
58
+ symbol: enclosing,
59
+ matchedIdentifier: spec.id,
60
+ kind: 'pattern',
61
+ snippet,
62
+ context,
63
+ score: 6, // Base score for regex match
64
+ evidence: [`regex-match: ${spec.id}`, `pattern: ${spec.pattern.substring(0, 60)}`],
65
+ sources: ['identifier'], // Counts as identifier-like evidence
66
+ });
67
+ // Limit matches per file
68
+ if (candidates.length > 500)
69
+ break;
70
+ }
71
+ }
72
+ }
73
+ return candidates.sort((a, b) => b.score - a.score);
74
+ }
75
+ /** Simple heuristic to find enclosing function name by scanning backwards. */
76
+ function findEnclosingFunctionName(lines, fromLine) {
77
+ for (let i = fromLine; i >= Math.max(0, fromLine - 15); i--) {
78
+ const line = lines[i];
79
+ // function foo(
80
+ const funcMatch = line.match(/(?:export\s+)?(?:async\s+)?function\s+(\w+)/);
81
+ if (funcMatch)
82
+ return funcMatch[1];
83
+ // const foo = (
84
+ const arrowMatch = line.match(/(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=/);
85
+ if (arrowMatch && (line.includes('=>') || line.includes('function')))
86
+ return arrowMatch[1];
87
+ }
88
+ return undefined;
89
+ }
90
+ //# sourceMappingURL=textPatternRetriever.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textPatternRetriever.js","sourceRoot":"","sources":["../../../src/search/retrievers/textPatternRetriever.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { StructuralLocator } from './types.js';
2
+ /**
3
+ * Locates call expression nodes — the original structural retriever path.
4
+ * Best for: useEffect, Promise.all, hook/API usage shapes.
5
+ */
6
+ export declare const callLocator: StructuralLocator;
@@ -0,0 +1,57 @@
1
+ import ts from 'typescript';
2
+ const CALL_PREDICATES = new Set([
3
+ 'returns-cleanup', 'no-cleanup', 'returns-function',
4
+ 'hook-callback', 'inside-hook', 'conditional',
5
+ ]);
6
+ /**
7
+ * Locates call expression nodes — the original structural retriever path.
8
+ * Best for: useEffect, Promise.all, hook/API usage shapes.
9
+ */
10
+ export const callLocator = {
11
+ kind: 'call',
12
+ supports(predicates, ir) {
13
+ // Supports if we have identifiers to match, or call-centric predicates
14
+ if (ir.exactIdentifiers.length > 0 || ir.dottedIdentifiers.length > 0)
15
+ return true;
16
+ return predicates.some((p) => CALL_PREDICATES.has(p));
17
+ },
18
+ locate(sf, ir) {
19
+ const nodes = [];
20
+ const allIds = [...ir.exactIdentifiers, ...ir.dottedIdentifiers];
21
+ function visit(node) {
22
+ if (ts.isCallExpression(node)) {
23
+ const expr = node.expression;
24
+ let name = null;
25
+ if (ts.isIdentifier(expr)) {
26
+ name = expr.text;
27
+ }
28
+ else if (ts.isPropertyAccessExpression(expr)) {
29
+ name = getFullPropertyAccess(expr);
30
+ }
31
+ if (name) {
32
+ const matches = allIds.length === 0 ||
33
+ allIds.some((id) => name === id || name.endsWith(`.${id}`));
34
+ if (matches) {
35
+ const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
36
+ nodes.push({ node, identifier: name, line });
37
+ }
38
+ }
39
+ }
40
+ ts.forEachChild(node, visit);
41
+ }
42
+ visit(sf);
43
+ return nodes;
44
+ },
45
+ };
46
+ function getFullPropertyAccess(node) {
47
+ const parts = [node.name.text];
48
+ let current = node.expression;
49
+ while (ts.isPropertyAccessExpression(current)) {
50
+ parts.unshift(current.name.text);
51
+ current = current.expression;
52
+ }
53
+ if (ts.isIdentifier(current))
54
+ parts.unshift(current.text);
55
+ return parts.join('.');
56
+ }
57
+ //# sourceMappingURL=callLocator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callLocator.js","sourceRoot":"","sources":["../../../../src/search/structural/locators/callLocator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,MAAM,eAAe,GAA6B,IAAI,GAAG,CAAC;IACxD,iBAAiB,EAAE,YAAY,EAAE,kBAAkB;IACnD,eAAe,EAAE,aAAa,EAAE,aAAa;CAC9C,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAsB;IAC5C,IAAI,EAAE,MAAM;IAEZ,QAAQ,CAAC,UAAU,EAAE,EAAE;QACrB,uEAAuE;QACvE,IAAI,EAAE,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACnF,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,CAAC,EAAE,EAAE,EAAE;QACX,MAAM,KAAK,GAAkB,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC;QAEjE,SAAS,KAAK,CAAC,IAAa;YAC1B,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;gBAC7B,IAAI,IAAI,GAAkB,IAAI,CAAC;gBAE/B,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC1B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;gBACnB,CAAC;qBAAM,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/C,IAAI,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;gBACrC,CAAC;gBAED,IAAI,IAAI,EAAE,CAAC;oBACT,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC;wBACjC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,IAAI,IAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;oBAC/D,IAAI,OAAO,EAAE,CAAC;wBACZ,MAAM,IAAI,GAAG,EAAE,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;wBAC1E,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC/C,CAAC;gBACH,CAAC;YACH,CAAC;YACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,CAAC,EAAE,CAAC,CAAC;QACV,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAC;AAEF,SAAS,qBAAqB,CAAC,IAAiC;IAC9D,MAAM,KAAK,GAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,OAAO,GAAkB,IAAI,CAAC,UAAU,CAAC;IAC7C,OAAO,EAAE,CAAC,0BAA0B,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAC/B,CAAC;IACD,IAAI,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC;QAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { StructuralLocator } from './types.js';
2
+ /**
3
+ * Locates function/method declarations for structural filtering.
4
+ * Best for: "async function without try/catch", declaration-shaped queries.
5
+ */
6
+ export declare const declarationLocator: StructuralLocator;
@@ -0,0 +1,57 @@
1
+ import ts from 'typescript';
2
+ const DECLARATION_PREDICATES = new Set([
3
+ 'no-try-catch', 'returns-function',
4
+ ]);
5
+ /**
6
+ * Locates function/method declarations for structural filtering.
7
+ * Best for: "async function without try/catch", declaration-shaped queries.
8
+ */
9
+ export const declarationLocator = {
10
+ kind: 'declaration',
11
+ supports(predicates, ir) {
12
+ // Only use when no identifiers and predicates apply to declarations
13
+ if (ir.exactIdentifiers.length > 0)
14
+ return false;
15
+ return predicates.some((p) => DECLARATION_PREDICATES.has(p));
16
+ },
17
+ locate(sf, ir) {
18
+ const nodes = [];
19
+ const isAsync = ir.codeTokens.includes('async');
20
+ function visit(node) {
21
+ if (ts.isFunctionDeclaration(node) && node.name && node.body) {
22
+ // Filter to async if query mentions async
23
+ if (isAsync && !node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) {
24
+ ts.forEachChild(node, visit);
25
+ return;
26
+ }
27
+ const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
28
+ nodes.push({ node, identifier: node.name.text, line });
29
+ }
30
+ // Arrow functions / function expressions assigned to variables
31
+ if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) {
32
+ const init = node.initializer;
33
+ if (ts.isArrowFunction(init) || ts.isFunctionExpression(init)) {
34
+ if (isAsync && !init.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) {
35
+ ts.forEachChild(node, visit);
36
+ return;
37
+ }
38
+ const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
39
+ nodes.push({ node: init, identifier: node.name.text, line });
40
+ }
41
+ }
42
+ // Methods
43
+ if (ts.isMethodDeclaration(node) && ts.isIdentifier(node.name) && node.body) {
44
+ if (isAsync && !node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) {
45
+ ts.forEachChild(node, visit);
46
+ return;
47
+ }
48
+ const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
49
+ nodes.push({ node, identifier: node.name.text, line });
50
+ }
51
+ ts.forEachChild(node, visit);
52
+ }
53
+ visit(sf);
54
+ return nodes;
55
+ },
56
+ };
57
+ //# sourceMappingURL=declarationLocator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declarationLocator.js","sourceRoot":"","sources":["../../../../src/search/structural/locators/declarationLocator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { StructuralLocator } from './types.js';
2
+ /**
3
+ * Locates statement-level nodes — switch, try/catch, loops with await.
4
+ * Best for: "switch without default", "await inside loop", "async without try/catch".
5
+ */
6
+ export declare const statementLocator: StructuralLocator;
@@ -0,0 +1,65 @@
1
+ import ts from 'typescript';
2
+ const STATEMENT_PREDICATES = new Set([
3
+ 'switch-no-default', 'has-try-catch', 'no-try-catch', 'await-in-loop',
4
+ ]);
5
+ /**
6
+ * Locates statement-level nodes — switch, try/catch, loops with await.
7
+ * Best for: "switch without default", "await inside loop", "async without try/catch".
8
+ */
9
+ export const statementLocator = {
10
+ kind: 'statement',
11
+ supports(predicates) {
12
+ return predicates.some((p) => STATEMENT_PREDICATES.has(p));
13
+ },
14
+ locate(sf, ir) {
15
+ const nodes = [];
16
+ const targetPredicates = ir.structuralPredicates.filter((p) => STATEMENT_PREDICATES.has(p));
17
+ function visit(node) {
18
+ // Switch statements
19
+ if (ts.isSwitchStatement(node) && targetPredicates.includes('switch-no-default')) {
20
+ const hasDefault = node.caseBlock.clauses.some((c) => ts.isDefaultClause(c));
21
+ if (!hasDefault) {
22
+ const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
23
+ nodes.push({ node, identifier: 'switch', line });
24
+ }
25
+ }
26
+ // Try statements
27
+ if (ts.isTryStatement(node) && targetPredicates.includes('has-try-catch')) {
28
+ const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
29
+ nodes.push({ node, identifier: 'try-catch', line });
30
+ }
31
+ // Loops with await
32
+ if (isLoopStatement(node) && targetPredicates.includes('await-in-loop')) {
33
+ if (containsAwait(node)) {
34
+ const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
35
+ nodes.push({ node, identifier: 'await-in-loop', line });
36
+ }
37
+ }
38
+ ts.forEachChild(node, visit);
39
+ }
40
+ visit(sf);
41
+ return nodes;
42
+ },
43
+ };
44
+ function isLoopStatement(node) {
45
+ return ts.isForStatement(node) || ts.isForOfStatement(node) ||
46
+ ts.isForInStatement(node) || ts.isWhileStatement(node) || ts.isDoStatement(node);
47
+ }
48
+ function containsAwait(node) {
49
+ let found = false;
50
+ function walk(n) {
51
+ if (found)
52
+ return;
53
+ if (ts.isAwaitExpression(n)) {
54
+ found = true;
55
+ return;
56
+ }
57
+ // Don't descend into nested functions
58
+ if (ts.isFunctionDeclaration(n) || ts.isArrowFunction(n) || ts.isFunctionExpression(n))
59
+ return;
60
+ ts.forEachChild(n, walk);
61
+ }
62
+ ts.forEachChild(node, walk);
63
+ return found;
64
+ }
65
+ //# sourceMappingURL=statementLocator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statementLocator.js","sourceRoot":"","sources":["../../../../src/search/structural/locators/statementLocator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import ts from 'typescript';
2
+ import type { QueryIR, StructuralPredicate } from '../../types.js';
3
+ export interface LocatedNode {
4
+ node: ts.Node;
5
+ identifier?: string;
6
+ line: number;
7
+ }
8
+ export interface StructuralLocator {
9
+ kind: 'call' | 'statement' | 'declaration';
10
+ supports(predicates: StructuralPredicate[], ir: QueryIR): boolean;
11
+ locate(sf: ts.SourceFile, ir: QueryIR): LocatedNode[];
12
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/search/structural/locators/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import type { QueryIR } from '../types.js';
2
+ import type { StructuralLocator } from './locators/types.js';
3
+ /**
4
+ * Select which locators to use based on the query's structural predicates.
5
+ * May return multiple locators if the query spans call + statement shapes.
6
+ */
7
+ export declare function selectLocators(ir: QueryIR): StructuralLocator[];
@@ -0,0 +1,21 @@
1
+ import { callLocator } from './locators/callLocator.js';
2
+ import { statementLocator } from './locators/statementLocator.js';
3
+ import { declarationLocator } from './locators/declarationLocator.js';
4
+ const ALL_LOCATORS = [
5
+ callLocator,
6
+ statementLocator,
7
+ declarationLocator,
8
+ ];
9
+ /**
10
+ * Select which locators to use based on the query's structural predicates.
11
+ * May return multiple locators if the query spans call + statement shapes.
12
+ */
13
+ export function selectLocators(ir) {
14
+ const selected = ALL_LOCATORS.filter((l) => l.supports(ir.structuralPredicates, ir));
15
+ // Always include at least call locator if we have identifiers
16
+ if (selected.length === 0 && (ir.exactIdentifiers.length > 0 || ir.dottedIdentifiers.length > 0)) {
17
+ selected.push(callLocator);
18
+ }
19
+ return selected;
20
+ }
21
+ //# sourceMappingURL=selectLocators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectLocators.js","sourceRoot":"","sources":["../../../src/search/structural/selectLocators.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,MAAM,YAAY,GAAwB;IACxC,WAAW;IACX,gBAAgB;IAChB,kBAAkB;CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,EAAW;IACxC,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC,CAAC;IACrF,8DAA8D;IAC9D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QACjG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}