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,57 @@
1
+ import ts from 'typescript';
2
+ /**
3
+ * Detect if a node contains a functional state updater pattern.
4
+ * Matches: setState(prev => ...), setCount(current => current + 1), etc.
5
+ *
6
+ * Only matches when the updater parameter is actually used in the body.
7
+ * Does NOT match: setState(() => 1) — that's a constant updater.
8
+ */
9
+ export function hasFunctionalStateUpdater(node) {
10
+ let found = false;
11
+ function walk(n) {
12
+ if (found)
13
+ return;
14
+ // Look for calls like setFoo(param => ...)
15
+ if (ts.isCallExpression(n) && ts.isIdentifier(n.expression)) {
16
+ const callee = n.expression.text;
17
+ // Must start with "set" and have PascalCase after (setState, setCount, setItems)
18
+ if (/^set[A-Z]/.test(callee) && n.arguments.length >= 1) {
19
+ const arg = n.arguments[0];
20
+ if (ts.isArrowFunction(arg) || ts.isFunctionExpression(arg)) {
21
+ // Must have exactly one parameter
22
+ if (arg.parameters.length === 1) {
23
+ const paramName = arg.parameters[0].name;
24
+ if (ts.isIdentifier(paramName)) {
25
+ // Check if the parameter is actually used in the body
26
+ if (isIdentifierUsedInBody(paramName.text, arg.body)) {
27
+ found = true;
28
+ return;
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
34
+ }
35
+ ts.forEachChild(n, walk);
36
+ }
37
+ walk(node);
38
+ return found;
39
+ }
40
+ function isIdentifierUsedInBody(name, body) {
41
+ let used = false;
42
+ function walk(n) {
43
+ if (used)
44
+ return;
45
+ if (ts.isIdentifier(n) && n.text === name) {
46
+ // Make sure it's not the parameter declaration itself
47
+ if (!ts.isParameter(n.parent)) {
48
+ used = true;
49
+ return;
50
+ }
51
+ }
52
+ ts.forEachChild(n, walk);
53
+ }
54
+ walk(body);
55
+ return used;
56
+ }
57
+ //# sourceMappingURL=reactState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactState.js","sourceRoot":"","sources":["../../../src/analysis/ts/reactState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAa;IACrD,IAAI,KAAK,GAAG,KAAK,CAAC;IAElB,SAAS,IAAI,CAAC,CAAU;QACtB,IAAI,KAAK;YAAE,OAAO;QAElB,2CAA2C;QAC3C,IAAI,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5D,MAAM,MAAM,GAAG,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;YACjC,iFAAiF;YACjF,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACxD,MAAM,GAAG,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;gBAC3B,IAAI,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC5D,kCAAkC;oBAClC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBAChC,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;wBACzC,IAAI,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;4BAC/B,sDAAsD;4BACtD,IAAI,sBAAsB,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gCACrD,KAAK,GAAG,IAAI,CAAC;gCACb,OAAO;4BACT,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,CAAC;IACX,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAY,EAAE,IAAa;IACzD,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,SAAS,IAAI,CAAC,CAAU;QACtB,IAAI,IAAI;YAAE,OAAO;QACjB,IAAI,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YAC1C,sDAAsD;YACtD,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,IAAI,GAAG,IAAI,CAAC;gBACZ,OAAO;YACT,CAAC;QACH,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,CAAC;IACX,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Build a code snippet around a specific line, with optional context.
3
+ */
4
+ export declare function buildSnippet(sourceText: string, line: number, column?: number, contextLines?: number): {
5
+ snippet: string;
6
+ context: string;
7
+ };
8
+ /**
9
+ * Build a snippet from a file path + line.
10
+ */
11
+ export declare function buildSnippetFromFile(filePath: string, line: number, contextLines?: number): {
12
+ snippet: string;
13
+ context: string;
14
+ };
@@ -0,0 +1,29 @@
1
+ import * as fs from 'fs';
2
+ /**
3
+ * Build a code snippet around a specific line, with optional context.
4
+ */
5
+ export function buildSnippet(sourceText, line, column, contextLines = 1) {
6
+ const lines = sourceText.split('\n');
7
+ const line0 = line - 1; // Convert 1-indexed to 0-indexed
8
+ const start = Math.max(0, line0 - contextLines);
9
+ const end = Math.min(lines.length - 1, line0 + contextLines);
10
+ const snippet = lines[line0]?.trim() ?? '';
11
+ const context = lines
12
+ .slice(start, end + 1)
13
+ .map((l, i) => `${start + i + 1}| ${l}`)
14
+ .join('\n');
15
+ return { snippet, context };
16
+ }
17
+ /**
18
+ * Build a snippet from a file path + line.
19
+ */
20
+ export function buildSnippetFromFile(filePath, line, contextLines = 1) {
21
+ try {
22
+ const content = fs.readFileSync(filePath, 'utf-8');
23
+ return buildSnippet(content, line, undefined, contextLines);
24
+ }
25
+ catch {
26
+ return { snippet: '', context: '' };
27
+ }
28
+ }
29
+ //# sourceMappingURL=snippets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snippets.js","sourceRoot":"","sources":["../../../src/analysis/ts/snippets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,UAAkB,EAClB,IAAY,EACZ,MAAe,EACf,eAAuB,CAAC;IAExB,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,iCAAiC;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,YAAY,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG,YAAY,CAAC,CAAC;IAE7D,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,KAAK;SAClB,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC;SACrB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;SACvC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,IAAY,EACZ,eAAuB,CAAC;IAExB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,OAAO,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACtC,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import ts from 'typescript';
2
+ import type { StructuralPredicate } from '../../search/types.js';
3
+ /**
4
+ * Evaluate structural predicates on a TS AST node.
5
+ * Returns which predicates matched and evidence strings.
6
+ */
7
+ export declare function evaluateStructuralPredicates(sf: ts.SourceFile, node: ts.Node, predicates: StructuralPredicate[]): {
8
+ matched: StructuralPredicate[];
9
+ evidence: string[];
10
+ };
@@ -0,0 +1,199 @@
1
+ import ts from 'typescript';
2
+ import { hasFunctionalStateUpdater } from './reactState.js';
3
+ /**
4
+ * Evaluate structural predicates on a TS AST node.
5
+ * Returns which predicates matched and evidence strings.
6
+ */
7
+ export function evaluateStructuralPredicates(sf, node, predicates) {
8
+ const matched = [];
9
+ const evidence = [];
10
+ for (const pred of predicates) {
11
+ const result = evaluatePredicate(sf, node, pred);
12
+ if (result) {
13
+ matched.push(pred);
14
+ evidence.push(result);
15
+ }
16
+ }
17
+ return { matched, evidence };
18
+ }
19
+ function evaluatePredicate(sf, node, pred) {
20
+ switch (pred) {
21
+ case 'conditional':
22
+ return hasConditional(node) ? 'contains conditional branch' : null;
23
+ case 'returns-function':
24
+ return returnsFunction(node) ? 'returns a function expression' : null;
25
+ case 'returns-cleanup':
26
+ return returnsCleanup(node) ? 'callback returns a cleanup function' : null;
27
+ case 'no-cleanup':
28
+ return !returnsCleanup(node) && isCallbackLike(node) ? 'callback does not return cleanup' : null;
29
+ case 'has-try-catch':
30
+ return containsTryCatch(node) ? 'contains try-catch block' : null;
31
+ case 'no-try-catch':
32
+ return !containsTryCatch(node) ? 'no try-catch in scope' : null;
33
+ case 'switch-no-default':
34
+ return hasSwitchWithoutDefault(node) ? 'switch statement missing default case' : null;
35
+ case 'await-in-loop':
36
+ return hasAwaitInLoop(node) ? 'await inside loop body' : null;
37
+ case 'inside-hook':
38
+ return isInsideHookCall(node) ? 'inside a React hook call' : null;
39
+ case 'hook-callback':
40
+ return isHookCallback(node) ? 'is a callback argument to a hook' : null;
41
+ case 'functional-state-updater':
42
+ return hasFunctionalStateUpdater(node) ? 'contains functional state updater (e.g. setState(prev => ...))' : null;
43
+ default:
44
+ return null;
45
+ }
46
+ }
47
+ // --- Predicate implementations ---
48
+ function hasConditional(node) {
49
+ let found = false;
50
+ function walk(n) {
51
+ if (found)
52
+ return;
53
+ if (ts.isIfStatement(n) || ts.isConditionalExpression(n) || ts.isSwitchStatement(n)) {
54
+ found = true;
55
+ return;
56
+ }
57
+ ts.forEachChild(n, walk);
58
+ }
59
+ ts.forEachChild(node, walk);
60
+ return found;
61
+ }
62
+ function returnsFunction(node) {
63
+ let found = false;
64
+ function walk(n) {
65
+ if (found)
66
+ return;
67
+ if (ts.isReturnStatement(n) && n.expression) {
68
+ if (ts.isArrowFunction(n.expression) || ts.isFunctionExpression(n.expression)) {
69
+ found = true;
70
+ return;
71
+ }
72
+ }
73
+ ts.forEachChild(n, walk);
74
+ }
75
+ ts.forEachChild(node, walk);
76
+ return found;
77
+ }
78
+ function returnsCleanup(node) {
79
+ // For hook callbacks: check if the callback body returns a function
80
+ const callback = getFirstCallbackArg(node);
81
+ if (!callback)
82
+ return returnsFunction(node);
83
+ return returnsFunction(callback);
84
+ }
85
+ function isCallbackLike(node) {
86
+ return getFirstCallbackArg(node) !== null;
87
+ }
88
+ function containsTryCatch(node) {
89
+ if (ts.isTryStatement(node))
90
+ return true;
91
+ let found = false;
92
+ function walk(n) {
93
+ if (found)
94
+ return;
95
+ if (ts.isTryStatement(n)) {
96
+ found = true;
97
+ return;
98
+ }
99
+ ts.forEachChild(n, walk);
100
+ }
101
+ ts.forEachChild(node, walk);
102
+ return found;
103
+ }
104
+ function hasSwitchWithoutDefault(node) {
105
+ // Check node itself first (statementLocator passes the SwitchStatement directly)
106
+ if (ts.isSwitchStatement(node)) {
107
+ return !node.caseBlock.clauses.some((c) => ts.isDefaultClause(c));
108
+ }
109
+ let found = false;
110
+ function walk(n) {
111
+ if (found)
112
+ return;
113
+ if (ts.isSwitchStatement(n)) {
114
+ const hasDefault = n.caseBlock.clauses.some((c) => ts.isDefaultClause(c));
115
+ if (!hasDefault) {
116
+ found = true;
117
+ return;
118
+ }
119
+ }
120
+ ts.forEachChild(n, walk);
121
+ }
122
+ ts.forEachChild(node, walk);
123
+ return found;
124
+ }
125
+ function hasAwaitInLoop(node) {
126
+ const isLoop = (n) => ts.isForStatement(n) || ts.isForOfStatement(n) || ts.isForInStatement(n) || ts.isWhileStatement(n) || ts.isDoStatement(n);
127
+ // If node itself is a loop, check its body for await
128
+ if (isLoop(node)) {
129
+ let found = false;
130
+ function walkBody(n) {
131
+ if (found)
132
+ return;
133
+ if (ts.isAwaitExpression(n)) {
134
+ found = true;
135
+ return;
136
+ }
137
+ if (ts.isFunctionDeclaration(n) || ts.isArrowFunction(n) || ts.isFunctionExpression(n))
138
+ return;
139
+ ts.forEachChild(n, walkBody);
140
+ }
141
+ ts.forEachChild(node, walkBody);
142
+ return found;
143
+ }
144
+ // Otherwise search descendants for loop-with-await
145
+ let insideLoop = false;
146
+ let found = false;
147
+ function walk(n) {
148
+ if (found)
149
+ return;
150
+ const wasInsideLoop = insideLoop;
151
+ if (isLoop(n))
152
+ insideLoop = true;
153
+ if (insideLoop && ts.isAwaitExpression(n)) {
154
+ found = true;
155
+ return;
156
+ }
157
+ if (ts.isFunctionDeclaration(n) || ts.isArrowFunction(n) || ts.isFunctionExpression(n))
158
+ return;
159
+ ts.forEachChild(n, walk);
160
+ insideLoop = wasInsideLoop;
161
+ }
162
+ ts.forEachChild(node, walk);
163
+ return found;
164
+ }
165
+ function isInsideHookCall(node) {
166
+ let current = node;
167
+ while (current) {
168
+ if (ts.isCallExpression(current) && ts.isIdentifier(current.expression)) {
169
+ if (isHookName(current.expression.text))
170
+ return true;
171
+ }
172
+ current = current.parent;
173
+ }
174
+ return false;
175
+ }
176
+ function isHookCallback(node) {
177
+ // Check if this node is a call expression where the callee is a hook
178
+ if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
179
+ return isHookName(node.expression.text);
180
+ }
181
+ return false;
182
+ }
183
+ function isHookName(name) {
184
+ return /^use[A-Z]/.test(name);
185
+ }
186
+ /**
187
+ * Get the first callback argument from a call expression.
188
+ * For useEffect(callback, deps), returns the callback.
189
+ */
190
+ function getFirstCallbackArg(node) {
191
+ if (ts.isCallExpression(node) && node.arguments.length > 0) {
192
+ const first = node.arguments[0];
193
+ if (ts.isArrowFunction(first) || ts.isFunctionExpression(first)) {
194
+ return first;
195
+ }
196
+ }
197
+ return null;
198
+ }
199
+ //# sourceMappingURL=structuralPredicates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structuralPredicates.js","sourceRoot":"","sources":["../../../src/analysis/ts/structuralPredicates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ExportDeclaration } from './extractExportDeclarations.js';
2
+ export type ApiChangeKind = 'added' | 'removed' | 'modified' | 'renamed' | 'enum_member_added' | 'enum_member_removed' | 'param_required' | 'param_added' | 'param_removed' | 'return_type_changed' | 'interface_shape_changed' | 'type_changed' | 'reexport_changed';
3
+ export type ApiRiskLevel = 'breaking' | 'risky' | 'safe';
4
+ export interface DeclDiff {
5
+ name: string;
6
+ kind: ApiChangeKind;
7
+ risk: ApiRiskLevel;
8
+ reason: string;
9
+ structuralDiff: string[];
10
+ baseDecl?: ExportDeclaration;
11
+ currentDecl?: ExportDeclaration;
12
+ }
13
+ /**
14
+ * Diff two sets of export declarations. Returns classified changes.
15
+ */
16
+ export declare function diffExportDeclarations(baseExports: ExportDeclaration[], currentExports: ExportDeclaration[]): DeclDiff[];
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Diff two sets of export declarations. Returns classified changes.
3
+ */
4
+ export function diffExportDeclarations(baseExports, currentExports) {
5
+ const diffs = [];
6
+ const baseMap = new Map(baseExports.map((e) => [e.name, e]));
7
+ const currentMap = new Map(currentExports.map((e) => [e.name, e]));
8
+ // Removed exports
9
+ for (const [name, base] of baseMap) {
10
+ if (!currentMap.has(name)) {
11
+ diffs.push({
12
+ name,
13
+ kind: 'removed',
14
+ risk: 'breaking',
15
+ reason: `Export "${name}" (${base.declarationKind}) was removed`,
16
+ structuralDiff: [`- ${base.signatureText.substring(0, 100)}`],
17
+ baseDecl: base,
18
+ });
19
+ }
20
+ }
21
+ // Added exports
22
+ for (const [name, current] of currentMap) {
23
+ if (!baseMap.has(name)) {
24
+ diffs.push({
25
+ name,
26
+ kind: 'added',
27
+ risk: 'safe',
28
+ reason: `New export "${name}" (${current.declarationKind})`,
29
+ structuralDiff: [`+ ${current.signatureText.substring(0, 100)}`],
30
+ currentDecl: current,
31
+ });
32
+ }
33
+ }
34
+ // Modified exports
35
+ for (const [name, current] of currentMap) {
36
+ const base = baseMap.get(name);
37
+ if (!base)
38
+ continue;
39
+ const changes = compareDeclarations(base, current);
40
+ if (changes.length > 0) {
41
+ const worstRisk = changes.reduce((worst, c) => {
42
+ if (c.risk === 'breaking')
43
+ return 'breaking';
44
+ if (c.risk === 'risky' && worst !== 'breaking')
45
+ return 'risky';
46
+ return worst;
47
+ }, 'safe');
48
+ diffs.push({
49
+ name,
50
+ kind: changes[0].kind,
51
+ risk: worstRisk,
52
+ reason: changes.map((c) => c.reason).join('; '),
53
+ structuralDiff: changes.flatMap((c) => c.diffs),
54
+ baseDecl: base,
55
+ currentDecl: current,
56
+ });
57
+ }
58
+ }
59
+ return diffs;
60
+ }
61
+ function compareDeclarations(base, current) {
62
+ const changes = [];
63
+ // Enum member comparison
64
+ if (base.declarationKind === 'enum' && current.declarationKind === 'enum') {
65
+ const baseMembers = new Set(base.members ?? []);
66
+ const currentMembers = new Set(current.members ?? []);
67
+ for (const m of currentMembers) {
68
+ if (!baseMembers.has(m)) {
69
+ changes.push({
70
+ kind: 'enum_member_added',
71
+ risk: 'risky',
72
+ reason: `Enum member "${m}" added — exhaustive handling may be incomplete`,
73
+ diffs: [`+ ${m}`],
74
+ });
75
+ }
76
+ }
77
+ for (const m of baseMembers) {
78
+ if (!currentMembers.has(m)) {
79
+ changes.push({
80
+ kind: 'enum_member_removed',
81
+ risk: 'breaking',
82
+ reason: `Enum member "${m}" removed`,
83
+ diffs: [`- ${m}`],
84
+ });
85
+ }
86
+ }
87
+ return changes;
88
+ }
89
+ // Interface member comparison
90
+ if (base.declarationKind === 'interface' && current.declarationKind === 'interface') {
91
+ const baseMembers = new Set(base.members ?? []);
92
+ const currentMembers = new Set(current.members ?? []);
93
+ for (const m of baseMembers) {
94
+ if (!currentMembers.has(m)) {
95
+ changes.push({
96
+ kind: 'interface_shape_changed',
97
+ risk: 'breaking',
98
+ reason: `Interface property "${m}" removed`,
99
+ diffs: [`- ${m}`],
100
+ });
101
+ }
102
+ }
103
+ for (const m of currentMembers) {
104
+ if (!baseMembers.has(m)) {
105
+ changes.push({
106
+ kind: 'interface_shape_changed',
107
+ risk: 'risky',
108
+ reason: `Interface property "${m}" added`,
109
+ diffs: [`+ ${m}`],
110
+ });
111
+ }
112
+ }
113
+ return changes;
114
+ }
115
+ // Function parameter comparison
116
+ if (base.declarationKind === 'function' && current.declarationKind === 'function') {
117
+ const baseParams = base.params ?? [];
118
+ const currentParams = current.params ?? [];
119
+ if (currentParams.length > baseParams.length) {
120
+ const added = currentParams.slice(baseParams.length);
121
+ for (const p of added) {
122
+ changes.push({
123
+ kind: p.optional ? 'param_added' : 'param_required',
124
+ risk: p.optional ? 'safe' : 'breaking',
125
+ reason: p.optional
126
+ ? `Optional parameter "${p.name}" added`
127
+ : `Required parameter "${p.name}" added`,
128
+ diffs: [`+ ${p.name}${p.optional ? '?' : ''}: ${p.type ?? 'unknown'}`],
129
+ });
130
+ }
131
+ }
132
+ if (currentParams.length < baseParams.length) {
133
+ const removed = baseParams.slice(currentParams.length);
134
+ for (const p of removed) {
135
+ changes.push({
136
+ kind: 'param_removed',
137
+ risk: 'breaking',
138
+ reason: `Parameter "${p.name}" removed`,
139
+ diffs: [`- ${p.name}: ${p.type ?? 'unknown'}`],
140
+ });
141
+ }
142
+ }
143
+ // Check optionality changes
144
+ for (let i = 0; i < Math.min(baseParams.length, currentParams.length); i++) {
145
+ if (baseParams[i].optional && !currentParams[i].optional) {
146
+ changes.push({
147
+ kind: 'param_required',
148
+ risk: 'breaking',
149
+ reason: `Parameter "${currentParams[i].name}" became required (was optional)`,
150
+ diffs: [`~ ${currentParams[i].name}?: → ${currentParams[i].name}:`],
151
+ });
152
+ }
153
+ }
154
+ // Return type change
155
+ if (base.returnType && current.returnType && base.returnType !== current.returnType) {
156
+ changes.push({
157
+ kind: 'return_type_changed',
158
+ risk: 'risky',
159
+ reason: `Return type changed: ${base.returnType} → ${current.returnType}`,
160
+ diffs: [`- returns: ${base.returnType}`, `+ returns: ${current.returnType}`],
161
+ });
162
+ }
163
+ return changes;
164
+ }
165
+ // Generic signature comparison (fallback)
166
+ if (base.signatureText !== current.signatureText) {
167
+ changes.push({
168
+ kind: 'modified',
169
+ risk: 'risky',
170
+ reason: `Declaration signature changed`,
171
+ diffs: [
172
+ `- ${base.signatureText.substring(0, 100)}`,
173
+ `+ ${current.signatureText.substring(0, 100)}`,
174
+ ],
175
+ });
176
+ }
177
+ return changes;
178
+ }
179
+ //# sourceMappingURL=diffDeclarationShapes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diffDeclarationShapes.js","sourceRoot":"","sources":["../../src/ast/diffDeclarationShapes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { SgNode } from '@ast-grep/napi';
2
+ export interface ExportDeclaration {
3
+ name: string;
4
+ declarationKind: 'function' | 'type' | 'interface' | 'enum' | 'class' | 'const' | 'variable' | 'reexport' | 'unknown';
5
+ line: number;
6
+ signatureText: string;
7
+ members?: string[];
8
+ params?: ParamInfo[];
9
+ returnType?: string;
10
+ }
11
+ export interface ParamInfo {
12
+ name: string;
13
+ type?: string;
14
+ optional: boolean;
15
+ }
16
+ /**
17
+ * AST-first export extraction with regex fallback for unsupported forms.
18
+ * When root is provided (non-null), uses ast-grep traversal.
19
+ * When root is null, falls back to regex over source lines.
20
+ */
21
+ export declare function extractExportDeclarations(root: SgNode | null, source: string): ExportDeclaration[];