lsp-intelligence 0.1.1 → 0.2.0

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 (128) hide show
  1. package/README.md +63 -10
  2. package/dist/analysis/pattern/collectSearchFiles.d.ts +5 -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 +63 -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 +120 -0
  13. package/dist/analysis/ts/extractUsages.js.map +1 -0
  14. package/dist/analysis/ts/parseSourceFile.d.ts +10 -0
  15. package/dist/analysis/ts/parseSourceFile.js +28 -0
  16. package/dist/analysis/ts/parseSourceFile.js.map +1 -0
  17. package/dist/analysis/ts/snippets.d.ts +14 -0
  18. package/dist/analysis/ts/snippets.js +29 -0
  19. package/dist/analysis/ts/snippets.js.map +1 -0
  20. package/dist/analysis/ts/structuralPredicates.d.ts +10 -0
  21. package/dist/analysis/ts/structuralPredicates.js +170 -0
  22. package/dist/analysis/ts/structuralPredicates.js.map +1 -0
  23. package/dist/ast/diffDeclarationShapes.d.ts +16 -0
  24. package/dist/ast/diffDeclarationShapes.js +179 -0
  25. package/dist/ast/diffDeclarationShapes.js.map +1 -0
  26. package/dist/ast/extractExportDeclarations.d.ts +21 -0
  27. package/dist/ast/extractExportDeclarations.js +218 -0
  28. package/dist/ast/extractExportDeclarations.js.map +1 -0
  29. package/dist/ast/findNodeAtPosition.d.ts +12 -0
  30. package/dist/ast/findNodeAtPosition.js +75 -0
  31. package/dist/ast/findNodeAtPosition.js.map +1 -0
  32. package/dist/ast/parseFile.d.ts +10 -0
  33. package/dist/ast/parseFile.js +29 -0
  34. package/dist/ast/parseFile.js.map +1 -0
  35. package/dist/engine/waitForDiagnostics.d.ts +7 -0
  36. package/dist/engine/waitForDiagnostics.js +16 -0
  37. package/dist/engine/waitForDiagnostics.js.map +1 -0
  38. package/dist/git/getBaseFileContent.d.ts +5 -0
  39. package/dist/git/getBaseFileContent.js +16 -0
  40. package/dist/git/getBaseFileContent.js.map +1 -0
  41. package/dist/git/getChangedFiles.d.ts +4 -0
  42. package/dist/git/getChangedFiles.js +21 -0
  43. package/dist/git/getChangedFiles.js.map +1 -0
  44. package/dist/git/getChangedHunks.d.ts +13 -0
  45. package/dist/git/getChangedHunks.js +51 -0
  46. package/dist/git/getChangedHunks.js.map +1 -0
  47. package/dist/git/getMergeBase.d.ts +5 -0
  48. package/dist/git/getMergeBase.js +23 -0
  49. package/dist/git/getMergeBase.js.map +1 -0
  50. package/dist/index.js +8 -2
  51. package/dist/index.js.map +1 -1
  52. package/dist/resolve/searchScope.d.ts +11 -0
  53. package/dist/resolve/searchScope.js +52 -0
  54. package/dist/resolve/searchScope.js.map +1 -0
  55. package/dist/resolve/targetResolver.d.ts +33 -0
  56. package/dist/resolve/targetResolver.js +84 -0
  57. package/dist/resolve/targetResolver.js.map +1 -0
  58. package/dist/search/families/behaviorFamilies.d.ts +22 -0
  59. package/dist/search/families/behaviorFamilies.js +90 -0
  60. package/dist/search/families/behaviorFamilies.js.map +1 -0
  61. package/dist/search/index/declarationIndex.d.ts +6 -0
  62. package/dist/search/index/declarationIndex.js +13 -0
  63. package/dist/search/index/declarationIndex.js.map +1 -0
  64. package/dist/search/index/types.d.ts +1 -0
  65. package/dist/search/index/types.js +2 -0
  66. package/dist/search/index/types.js.map +1 -0
  67. package/dist/search/index/usageIndex.d.ts +6 -0
  68. package/dist/search/index/usageIndex.js +13 -0
  69. package/dist/search/index/usageIndex.js.map +1 -0
  70. package/dist/search/index/workspaceIndex.d.ts +8 -0
  71. package/dist/search/index/workspaceIndex.js +91 -0
  72. package/dist/search/index/workspaceIndex.js.map +1 -0
  73. package/dist/search/query/parseQuery.d.ts +9 -0
  74. package/dist/search/query/parseQuery.js +244 -0
  75. package/dist/search/query/parseQuery.js.map +1 -0
  76. package/dist/search/query/planQuery.d.ts +9 -0
  77. package/dist/search/query/planQuery.js +58 -0
  78. package/dist/search/query/planQuery.js.map +1 -0
  79. package/dist/search/ranking/assessConfidence.d.ts +6 -0
  80. package/dist/search/ranking/assessConfidence.js +25 -0
  81. package/dist/search/ranking/assessConfidence.js.map +1 -0
  82. package/dist/search/ranking/mergeCandidates.d.ts +10 -0
  83. package/dist/search/ranking/mergeCandidates.js +46 -0
  84. package/dist/search/ranking/mergeCandidates.js.map +1 -0
  85. package/dist/search/ranking/rankCandidates.d.ts +12 -0
  86. package/dist/search/ranking/rankCandidates.js +58 -0
  87. package/dist/search/ranking/rankCandidates.js.map +1 -0
  88. package/dist/search/retrievers/behaviorRetriever.d.ts +7 -0
  89. package/dist/search/retrievers/behaviorRetriever.js +91 -0
  90. package/dist/search/retrievers/behaviorRetriever.js.map +1 -0
  91. package/dist/search/retrievers/identifierRetriever.d.ts +7 -0
  92. package/dist/search/retrievers/identifierRetriever.js +66 -0
  93. package/dist/search/retrievers/identifierRetriever.js.map +1 -0
  94. package/dist/search/retrievers/structuralRetriever.d.ts +11 -0
  95. package/dist/search/retrievers/structuralRetriever.js +141 -0
  96. package/dist/search/retrievers/structuralRetriever.js.map +1 -0
  97. package/dist/search/types.d.ts +121 -0
  98. package/dist/search/types.js +11 -0
  99. package/dist/search/types.js.map +1 -0
  100. package/dist/tools/composites/apiGuard.d.ts +1 -0
  101. package/dist/tools/composites/apiGuard.js +194 -0
  102. package/dist/tools/composites/apiGuard.js.map +1 -0
  103. package/dist/tools/composites/explainError.js +3 -2
  104. package/dist/tools/composites/explainError.js.map +1 -1
  105. package/dist/tools/composites/findCode.d.ts +1 -0
  106. package/dist/tools/composites/findCode.js +68 -0
  107. package/dist/tools/composites/findCode.js.map +1 -0
  108. package/dist/tools/composites/findPattern.d.ts +5 -0
  109. package/dist/tools/composites/findPattern.js +41 -0
  110. package/dist/tools/composites/findPattern.js.map +1 -0
  111. package/dist/tools/composites/rootCauseTrace.d.ts +1 -0
  112. package/dist/tools/composites/rootCauseTrace.js +213 -0
  113. package/dist/tools/composites/rootCauseTrace.js.map +1 -0
  114. package/dist/tools/composites/semanticDiff.js +24 -77
  115. package/dist/tools/composites/semanticDiff.js.map +1 -1
  116. package/dist/tools/live/autoImport.js +38 -20
  117. package/dist/tools/live/autoImport.js.map +1 -1
  118. package/dist/tools/live/liveDiagnostics.js +3 -2
  119. package/dist/tools/live/liveDiagnostics.js.map +1 -1
  120. package/dist/tools/primitives/diagnostics.js +2 -2
  121. package/dist/tools/primitives/diagnostics.js.map +1 -1
  122. package/dist/tools/registry.d.ts +10 -2
  123. package/dist/tools/registry.js +7 -2
  124. package/dist/tools/registry.js.map +1 -1
  125. package/package.json +8 -4
  126. package/dist/tools/primitives/typeHierarchy.d.ts +0 -1
  127. package/dist/tools/primitives/typeHierarchy.js +0 -49
  128. package/dist/tools/primitives/typeHierarchy.js.map +0 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Type-aware code intelligence for AI agents — impact analysis, semantic diff, and context building via LSP.
4
4
 
5
- **25 MCP tools** across 5 layers — from basic navigation to "what breaks if I change this?" in one call.
5
+ **28 MCP tools** across 5 layers — from basic navigation to "what breaks if I change this?" in one call.
6
6
 
7
7
  Currently supports **TypeScript and JavaScript** projects. The architecture supports other LSP servers — additional language support is planned.
8
8
 
@@ -32,7 +32,56 @@ Or get a file overview without reading it:
32
32
  { "tool": "outline", "arguments": { "file_path": "/workspace/src/services/auth.ts" } }
33
33
  ```
34
34
 
35
- > All tools that accept `file_path` require absolute paths. The `LSP_WORKSPACE_ROOT` env var tells the engine where your project lives.
35
+ > All tools that accept `file_path` require absolute paths.
36
+
37
+ ## Installation
38
+
39
+ Requires **Node.js 20+**. Dependencies are installed automatically on first session start.
40
+
41
+ ### Option 1: CLI (recommended)
42
+
43
+ Add the marketplace and install the plugin:
44
+
45
+ ```shell
46
+ /plugin marketplace add perilevy/lsp-intelligence
47
+ /plugin install lsp-intelligence@lsp-intelligence
48
+ /reload-plugins
49
+ ```
50
+
51
+ ### Option 2: Project configuration (team setup)
52
+
53
+ Add to your project's `.claude/settings.json` — any teammate who clones the repo gets it automatically:
54
+
55
+ ```json
56
+ {
57
+ "extraKnownMarketplaces": {
58
+ "lsp-intelligence": {
59
+ "source": {
60
+ "source": "github",
61
+ "repo": "perilevy/lsp-intelligence"
62
+ }
63
+ }
64
+ },
65
+ "enabledPlugins": {
66
+ "lsp-intelligence@lsp-intelligence": true
67
+ }
68
+ }
69
+ ```
70
+
71
+ ### Option 3: npm source
72
+
73
+ Use npm source in `marketplace.json` for version pinning and built-in dependency resolution:
74
+
75
+ ```json
76
+ {
77
+ "name": "lsp-intelligence",
78
+ "source": {
79
+ "source": "npm",
80
+ "package": "lsp-intelligence",
81
+ "version": "0.2.0"
82
+ }
83
+ }
84
+ ```
36
85
 
37
86
  ## Capabilities
38
87
 
@@ -73,7 +122,7 @@ The engine initializes once per session and stays warm. Warmup includes spawning
73
122
 
74
123
  ## Tools
75
124
 
76
- ### Layer 1: Primitives (14 tools)
125
+ ### Layer 1: Primitives (13 tools)
77
126
 
78
127
  Direct LSP wrappers. Every tool accepts **symbol names** — agents never need to guess line numbers.
79
128
 
@@ -87,22 +136,25 @@ Direct LSP wrappers. Every tool accepts **symbol names** — agents never need t
87
136
  | `document_symbols` | List all symbols in a file. |
88
137
  | `workspace_symbols` | Search for symbols by name across the workspace. |
89
138
  | `call_hierarchy` | Trace incoming callers or outgoing callees. |
90
- | `type_hierarchy` | Explore supertypes and subtypes. |
91
139
  | `rename` | Preview a semantic rename across the codebase (dry-run by default). |
92
140
  | `diagnostics` | Get type errors and warnings for a file. |
93
141
  | `completions` | Code completion suggestions. |
94
142
  | `file_imports` | List all imports of a file. |
95
143
  | `file_exports` | List a file's public API including re-exports. |
96
144
 
97
- ### Layer 2: Composites (6 tools)
145
+ ### Layer 2: Intelligence Tools (10 tools)
98
146
 
99
- Combine multiple primitives into high-level operations.
147
+ Combine LSP, AST, and Git substrates into high-level operations.
100
148
 
101
149
  | Tool | Description |
102
150
  |------|-------------|
151
+ | `api_guard` | Detect public API contract changes — export diffs, structural classification, consumer impact, semver summary. |
152
+ | `root_cause_trace` | Trace the root cause of a TypeScript error — find the originating declaration change, not just the symptom. |
153
+ | `find_code` | Unified code search: behavior discovery, identifier/API usage search, and structural queries. Routes automatically based on the query. |
154
+ | `find_pattern` | AST structural search — find code by pattern (e.g. `useEffect($$$)`, `try { $$$ } catch ($E) { $$$ }`). |
103
155
  | `inspect_symbol` | Hover + definition + references in one call. Full context about any symbol. |
104
156
  | `batch_query` | Look up multiple symbols at once. Saves round-trips when exploring. |
105
- | `impact_trace` | Follow a symbol through type aliases and re-exports to find ALL transitive usages. Answers **"what breaks if I change X?"** in one call. |
157
+ | `impact_trace` | Follow a symbol through type aliases and re-exports to find ALL transitive usages. |
106
158
  | `semantic_diff` | Analyze git diff semantically: identify changed symbols and their blast radius. |
107
159
  | `find_test_files` | Find all test/spec/stories files that reference a symbol. |
108
160
  | `explain_error` | Turn a TypeScript error into actionable context: expected type, actual type, and fix suggestion. |
@@ -136,13 +188,14 @@ Post-edit verification.
136
188
  │ Layer 3: Context Engine [read-only] │
137
189
  │ gather_context, outline │
138
190
  ├─────────────────────────────────────────────────────────┤
139
- │ Layer 2: Composites [read-only] │
191
+ │ Layer 2: Intelligence Tools [read-only] │
192
+ │ api_guard, root_cause_trace, find_code, find_pattern, │
140
193
  │ impact_trace, semantic_diff, inspect_symbol, │
141
194
  │ batch_query, find_test_files, explain_error │
142
195
  ├─────────────────────────────────────────────────────────┤
143
196
  │ Layer 1: Primitives [read-only] │
144
197
  │ find_references, hover, definition, call_hierarchy, │
145
- type_hierarchy, rename, diagnostics, symbols, etc.
198
+ │ rename, diagnostics, symbols, imports, exports
146
199
  ├─────────────────────────────────────────────────────────┤
147
200
  │ Layer 0: LSP Engine [infrastructure] │
148
201
  │ TypeScript Server spawn, monorepo preopen, │
@@ -191,7 +244,7 @@ Add to your `.mcp.json`:
191
244
  "mcpServers": {
192
245
  "lsp": {
193
246
  "command": "npx",
194
- "args": ["-y", "lsp-intelligence"],
247
+ "args": ["--registry", "https://registry.npmjs.org", "-y", "lsp-intelligence"],
195
248
  "env": {
196
249
  "LSP_WORKSPACE_ROOT": "${CLAUDE_PROJECT_DIR}"
197
250
  }
@@ -0,0 +1,5 @@
1
+ import type { SearchScope } from '../../search/types.js';
2
+ /**
3
+ * Collect files matching a language within a search scope.
4
+ */
5
+ export declare function collectSearchFiles(scope: SearchScope, extensions: string[], maxFiles: number): string[];
@@ -0,0 +1,38 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { SKIP_DIRS } from '../../engine/types.js';
4
+ const TEST_PATTERN = /\.(spec|test|stories)\.(ts|tsx|js|jsx)$/;
5
+ /**
6
+ * Collect files matching a language within a search scope.
7
+ */
8
+ export function collectSearchFiles(scope, extensions, maxFiles) {
9
+ const files = [];
10
+ for (const root of scope.roots) {
11
+ walkDir(root, files, extensions, scope.includeTests, maxFiles, 0);
12
+ if (files.length >= maxFiles)
13
+ break;
14
+ }
15
+ return files;
16
+ }
17
+ function walkDir(dir, files, extensions, includeTests, maxFiles, depth) {
18
+ if (depth > 8 || files.length >= maxFiles)
19
+ return;
20
+ try {
21
+ for (const entry of fs.readdirSync(dir)) {
22
+ if (SKIP_DIRS.has(entry))
23
+ continue;
24
+ const full = path.join(dir, entry);
25
+ const stat = fs.statSync(full);
26
+ if (stat.isDirectory()) {
27
+ walkDir(full, files, extensions, includeTests, maxFiles, depth + 1);
28
+ }
29
+ else if (extensions.some((e) => entry.endsWith(e)) && !entry.endsWith('.d.ts')) {
30
+ if (!includeTests && TEST_PATTERN.test(entry))
31
+ continue;
32
+ files.push(full);
33
+ }
34
+ }
35
+ }
36
+ catch { }
37
+ }
38
+ //# sourceMappingURL=collectSearchFiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collectSearchFiles.js","sourceRoot":"","sources":["../../../src/analysis/pattern/collectSearchFiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,MAAM,YAAY,GAAG,yCAAyC,CAAC;AAE/D;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAkB,EAClB,UAAoB,EACpB,QAAgB;IAEhB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAClE,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ;YAAE,MAAM;IACtC,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,OAAO,CACd,GAAW,EACX,KAAe,EACf,UAAoB,EACpB,YAAqB,EACrB,QAAgB,EAChB,KAAa;IAEb,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO;IAClD,IAAI,CAAC;QACH,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,SAAS;YACnC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACnC,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YACtE,CAAC;iBAAM,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACjF,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;oBAAE,SAAS;gBACxD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { SearchScope, PatternMatch } from '../../search/types.js';
2
+ /**
3
+ * Run an ast-grep pattern search across files in scope.
4
+ * This is the engine behind find_pattern. Structural retrievers may also use it.
5
+ */
6
+ export declare function runPatternSearch(input: {
7
+ pattern: string;
8
+ language: 'typescript' | 'tsx' | 'javascript';
9
+ scope: SearchScope;
10
+ maxResults: number;
11
+ contextLines: number;
12
+ workspaceRoot: string;
13
+ }): {
14
+ filesScanned: number;
15
+ matches: PatternMatch[];
16
+ warnings: string[];
17
+ };
@@ -0,0 +1,63 @@
1
+ import * as fs from 'fs';
2
+ import { parse, Lang } from '@ast-grep/napi';
3
+ import { collectSearchFiles } from './collectSearchFiles.js';
4
+ import { relativePath } from '../../engine/positions.js';
5
+ const LANG_MAP = {
6
+ typescript: Lang.TypeScript,
7
+ tsx: Lang.Tsx,
8
+ javascript: Lang.JavaScript,
9
+ };
10
+ const EXT_MAP = {
11
+ typescript: ['.ts'],
12
+ tsx: ['.tsx', '.ts'],
13
+ javascript: ['.js'],
14
+ };
15
+ /**
16
+ * Run an ast-grep pattern search across files in scope.
17
+ * This is the engine behind find_pattern. Structural retrievers may also use it.
18
+ */
19
+ export function runPatternSearch(input) {
20
+ const lang = LANG_MAP[input.language];
21
+ if (!lang)
22
+ return { filesScanned: 0, matches: [], warnings: [`Unsupported language: ${input.language}`] };
23
+ const extensions = EXT_MAP[input.language];
24
+ const files = collectSearchFiles(input.scope, extensions, 500);
25
+ const matches = [];
26
+ const warnings = [];
27
+ for (const file of files) {
28
+ if (matches.length >= input.maxResults)
29
+ break;
30
+ try {
31
+ const content = fs.readFileSync(file, 'utf-8');
32
+ const root = parse(lang, content).root();
33
+ const found = root.findAll(input.pattern);
34
+ for (const match of found) {
35
+ if (matches.length >= input.maxResults)
36
+ break;
37
+ const range = match.range();
38
+ const line = range.start.line + 1;
39
+ matches.push({
40
+ filePath: relativePath(file, input.workspaceRoot),
41
+ line,
42
+ column: range.start.column,
43
+ text: match.text().substring(0, 200),
44
+ context: getContextLines(content, range.start.line, input.contextLines),
45
+ });
46
+ }
47
+ }
48
+ catch (err) {
49
+ warnings.push(`Parse failed for ${relativePath(file, input.workspaceRoot)}: ${err instanceof Error ? err.message : String(err)}`);
50
+ }
51
+ }
52
+ return { filesScanned: files.length, matches, warnings };
53
+ }
54
+ function getContextLines(content, line0, ctx) {
55
+ const lines = content.split('\n');
56
+ const start = Math.max(0, line0 - ctx);
57
+ const end = Math.min(lines.length - 1, line0 + ctx);
58
+ return lines
59
+ .slice(start, end + 1)
60
+ .map((l, i) => `${start + i + 1}| ${l}`)
61
+ .join('\n');
62
+ }
63
+ //# sourceMappingURL=runPatternSearch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runPatternSearch.js","sourceRoot":"","sources":["../../../src/analysis/pattern/runPatternSearch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import ts from 'typescript';
2
+ import type { DeclarationIndexEntry } from '../../search/types.js';
3
+ /**
4
+ * Extract all declarations from a TypeScript source file using the TS compiler API.
5
+ * Returns top-level and exported declarations with symbol tokens for searching.
6
+ */
7
+ export declare function extractDeclarations(sf: ts.SourceFile): DeclarationIndexEntry[];
@@ -0,0 +1,93 @@
1
+ import ts from 'typescript';
2
+ import * as path from 'path';
3
+ /**
4
+ * Tokenize a symbol name: split camelCase, PascalCase, snake_case.
5
+ */
6
+ function tokenize(name) {
7
+ return name
8
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
9
+ .split(/[^a-zA-Z0-9]+/)
10
+ .map((t) => t.toLowerCase())
11
+ .filter((t) => t.length > 1);
12
+ }
13
+ function pathTokenize(filePath) {
14
+ const rel = path.basename(filePath, path.extname(filePath));
15
+ return tokenize(rel);
16
+ }
17
+ /**
18
+ * Extract all declarations from a TypeScript source file using the TS compiler API.
19
+ * Returns top-level and exported declarations with symbol tokens for searching.
20
+ */
21
+ export function extractDeclarations(sf) {
22
+ const entries = [];
23
+ const filePath = sf.fileName;
24
+ const pathToks = pathTokenize(filePath);
25
+ function visit(node) {
26
+ // Function declarations
27
+ if (ts.isFunctionDeclaration(node) && node.name) {
28
+ entries.push(makeEntry(node.name.text, 'function', node, sf, filePath, pathToks));
29
+ }
30
+ // Variable statements: export const/let/var
31
+ else if (ts.isVariableStatement(node)) {
32
+ const isExported = hasExportModifier(node);
33
+ for (const decl of node.declarationList.declarations) {
34
+ if (ts.isIdentifier(decl.name)) {
35
+ const kind = decl.initializer && (ts.isArrowFunction(decl.initializer) || ts.isFunctionExpression(decl.initializer))
36
+ ? 'function' : 'variable';
37
+ entries.push({
38
+ symbol: decl.name.text,
39
+ kind,
40
+ filePath,
41
+ line: sf.getLineAndCharacterOfPosition(decl.getStart(sf)).line + 1,
42
+ column: sf.getLineAndCharacterOfPosition(decl.getStart(sf)).character,
43
+ isExported,
44
+ pathTokens: pathToks,
45
+ symbolTokens: tokenize(decl.name.text),
46
+ });
47
+ }
48
+ }
49
+ }
50
+ // Class declarations
51
+ else if (ts.isClassDeclaration(node) && node.name) {
52
+ entries.push(makeEntry(node.name.text, 'class', node, sf, filePath, pathToks));
53
+ }
54
+ // Interface declarations
55
+ else if (ts.isInterfaceDeclaration(node)) {
56
+ entries.push(makeEntry(node.name.text, 'interface', node, sf, filePath, pathToks));
57
+ }
58
+ // Type alias declarations
59
+ else if (ts.isTypeAliasDeclaration(node)) {
60
+ entries.push(makeEntry(node.name.text, 'type', node, sf, filePath, pathToks));
61
+ }
62
+ // Enum declarations
63
+ else if (ts.isEnumDeclaration(node)) {
64
+ entries.push(makeEntry(node.name.text, 'enum', node, sf, filePath, pathToks));
65
+ }
66
+ // Only visit top-level children
67
+ if (node === sf) {
68
+ ts.forEachChild(node, visit);
69
+ }
70
+ }
71
+ visit(sf);
72
+ return entries;
73
+ }
74
+ function makeEntry(name, kind, node, sf, filePath, pathToks) {
75
+ const pos = sf.getLineAndCharacterOfPosition(node.getStart(sf));
76
+ return {
77
+ symbol: name,
78
+ kind,
79
+ filePath,
80
+ line: pos.line + 1,
81
+ column: pos.character,
82
+ isExported: hasExportModifier(node),
83
+ pathTokens: pathToks,
84
+ symbolTokens: tokenize(name),
85
+ };
86
+ }
87
+ function hasExportModifier(node) {
88
+ if (!ts.canHaveModifiers(node))
89
+ return false;
90
+ const mods = ts.getModifiers(node);
91
+ return mods?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
92
+ }
93
+ //# sourceMappingURL=extractDeclarations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractDeclarations.js","sourceRoot":"","sources":["../../../src/analysis/ts/extractDeclarations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import ts from 'typescript';
2
+ import type { UsageIndexEntry } from '../../search/types.js';
3
+ /**
4
+ * Extract all identifier usage sites from a TypeScript source file.
5
+ * Indexes: call expressions, member calls, import specifiers, JSX tags.
6
+ */
7
+ export declare function extractUsages(sf: ts.SourceFile): UsageIndexEntry[];
@@ -0,0 +1,120 @@
1
+ import ts from 'typescript';
2
+ import * as path from 'path';
3
+ function pathTokenize(filePath) {
4
+ return path.basename(filePath, path.extname(filePath))
5
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
6
+ .split(/[^a-zA-Z0-9]+/)
7
+ .map((t) => t.toLowerCase())
8
+ .filter((t) => t.length > 1);
9
+ }
10
+ /**
11
+ * Extract all identifier usage sites from a TypeScript source file.
12
+ * Indexes: call expressions, member calls, import specifiers, JSX tags.
13
+ */
14
+ export function extractUsages(sf) {
15
+ const entries = [];
16
+ const filePath = sf.fileName;
17
+ const pathToks = pathTokenize(filePath);
18
+ // Track enclosing symbol for context
19
+ let enclosingSymbol;
20
+ let enclosingKind;
21
+ function visit(node) {
22
+ // Save enclosing context so it restores correctly on recursion unwind
23
+ const prevSymbol = enclosingSymbol;
24
+ const prevKind = enclosingKind;
25
+ // Track enclosing function/class/method for context
26
+ if (ts.isFunctionDeclaration(node) && node.name) {
27
+ enclosingSymbol = node.name.text;
28
+ enclosingKind = 'function';
29
+ }
30
+ else if (ts.isVariableStatement(node)) {
31
+ for (const decl of node.declarationList.declarations) {
32
+ if (ts.isIdentifier(decl.name) && decl.initializer &&
33
+ (ts.isArrowFunction(decl.initializer) || ts.isFunctionExpression(decl.initializer))) {
34
+ enclosingSymbol = decl.name.text;
35
+ enclosingKind = 'function';
36
+ }
37
+ }
38
+ }
39
+ else if (ts.isClassDeclaration(node) && node.name) {
40
+ enclosingSymbol = node.name.text;
41
+ enclosingKind = 'class';
42
+ }
43
+ else if (ts.isMethodDeclaration(node) && ts.isIdentifier(node.name)) {
44
+ enclosingSymbol = node.name.text;
45
+ enclosingKind = 'method';
46
+ }
47
+ // Call expressions: foo(), bar.baz()
48
+ if (ts.isCallExpression(node)) {
49
+ const expr = node.expression;
50
+ // Simple call: useEffect(...)
51
+ if (ts.isIdentifier(expr)) {
52
+ entries.push(makeUsage(expr.text, expr.text, 'call', node, sf, filePath, pathToks, enclosingSymbol, enclosingKind));
53
+ }
54
+ // Member call: Promise.all(...), sdk.Items.get(...)
55
+ else if (ts.isPropertyAccessExpression(expr)) {
56
+ const fullName = getPropertyAccessText(expr);
57
+ const leafName = expr.name.text;
58
+ entries.push(makeUsage(fullName, leafName, 'member-call', node, sf, filePath, pathToks, enclosingSymbol, enclosingKind));
59
+ }
60
+ }
61
+ // Import declarations: import { X } from "module"
62
+ if (ts.isImportDeclaration(node) && node.importClause) {
63
+ const clause = node.importClause;
64
+ // Default import
65
+ if (clause.name) {
66
+ entries.push(makeUsage(clause.name.text, clause.name.text, 'import', clause.name, sf, filePath, pathToks, undefined, undefined));
67
+ }
68
+ // Named imports: { A, B }
69
+ if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {
70
+ for (const spec of clause.namedBindings.elements) {
71
+ entries.push(makeUsage(spec.name.text, spec.name.text, 'import', spec, sf, filePath, pathToks, undefined, undefined));
72
+ }
73
+ }
74
+ // Namespace import: * as X
75
+ if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings)) {
76
+ entries.push(makeUsage(clause.namedBindings.name.text, clause.namedBindings.name.text, 'import', clause.namedBindings, sf, filePath, pathToks, undefined, undefined));
77
+ }
78
+ }
79
+ // JSX elements: <Component ... />
80
+ if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
81
+ const tagName = node.tagName;
82
+ if (ts.isIdentifier(tagName) && /^[A-Z]/.test(tagName.text)) {
83
+ entries.push(makeUsage(tagName.text, tagName.text, 'jsx-tag', node, sf, filePath, pathToks, enclosingSymbol, enclosingKind));
84
+ }
85
+ }
86
+ ts.forEachChild(node, visit);
87
+ // Restore enclosing context on unwind
88
+ enclosingSymbol = prevSymbol;
89
+ enclosingKind = prevKind;
90
+ }
91
+ visit(sf);
92
+ return entries;
93
+ }
94
+ function makeUsage(identifier, normalizedIdentifier, kind, node, sf, filePath, pathToks, enclosingSymbol, enclosingKind) {
95
+ const pos = sf.getLineAndCharacterOfPosition(node.getStart(sf));
96
+ return {
97
+ identifier,
98
+ normalizedIdentifier,
99
+ kind,
100
+ filePath,
101
+ line: pos.line + 1,
102
+ column: pos.character,
103
+ enclosingSymbol,
104
+ enclosingKind,
105
+ pathTokens: pathToks,
106
+ };
107
+ }
108
+ function getPropertyAccessText(node) {
109
+ const parts = [node.name.text];
110
+ let current = node.expression;
111
+ while (ts.isPropertyAccessExpression(current)) {
112
+ parts.unshift(current.name.text);
113
+ current = current.expression;
114
+ }
115
+ if (ts.isIdentifier(current)) {
116
+ parts.unshift(current.text);
117
+ }
118
+ return parts.join('.');
119
+ }
120
+ //# sourceMappingURL=extractUsages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractUsages.js","sourceRoot":"","sources":["../../../src/analysis/ts/extractUsages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import ts from 'typescript';
2
+ /**
3
+ * Parse a TypeScript/TSX file into a ts.SourceFile using the TypeScript compiler API.
4
+ * Returns null if the file doesn't exist or can't be parsed.
5
+ */
6
+ export declare function parseSourceFile(filePath: string): ts.SourceFile | null;
7
+ /**
8
+ * Parse source content directly (for base-version comparison).
9
+ */
10
+ export declare function parseSourceContent(content: string, fileName: string): ts.SourceFile;
@@ -0,0 +1,28 @@
1
+ import ts from 'typescript';
2
+ import * as fs from 'fs';
3
+ /**
4
+ * Parse a TypeScript/TSX file into a ts.SourceFile using the TypeScript compiler API.
5
+ * Returns null if the file doesn't exist or can't be parsed.
6
+ */
7
+ export function parseSourceFile(filePath) {
8
+ try {
9
+ const content = fs.readFileSync(filePath, 'utf-8');
10
+ const scriptKind = filePath.endsWith('.tsx') ? ts.ScriptKind.TSX
11
+ : filePath.endsWith('.jsx') ? ts.ScriptKind.JSX
12
+ : ts.ScriptKind.TS;
13
+ return ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, scriptKind);
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
19
+ /**
20
+ * Parse source content directly (for base-version comparison).
21
+ */
22
+ export function parseSourceContent(content, fileName) {
23
+ const scriptKind = fileName.endsWith('.tsx') ? ts.ScriptKind.TSX
24
+ : fileName.endsWith('.jsx') ? ts.ScriptKind.JSX
25
+ : ts.ScriptKind.TS;
26
+ return ts.createSourceFile(fileName, content, ts.ScriptTarget.Latest, true, scriptKind);
27
+ }
28
+ //# sourceMappingURL=parseSourceFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseSourceFile.js","sourceRoot":"","sources":["../../../src/analysis/ts/parseSourceFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG;YAC9D,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG;gBAC/C,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1F,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe,EAAE,QAAgB;IAClE,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG;QAC9D,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG;YAC/C,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;IACrB,OAAO,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AAC1F,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
+ };