lsp-intelligence 0.2.1 → 0.3.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.
- package/dist/adapters/express/index.d.ts +9 -0
- package/dist/adapters/express/index.js +46 -0
- package/dist/adapters/express/index.js.map +1 -0
- package/dist/adapters/next/index.d.ts +10 -0
- package/dist/adapters/next/index.js +67 -0
- package/dist/adapters/next/index.js.map +1 -0
- package/dist/adapters/react/index.d.ts +11 -0
- package/dist/adapters/react/index.js +133 -0
- package/dist/adapters/react/index.js.map +1 -0
- package/dist/adapters/registry.d.ts +22 -0
- package/dist/adapters/registry.js +101 -0
- package/dist/adapters/registry.js.map +1 -0
- package/dist/adapters/types.d.ts +97 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/analysis/ts/applyVirtualEdit.d.ts +27 -0
- package/dist/analysis/ts/applyVirtualEdit.js +235 -0
- package/dist/analysis/ts/applyVirtualEdit.js.map +1 -0
- package/dist/analysis/ts/changeRecipes.d.ts +52 -0
- package/dist/analysis/ts/changeRecipes.js +14 -0
- package/dist/analysis/ts/changeRecipes.js.map +1 -0
- package/dist/analysis/ts/compatibility.d.ts +54 -0
- package/dist/analysis/ts/compatibility.js +113 -0
- package/dist/analysis/ts/compatibility.js.map +1 -0
- package/dist/analysis/ts/diffDeclarationShape.d.ts +26 -0
- package/dist/analysis/ts/diffDeclarationShape.js +114 -0
- package/dist/analysis/ts/diffDeclarationShape.js.map +1 -0
- package/dist/analysis/ts/exhaustiveness.d.ts +49 -0
- package/dist/analysis/ts/exhaustiveness.js +158 -0
- package/dist/analysis/ts/exhaustiveness.js.map +1 -0
- package/dist/analysis/ts/extractDeclarationShape.d.ts +30 -0
- package/dist/analysis/ts/extractDeclarationShape.js +127 -0
- package/dist/analysis/ts/extractDeclarationShape.js.map +1 -0
- package/dist/analysis/ts/extractExports.d.ts +19 -0
- package/dist/analysis/ts/extractExports.js +178 -0
- package/dist/analysis/ts/extractExports.js.map +1 -0
- package/dist/analysis/ts/extractRoutes.d.ts +12 -0
- package/dist/analysis/ts/extractRoutes.js +165 -0
- package/dist/analysis/ts/extractRoutes.js.map +1 -0
- package/dist/analysis/ts/parseSourceFile.d.ts +5 -1
- package/dist/analysis/ts/parseSourceFile.js +6 -2
- package/dist/analysis/ts/parseSourceFile.js.map +1 -1
- package/dist/analysis/ts/program/CheckerQueries.d.ts +56 -0
- package/dist/analysis/ts/program/CheckerQueries.js +187 -0
- package/dist/analysis/ts/program/CheckerQueries.js.map +1 -0
- package/dist/analysis/ts/program/ProgramManager.d.ts +27 -0
- package/dist/analysis/ts/program/ProgramManager.js +147 -0
- package/dist/analysis/ts/program/ProgramManager.js.map +1 -0
- package/dist/analysis/ts/program/TypeFacts.d.ts +58 -0
- package/dist/analysis/ts/program/TypeFacts.js +68 -0
- package/dist/analysis/ts/program/TypeFacts.js.map +1 -0
- package/dist/analysis/ts/typeState.d.ts +46 -0
- package/dist/analysis/ts/typeState.js +108 -0
- package/dist/analysis/ts/typeState.js.map +1 -0
- package/dist/ast/diffDeclarationShapes.js +25 -11
- package/dist/ast/diffDeclarationShapes.js.map +1 -1
- package/dist/ast/extractExportDeclarations.js +8 -3
- package/dist/ast/extractExportDeclarations.js.map +1 -1
- package/dist/cache/CacheSchema.d.ts +30 -0
- package/dist/cache/CacheSchema.js +9 -0
- package/dist/cache/CacheSchema.js.map +1 -0
- package/dist/cache/CacheStore.d.ts +22 -0
- package/dist/cache/CacheStore.js +111 -0
- package/dist/cache/CacheStore.js.map +1 -0
- package/dist/cache/SemanticCache.d.ts +38 -0
- package/dist/cache/SemanticCache.js +87 -0
- package/dist/cache/SemanticCache.js.map +1 -0
- package/dist/cache/SnapshotFingerprint.d.ts +17 -0
- package/dist/cache/SnapshotFingerprint.js +14 -0
- package/dist/cache/SnapshotFingerprint.js.map +1 -0
- package/dist/engine/DocumentManager.d.ts +16 -0
- package/dist/engine/DocumentManager.js +32 -0
- package/dist/engine/DocumentManager.js.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/search/adapters/http.d.ts +9 -3
- package/dist/search/adapters/http.js +7 -52
- package/dist/search/adapters/http.js.map +1 -1
- package/dist/search/adapters/react.d.ts +8 -8
- package/dist/search/adapters/react.js +3 -88
- package/dist/search/adapters/react.js.map +1 -1
- package/dist/search/adapters/registry.d.ts +7 -4
- package/dist/search/adapters/registry.js +7 -17
- package/dist/search/adapters/registry.js.map +1 -1
- package/dist/search/expand/graphExpansion.js +47 -14
- package/dist/search/expand/graphExpansion.js.map +1 -1
- package/dist/search/index/declarationIndex.d.ts +3 -1
- package/dist/search/index/declarationIndex.js +4 -2
- package/dist/search/index/declarationIndex.js.map +1 -1
- package/dist/search/index/routeIndex.d.ts +6 -0
- package/dist/search/index/routeIndex.js +19 -0
- package/dist/search/index/routeIndex.js.map +1 -0
- package/dist/search/index/usageIndex.d.ts +3 -1
- package/dist/search/index/usageIndex.js +4 -2
- package/dist/search/index/usageIndex.js.map +1 -1
- package/dist/search/index/workspaceIndex.d.ts +7 -1
- package/dist/search/index/workspaceIndex.js +54 -14
- package/dist/search/index/workspaceIndex.js.map +1 -1
- package/dist/search/query/compileEffectiveSearchSpec.js +9 -0
- package/dist/search/query/compileEffectiveSearchSpec.js.map +1 -1
- package/dist/search/query/parseQuery.js +5 -1
- package/dist/search/query/parseQuery.js.map +1 -1
- package/dist/search/query/planQuery.js +14 -4
- package/dist/search/query/planQuery.js.map +1 -1
- package/dist/search/ranking/mergeCandidates.d.ts +1 -0
- package/dist/search/ranking/mergeCandidates.js +16 -0
- package/dist/search/ranking/mergeCandidates.js.map +1 -1
- package/dist/search/retrievers/routeRetriever.d.ts +7 -0
- package/dist/search/retrievers/routeRetriever.js +64 -0
- package/dist/search/retrievers/routeRetriever.js.map +1 -0
- package/dist/search/types.d.ts +16 -4
- package/dist/session/OverlayStore.d.ts +15 -0
- package/dist/session/OverlayStore.js +46 -0
- package/dist/session/OverlayStore.js.map +1 -0
- package/dist/session/SnapshotResolver.d.ts +31 -0
- package/dist/session/SnapshotResolver.js +50 -0
- package/dist/session/SnapshotResolver.js.map +1 -0
- package/dist/session/WorkspaceSnapshot.d.ts +21 -0
- package/dist/session/WorkspaceSnapshot.js +2 -0
- package/dist/session/WorkspaceSnapshot.js.map +1 -0
- package/dist/tools/composites/apiGuard.d.ts +4 -0
- package/dist/tools/composites/apiGuard.js +158 -24
- package/dist/tools/composites/apiGuard.js.map +1 -1
- package/dist/tools/composites/findCode.js +12 -2
- package/dist/tools/composites/findCode.js.map +1 -1
- package/dist/tools/composites/rootCauseTrace.js +89 -13
- package/dist/tools/composites/rootCauseTrace.js.map +1 -1
- package/dist/workflows/simulateChange.d.ts +44 -0
- package/dist/workflows/simulateChange.js +194 -0
- package/dist/workflows/simulateChange.js.map +1 -0
- package/dist/workflows/verifyChangeSet.d.ts +58 -0
- package/dist/workflows/verifyChangeSet.js +300 -0
- package/dist/workflows/verifyChangeSet.js.map +1 -0
- package/package.json +6 -4
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Apply a change recipe to source text.
|
|
4
|
+
* Returns null if the target symbol cannot be found.
|
|
5
|
+
*/
|
|
6
|
+
export function applyVirtualEdit(source, filePath, recipe) {
|
|
7
|
+
switch (recipe.kind) {
|
|
8
|
+
case 'add_required_param':
|
|
9
|
+
case 'add_optional_param':
|
|
10
|
+
return applyAddParam(source, filePath, recipe.funcName, {
|
|
11
|
+
name: recipe.paramName,
|
|
12
|
+
type: recipe.paramType,
|
|
13
|
+
optional: recipe.kind === 'add_optional_param',
|
|
14
|
+
});
|
|
15
|
+
case 'remove_param':
|
|
16
|
+
return applyRemoveParam(source, filePath, recipe.funcName, recipe.paramName);
|
|
17
|
+
case 'add_enum_member':
|
|
18
|
+
return applyAddEnumMember(source, filePath, recipe.enumName, recipe.memberName, recipe.memberValue);
|
|
19
|
+
case 'remove_enum_member':
|
|
20
|
+
return applyRemoveEnumMember(source, filePath, recipe.enumName, recipe.memberName);
|
|
21
|
+
case 'change_return_type':
|
|
22
|
+
return applyChangeReturnType(source, filePath, recipe.funcName, recipe.newReturnType);
|
|
23
|
+
default:
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Recipe implementations
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
function applyAddParam(source, filePath, funcName, param) {
|
|
31
|
+
const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);
|
|
32
|
+
const funcNode = findFunction(sf, funcName);
|
|
33
|
+
if (!funcNode)
|
|
34
|
+
return null;
|
|
35
|
+
const funcStart = funcNode.getStart(sf);
|
|
36
|
+
const funcText = source.slice(funcStart, funcNode.end);
|
|
37
|
+
const openParen = funcText.indexOf('(');
|
|
38
|
+
const closeParen = findMatchingParen(funcText, openParen);
|
|
39
|
+
if (openParen === -1 || closeParen === -1)
|
|
40
|
+
return null;
|
|
41
|
+
const paramListStart = funcStart + openParen + 1;
|
|
42
|
+
const paramListEnd = funcStart + closeParen;
|
|
43
|
+
const existing = source.slice(paramListStart, paramListEnd).trim();
|
|
44
|
+
const newParam = `${param.name}${param.optional ? '?' : ''}: ${param.type}`;
|
|
45
|
+
const newParamList = existing ? `${existing}, ${newParam}` : newParam;
|
|
46
|
+
const modifiedSource = source.slice(0, paramListStart) + newParamList + source.slice(paramListEnd);
|
|
47
|
+
return {
|
|
48
|
+
modifiedSource,
|
|
49
|
+
originalSignature: existing ? `(${existing})` : '()',
|
|
50
|
+
newSignature: `(${newParamList})`,
|
|
51
|
+
editStart: paramListStart,
|
|
52
|
+
editEnd: paramListEnd,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function applyRemoveParam(source, filePath, funcName, paramName) {
|
|
56
|
+
const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);
|
|
57
|
+
const funcNode = findFunction(sf, funcName);
|
|
58
|
+
if (!funcNode)
|
|
59
|
+
return null;
|
|
60
|
+
const funcStart = funcNode.getStart(sf);
|
|
61
|
+
const funcText = source.slice(funcStart, funcNode.end);
|
|
62
|
+
const openParen = funcText.indexOf('(');
|
|
63
|
+
const closeParen = findMatchingParen(funcText, openParen);
|
|
64
|
+
if (openParen === -1 || closeParen === -1)
|
|
65
|
+
return null;
|
|
66
|
+
const paramListStart = funcStart + openParen + 1;
|
|
67
|
+
const paramListEnd = funcStart + closeParen;
|
|
68
|
+
const existing = source.slice(paramListStart, paramListEnd).trim();
|
|
69
|
+
// Simple comma-split removal (handles basic cases)
|
|
70
|
+
const parts = splitParams(existing);
|
|
71
|
+
const newParts = parts.filter((p) => {
|
|
72
|
+
const name = p.trim().split(/[?:]/)[0].replace(/^\.\.\./, '').trim();
|
|
73
|
+
return name !== paramName;
|
|
74
|
+
});
|
|
75
|
+
if (newParts.length === parts.length)
|
|
76
|
+
return null; // param not found
|
|
77
|
+
const newParamList = newParts.join(', ');
|
|
78
|
+
const modifiedSource = source.slice(0, paramListStart) + newParamList + source.slice(paramListEnd);
|
|
79
|
+
return {
|
|
80
|
+
modifiedSource,
|
|
81
|
+
originalSignature: `(${existing})`,
|
|
82
|
+
newSignature: `(${newParamList})`,
|
|
83
|
+
editStart: paramListStart,
|
|
84
|
+
editEnd: paramListEnd,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function applyAddEnumMember(source, filePath, enumName, memberName, memberValue) {
|
|
88
|
+
const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);
|
|
89
|
+
let enumNode;
|
|
90
|
+
ts.forEachChild(sf, (node) => {
|
|
91
|
+
if (ts.isEnumDeclaration(node) && node.name.text === enumName)
|
|
92
|
+
enumNode = node;
|
|
93
|
+
});
|
|
94
|
+
if (!enumNode)
|
|
95
|
+
return null;
|
|
96
|
+
const lastMember = enumNode.members[enumNode.members.length - 1];
|
|
97
|
+
if (!lastMember)
|
|
98
|
+
return null;
|
|
99
|
+
const insertPos = lastMember.end;
|
|
100
|
+
const valueStr = memberValue ? ` = ${memberValue}` : '';
|
|
101
|
+
const memberStr = `,\n ${memberName}${valueStr}`;
|
|
102
|
+
const modifiedSource = source.slice(0, insertPos) + memberStr + source.slice(insertPos);
|
|
103
|
+
const existing = enumNode.members.map((m) => (ts.isIdentifier(m.name) ? m.name.text : m.name.getText(sf))).join(', ');
|
|
104
|
+
return {
|
|
105
|
+
modifiedSource,
|
|
106
|
+
originalSignature: `enum ${enumName} { ${existing} }`,
|
|
107
|
+
newSignature: `enum ${enumName} { ${existing}, ${memberName} }`,
|
|
108
|
+
editStart: insertPos,
|
|
109
|
+
editEnd: insertPos,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function applyRemoveEnumMember(source, filePath, enumName, memberName) {
|
|
113
|
+
const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);
|
|
114
|
+
let enumNode;
|
|
115
|
+
ts.forEachChild(sf, (node) => {
|
|
116
|
+
if (ts.isEnumDeclaration(node) && node.name.text === enumName)
|
|
117
|
+
enumNode = node;
|
|
118
|
+
});
|
|
119
|
+
if (!enumNode)
|
|
120
|
+
return null;
|
|
121
|
+
const member = enumNode.members.find((m) => ts.isIdentifier(m.name) && m.name.text === memberName);
|
|
122
|
+
if (!member)
|
|
123
|
+
return null;
|
|
124
|
+
// Remove the member and the comma before/after it
|
|
125
|
+
let removeStart = member.pos;
|
|
126
|
+
let removeEnd = member.end;
|
|
127
|
+
// Include trailing comma if present
|
|
128
|
+
if (source[removeEnd] === ',')
|
|
129
|
+
removeEnd++;
|
|
130
|
+
// Or include preceding comma
|
|
131
|
+
const beforeMember = source.slice(enumNode.members.pos, member.pos);
|
|
132
|
+
if (beforeMember.trimEnd().endsWith(',')) {
|
|
133
|
+
removeStart = source.lastIndexOf(',', member.pos - 1);
|
|
134
|
+
}
|
|
135
|
+
const modifiedSource = source.slice(0, removeStart) + source.slice(removeEnd);
|
|
136
|
+
const existing = enumNode.members.map((m) => (ts.isIdentifier(m.name) ? m.name.text : m.name.getText(sf))).join(', ');
|
|
137
|
+
return {
|
|
138
|
+
modifiedSource,
|
|
139
|
+
originalSignature: `enum ${enumName} { ${existing} }`,
|
|
140
|
+
newSignature: `enum ${enumName} { ${existing.replace(new RegExp(`(?:,\\s*)?${memberName}(?:,\\s*)?`), '')} }`,
|
|
141
|
+
editStart: removeStart,
|
|
142
|
+
editEnd: removeEnd,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function applyChangeReturnType(source, filePath, funcName, newReturnType) {
|
|
146
|
+
const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true);
|
|
147
|
+
const funcNode = findFunction(sf, funcName);
|
|
148
|
+
if (!funcNode)
|
|
149
|
+
return null;
|
|
150
|
+
const funcStart = funcNode.getStart(sf);
|
|
151
|
+
const funcText = source.slice(funcStart, funcNode.end);
|
|
152
|
+
// Find ): Type { pattern
|
|
153
|
+
const returnTypeMatch = funcText.match(/\)\s*:\s*([^{=>]+?)(\s*(?:\{|=>))/);
|
|
154
|
+
if (!returnTypeMatch)
|
|
155
|
+
return null;
|
|
156
|
+
const matchStart = funcStart + funcText.indexOf(returnTypeMatch[0]);
|
|
157
|
+
const returnTypeStart = matchStart + funcText.indexOf(returnTypeMatch[0]) - funcText.indexOf(returnTypeMatch[0]) + returnTypeMatch[0].indexOf(returnTypeMatch[1]);
|
|
158
|
+
// Simpler: find the colon after the closing ) and replace up to {
|
|
159
|
+
const colonIdx = funcText.lastIndexOf('): ');
|
|
160
|
+
if (colonIdx === -1)
|
|
161
|
+
return null;
|
|
162
|
+
const editStart = funcStart + colonIdx + 2;
|
|
163
|
+
const bodyOrArrowMatch = funcText.slice(colonIdx + 2).match(/^([^{=]+?)(\s*(?:\{|=>))/);
|
|
164
|
+
if (!bodyOrArrowMatch)
|
|
165
|
+
return null;
|
|
166
|
+
const editEnd = editStart + bodyOrArrowMatch[1].length;
|
|
167
|
+
const originalType = source.slice(editStart, editEnd).trim();
|
|
168
|
+
const modifiedSource = source.slice(0, editStart) + ` ${newReturnType} ` + source.slice(editEnd);
|
|
169
|
+
return {
|
|
170
|
+
modifiedSource,
|
|
171
|
+
originalSignature: `(): ${originalType}`,
|
|
172
|
+
newSignature: `(): ${newReturnType}`,
|
|
173
|
+
editStart,
|
|
174
|
+
editEnd,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// Internal helpers
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
function findFunction(sf, funcName) {
|
|
181
|
+
let found;
|
|
182
|
+
ts.forEachChild(sf, (node) => {
|
|
183
|
+
if (found)
|
|
184
|
+
return;
|
|
185
|
+
if (ts.isFunctionDeclaration(node) && node.name?.text === funcName) {
|
|
186
|
+
found = node;
|
|
187
|
+
}
|
|
188
|
+
else if (ts.isVariableStatement(node)) {
|
|
189
|
+
for (const decl of node.declarationList.declarations) {
|
|
190
|
+
if (ts.isIdentifier(decl.name) && decl.name.text === funcName && decl.initializer) {
|
|
191
|
+
if (ts.isArrowFunction(decl.initializer) || ts.isFunctionExpression(decl.initializer)) {
|
|
192
|
+
found = decl.initializer;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
return found;
|
|
199
|
+
}
|
|
200
|
+
function findMatchingParen(text, openPos) {
|
|
201
|
+
let depth = 0;
|
|
202
|
+
for (let i = openPos; i < text.length; i++) {
|
|
203
|
+
if (text[i] === '(')
|
|
204
|
+
depth++;
|
|
205
|
+
if (text[i] === ')') {
|
|
206
|
+
depth--;
|
|
207
|
+
if (depth === 0)
|
|
208
|
+
return i;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return -1;
|
|
212
|
+
}
|
|
213
|
+
function splitParams(paramText) {
|
|
214
|
+
// Split by commas, respecting nested <>, (), {}
|
|
215
|
+
const result = [];
|
|
216
|
+
let depth = 0;
|
|
217
|
+
let current = '';
|
|
218
|
+
for (const ch of paramText) {
|
|
219
|
+
if (ch === ',' && depth === 0) {
|
|
220
|
+
result.push(current);
|
|
221
|
+
current = '';
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
if ('<({'.includes(ch))
|
|
225
|
+
depth++;
|
|
226
|
+
if ('>)}'.includes(ch))
|
|
227
|
+
depth--;
|
|
228
|
+
current += ch;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (current.trim())
|
|
232
|
+
result.push(current);
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=applyVirtualEdit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyVirtualEdit.js","sourceRoot":"","sources":["../../../src/analysis/ts/applyVirtualEdit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 3B — Change recipe definitions.
|
|
3
|
+
*
|
|
4
|
+
* A recipe describes the *intent* of a change: what kind of modification
|
|
5
|
+
* to apply to a symbol. The execution engine in applyVirtualEdit.ts turns
|
|
6
|
+
* a recipe into modified source text. Simulation then rebuilds the semantic
|
|
7
|
+
* state and reports the impact.
|
|
8
|
+
*
|
|
9
|
+
* First recipe (Phase 3B spike): add_required_param
|
|
10
|
+
* Future recipes: remove_param, change_return_type, add_enum_member, remove_enum_member,
|
|
11
|
+
* narrow_union, widen_union, move_export, rename_symbol
|
|
12
|
+
*/
|
|
13
|
+
export type RecipeKind = 'add_required_param' | 'add_optional_param' | 'remove_param' | 'change_return_type' | 'add_enum_member' | 'remove_enum_member' | 'rename_symbol' | 'narrow_union' | 'widen_union';
|
|
14
|
+
export interface AddParamRecipe {
|
|
15
|
+
kind: 'add_required_param' | 'add_optional_param';
|
|
16
|
+
funcName: string;
|
|
17
|
+
filePath: string;
|
|
18
|
+
paramName: string;
|
|
19
|
+
paramType: string;
|
|
20
|
+
}
|
|
21
|
+
export interface RemoveParamRecipe {
|
|
22
|
+
kind: 'remove_param';
|
|
23
|
+
funcName: string;
|
|
24
|
+
filePath: string;
|
|
25
|
+
paramName: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ChangeReturnTypeRecipe {
|
|
28
|
+
kind: 'change_return_type';
|
|
29
|
+
funcName: string;
|
|
30
|
+
filePath: string;
|
|
31
|
+
newReturnType: string;
|
|
32
|
+
}
|
|
33
|
+
export interface AddEnumMemberRecipe {
|
|
34
|
+
kind: 'add_enum_member';
|
|
35
|
+
enumName: string;
|
|
36
|
+
filePath: string;
|
|
37
|
+
memberName: string;
|
|
38
|
+
memberValue?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface RemoveEnumMemberRecipe {
|
|
41
|
+
kind: 'remove_enum_member';
|
|
42
|
+
enumName: string;
|
|
43
|
+
filePath: string;
|
|
44
|
+
memberName: string;
|
|
45
|
+
}
|
|
46
|
+
export interface RenameSymbolRecipe {
|
|
47
|
+
kind: 'rename_symbol';
|
|
48
|
+
symbolName: string;
|
|
49
|
+
filePath: string;
|
|
50
|
+
newName: string;
|
|
51
|
+
}
|
|
52
|
+
export type ChangeRecipe = AddParamRecipe | RemoveParamRecipe | ChangeReturnTypeRecipe | AddEnumMemberRecipe | RemoveEnumMemberRecipe | RenameSymbolRecipe;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 3B — Change recipe definitions.
|
|
3
|
+
*
|
|
4
|
+
* A recipe describes the *intent* of a change: what kind of modification
|
|
5
|
+
* to apply to a symbol. The execution engine in applyVirtualEdit.ts turns
|
|
6
|
+
* a recipe into modified source text. Simulation then rebuilds the semantic
|
|
7
|
+
* state and reports the impact.
|
|
8
|
+
*
|
|
9
|
+
* First recipe (Phase 3B spike): add_required_param
|
|
10
|
+
* Future recipes: remove_param, change_return_type, add_enum_member, remove_enum_member,
|
|
11
|
+
* narrow_union, widen_union, move_export, rename_symbol
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=changeRecipes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changeRecipes.js","sourceRoot":"","sources":["../../../src/analysis/ts/changeRecipes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Phase 2D — Type compatibility intelligence.
|
|
4
|
+
*
|
|
5
|
+
* Answers: "Would this type change break existing callers?"
|
|
6
|
+
* Uses the TypeScript checker to determine assignability, not just structural text.
|
|
7
|
+
*
|
|
8
|
+
* This is a key "smarter than graph" capability: a graph product can find callers
|
|
9
|
+
* but cannot determine which callers would actually break due to a type change.
|
|
10
|
+
*/
|
|
11
|
+
export interface CallSiteResult {
|
|
12
|
+
filePath: string;
|
|
13
|
+
line: number;
|
|
14
|
+
/** Argument count passed at this call site */
|
|
15
|
+
argCount: number;
|
|
16
|
+
/** Whether this call site is compatible with the new signature */
|
|
17
|
+
compatible: boolean;
|
|
18
|
+
/** Human-readable explanation if not compatible */
|
|
19
|
+
issue: string | null;
|
|
20
|
+
}
|
|
21
|
+
export interface CompatibilityReport {
|
|
22
|
+
funcName: string;
|
|
23
|
+
filePath: string;
|
|
24
|
+
/** Total callers found */
|
|
25
|
+
callerCount: number;
|
|
26
|
+
/** Callers that would break */
|
|
27
|
+
breakingCallers: CallSiteResult[];
|
|
28
|
+
/** Callers that are still compatible */
|
|
29
|
+
compatibleCallers: CallSiteResult[];
|
|
30
|
+
/** Minimum required arity */
|
|
31
|
+
requiredArity: number;
|
|
32
|
+
/** Max arity */
|
|
33
|
+
maxArity: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Find all call sites of a function and classify them as compatible or breaking,
|
|
37
|
+
* given the function's new signature (required params, max arity).
|
|
38
|
+
*
|
|
39
|
+
* Use case: after detecting a `param_required` change via api_guard, determine
|
|
40
|
+
* exactly which callers now pass too few arguments.
|
|
41
|
+
*/
|
|
42
|
+
export declare function analyzeCallSiteCompatibility(program: ts.Program, funcFilePath: string, funcName: string, newMinArity: number, newMaxArity: number): CompatibilityReport;
|
|
43
|
+
/**
|
|
44
|
+
* Determine if a parameter type change is backward-compatible.
|
|
45
|
+
* Checks assignability in both directions using the TypeScript checker.
|
|
46
|
+
*
|
|
47
|
+
* Returns:
|
|
48
|
+
* - 'widening' — new type accepts more values (compatible for existing callers)
|
|
49
|
+
* - 'narrowing' — new type accepts fewer values (breaking for some callers)
|
|
50
|
+
* - 'incompatible' — types are unrelated (breaking)
|
|
51
|
+
* - 'equivalent' — types are the same
|
|
52
|
+
* - 'unknown' — cannot determine
|
|
53
|
+
*/
|
|
54
|
+
export declare function classifyTypeChange(program: ts.Program, contextFilePath: string, oldTypeText: string, newTypeText: string): 'widening' | 'narrowing' | 'incompatible' | 'equivalent' | 'unknown';
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Find all call sites of a function and classify them as compatible or breaking,
|
|
4
|
+
* given the function's new signature (required params, max arity).
|
|
5
|
+
*
|
|
6
|
+
* Use case: after detecting a `param_required` change via api_guard, determine
|
|
7
|
+
* exactly which callers now pass too few arguments.
|
|
8
|
+
*/
|
|
9
|
+
export function analyzeCallSiteCompatibility(program, funcFilePath, funcName, newMinArity, newMaxArity) {
|
|
10
|
+
const breakingCallers = [];
|
|
11
|
+
const compatibleCallers = [];
|
|
12
|
+
for (const sf of program.getSourceFiles()) {
|
|
13
|
+
if (sf.fileName.includes('node_modules') || sf.fileName.endsWith('.d.ts'))
|
|
14
|
+
continue;
|
|
15
|
+
ts.forEachChild(sf, function visitNode(node) {
|
|
16
|
+
if (ts.isCallExpression(node)) {
|
|
17
|
+
const calleeName = extractCalleeName(node.expression);
|
|
18
|
+
if (calleeName === funcName) {
|
|
19
|
+
const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
|
|
20
|
+
const argCount = node.arguments.length;
|
|
21
|
+
const compatible = argCount >= newMinArity && argCount <= newMaxArity;
|
|
22
|
+
const result = {
|
|
23
|
+
filePath: sf.fileName,
|
|
24
|
+
line,
|
|
25
|
+
argCount,
|
|
26
|
+
compatible,
|
|
27
|
+
issue: compatible
|
|
28
|
+
? null
|
|
29
|
+
: argCount < newMinArity
|
|
30
|
+
? `Too few args: ${argCount} passed, ${newMinArity} required`
|
|
31
|
+
: `Too many args: ${argCount} passed, max ${newMaxArity}`,
|
|
32
|
+
};
|
|
33
|
+
if (compatible)
|
|
34
|
+
compatibleCallers.push(result);
|
|
35
|
+
else
|
|
36
|
+
breakingCallers.push(result);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
ts.forEachChild(node, visitNode);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
funcName,
|
|
44
|
+
filePath: funcFilePath,
|
|
45
|
+
callerCount: breakingCallers.length + compatibleCallers.length,
|
|
46
|
+
breakingCallers,
|
|
47
|
+
compatibleCallers,
|
|
48
|
+
requiredArity: newMinArity,
|
|
49
|
+
maxArity: newMaxArity,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Determine if a parameter type change is backward-compatible.
|
|
54
|
+
* Checks assignability in both directions using the TypeScript checker.
|
|
55
|
+
*
|
|
56
|
+
* Returns:
|
|
57
|
+
* - 'widening' — new type accepts more values (compatible for existing callers)
|
|
58
|
+
* - 'narrowing' — new type accepts fewer values (breaking for some callers)
|
|
59
|
+
* - 'incompatible' — types are unrelated (breaking)
|
|
60
|
+
* - 'equivalent' — types are the same
|
|
61
|
+
* - 'unknown' — cannot determine
|
|
62
|
+
*/
|
|
63
|
+
export function classifyTypeChange(program, contextFilePath, oldTypeText, newTypeText) {
|
|
64
|
+
const sf = program.getSourceFile(contextFilePath);
|
|
65
|
+
if (!sf)
|
|
66
|
+
return 'unknown';
|
|
67
|
+
const checker = program.getTypeChecker();
|
|
68
|
+
try {
|
|
69
|
+
// Create synthetic type nodes and check assignability using the checker
|
|
70
|
+
// We use a heuristic based on type text comparison first for common cases
|
|
71
|
+
if (oldTypeText === newTypeText)
|
|
72
|
+
return 'equivalent';
|
|
73
|
+
// Simple heuristic: union widening (string | number vs string)
|
|
74
|
+
const oldIsSubset = isTypeSubsetHeuristic(oldTypeText, newTypeText);
|
|
75
|
+
const newIsSubset = isTypeSubsetHeuristic(newTypeText, oldTypeText);
|
|
76
|
+
if (oldIsSubset && newIsSubset)
|
|
77
|
+
return 'equivalent';
|
|
78
|
+
if (newIsSubset && !oldIsSubset)
|
|
79
|
+
return 'narrowing'; // new is stricter
|
|
80
|
+
if (oldIsSubset && !newIsSubset)
|
|
81
|
+
return 'widening'; // new is broader
|
|
82
|
+
return 'incompatible';
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return 'unknown';
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// Internal helpers
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
function extractCalleeName(expr) {
|
|
92
|
+
if (ts.isIdentifier(expr))
|
|
93
|
+
return expr.text;
|
|
94
|
+
if (ts.isPropertyAccessExpression(expr))
|
|
95
|
+
return expr.name.text;
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Heuristic: does typeA appear to be a subset of typeB?
|
|
100
|
+
* E.g., 'string' is a subset of 'string | number'.
|
|
101
|
+
* This is approximate — use the TypeScript checker for precise results.
|
|
102
|
+
*/
|
|
103
|
+
function isTypeSubsetHeuristic(typeA, typeB) {
|
|
104
|
+
// Exact match
|
|
105
|
+
if (typeA === typeB)
|
|
106
|
+
return true;
|
|
107
|
+
// typeA is in a union that contains typeB
|
|
108
|
+
const bParts = typeB.split('|').map((p) => p.trim());
|
|
109
|
+
const aParts = typeA.split('|').map((p) => p.trim());
|
|
110
|
+
// Every part of A must be in B
|
|
111
|
+
return aParts.every((a) => bParts.some((b) => b === a || b === typeA));
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=compatibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compatibility.js","sourceRoot":"","sources":["../../../src/analysis/ts/compatibility.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { DeclarationShape } from './extractDeclarationShape.js';
|
|
2
|
+
export type DeclRisk = 'breaking' | 'risky' | 'safe';
|
|
3
|
+
export interface DeclarationDiff {
|
|
4
|
+
kind: 'added' | 'removed' | 'renamed' | 'param_added' | 'param_removed' | 'param_required' | 'return_type_changed' | 'interface_shape_changed' | 'enum_member_added' | 'enum_member_removed' | 'reexport_changed' | 'type_changed' | 'signature_changed' | 'unknown';
|
|
5
|
+
/** Semantic risk level of this change. */
|
|
6
|
+
risk: DeclRisk;
|
|
7
|
+
reason: string;
|
|
8
|
+
details: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Diff two declaration shapes and return a list of changes.
|
|
12
|
+
*/
|
|
13
|
+
export declare function diffDeclarationShapes(base: DeclarationShape, current: DeclarationShape): DeclarationDiff[];
|
|
14
|
+
export interface ExportSetDiff {
|
|
15
|
+
name: string;
|
|
16
|
+
status: 'added' | 'removed' | 'changed';
|
|
17
|
+
risk: DeclRisk;
|
|
18
|
+
diffs: DeclarationDiff[];
|
|
19
|
+
baseShape?: DeclarationShape;
|
|
20
|
+
currentShape?: DeclarationShape;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Diff two sets of exports: find added, removed, and changed declarations.
|
|
24
|
+
* Each result includes risk, the originating shapes, and per-change diffs.
|
|
25
|
+
*/
|
|
26
|
+
export declare function diffExportSets(baseShapes: DeclarationShape[], currentShapes: DeclarationShape[]): ExportSetDiff[];
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diff two declaration shapes and return a list of changes.
|
|
3
|
+
*/
|
|
4
|
+
export function diffDeclarationShapes(base, current) {
|
|
5
|
+
const diffs = [];
|
|
6
|
+
// Name changed
|
|
7
|
+
if (base.name !== current.name) {
|
|
8
|
+
diffs.push({ kind: 'renamed', risk: 'breaking', reason: `Renamed from "${base.name}" to "${current.name}"`, details: [`base: ${base.name}`, `current: ${current.name}`] });
|
|
9
|
+
}
|
|
10
|
+
// Params changed (functions)
|
|
11
|
+
if (base.params && current.params) {
|
|
12
|
+
// New params (required or optional)
|
|
13
|
+
for (const cp of current.params) {
|
|
14
|
+
const bp = base.params.find((p) => p.name === cp.name);
|
|
15
|
+
if (!bp && !cp.optional) {
|
|
16
|
+
diffs.push({ kind: 'param_required', risk: 'breaking', reason: `New required parameter "${cp.name}"`, details: [`param: ${cp.name}`, `type: ${cp.typeText ?? 'unknown'}`] });
|
|
17
|
+
}
|
|
18
|
+
else if (!bp && cp.optional) {
|
|
19
|
+
diffs.push({ kind: 'param_added', risk: 'safe', reason: `New optional parameter "${cp.name}"`, details: [`param: ${cp.name}`, `type: ${cp.typeText ?? 'unknown'}`] });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// Removed params
|
|
23
|
+
for (const bp of base.params) {
|
|
24
|
+
if (!current.params.find((p) => p.name === bp.name)) {
|
|
25
|
+
diffs.push({ kind: 'param_removed', risk: 'breaking', reason: `Parameter "${bp.name}" removed`, details: [`param: ${bp.name}`] });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Optional → required
|
|
29
|
+
for (const cp of current.params) {
|
|
30
|
+
const bp = base.params.find((p) => p.name === cp.name);
|
|
31
|
+
if (bp && bp.optional && !cp.optional) {
|
|
32
|
+
diffs.push({ kind: 'param_required', risk: 'breaking', reason: `Parameter "${cp.name}" became required (was optional)`, details: [`param: ${cp.name}`] });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Return type changed
|
|
37
|
+
if (base.returnTypeText && current.returnTypeText && base.returnTypeText !== current.returnTypeText) {
|
|
38
|
+
diffs.push({ kind: 'return_type_changed', risk: 'risky', reason: `Return type changed from "${base.returnTypeText}" to "${current.returnTypeText}"`, details: [`base: ${base.returnTypeText}`, `current: ${current.returnTypeText}`] });
|
|
39
|
+
}
|
|
40
|
+
// Interface members changed
|
|
41
|
+
if (base.members && current.members) {
|
|
42
|
+
const baseByName = new Map(base.members.map((m) => [m.name, m]));
|
|
43
|
+
const currentByName = new Map(current.members.map((m) => [m.name, m]));
|
|
44
|
+
for (const [name, cm] of currentByName) {
|
|
45
|
+
const bm = baseByName.get(name);
|
|
46
|
+
if (!bm) {
|
|
47
|
+
if (!cm.optional) {
|
|
48
|
+
diffs.push({ kind: 'interface_shape_changed', risk: 'breaking', reason: `Required interface property "${name}" added — breaking for existing implementations`, details: [`property: ${name}`, `type: ${cm.typeText ?? 'unknown'}`] });
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
diffs.push({ kind: 'interface_shape_changed', risk: 'risky', reason: `Optional interface property "${name}" added`, details: [`property: ${name}`] });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else if (bm.optional && !cm.optional) {
|
|
55
|
+
diffs.push({ kind: 'interface_shape_changed', risk: 'breaking', reason: `Interface property "${name}" became required (was optional)`, details: [`property: ${name}`] });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (const [name] of baseByName) {
|
|
59
|
+
if (!currentByName.has(name)) {
|
|
60
|
+
diffs.push({ kind: 'interface_shape_changed', risk: 'breaking', reason: `Interface property "${name}" removed`, details: [`property: ${name}`] });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Enum members changed
|
|
65
|
+
if (base.enumMembers && current.enumMembers) {
|
|
66
|
+
const added = current.enumMembers.filter((m) => !base.enumMembers.includes(m));
|
|
67
|
+
const removed = base.enumMembers.filter((m) => !current.enumMembers.includes(m));
|
|
68
|
+
for (const m of added) {
|
|
69
|
+
diffs.push({ kind: 'enum_member_added', risk: 'risky', reason: `Enum member "${m}" added — exhaustive handling may be incomplete`, details: [m] });
|
|
70
|
+
}
|
|
71
|
+
for (const m of removed) {
|
|
72
|
+
diffs.push({ kind: 'enum_member_removed', risk: 'breaking', reason: `Enum member "${m}" removed`, details: [m] });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Signature text changed (catch-all)
|
|
76
|
+
if (diffs.length === 0 && base.signatureText !== current.signatureText) {
|
|
77
|
+
diffs.push({ kind: 'signature_changed', risk: 'risky', reason: 'Declaration signature changed', details: [`base: ${base.signatureText}`, `current: ${current.signatureText}`] });
|
|
78
|
+
}
|
|
79
|
+
return diffs;
|
|
80
|
+
}
|
|
81
|
+
const RISK_ORDER = { breaking: 2, risky: 1, safe: 0 };
|
|
82
|
+
function worstRisk(diffs) {
|
|
83
|
+
return diffs.reduce((worst, d) => RISK_ORDER[d.risk] > RISK_ORDER[worst] ? d.risk : worst, 'safe');
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Diff two sets of exports: find added, removed, and changed declarations.
|
|
87
|
+
* Each result includes risk, the originating shapes, and per-change diffs.
|
|
88
|
+
*/
|
|
89
|
+
export function diffExportSets(baseShapes, currentShapes) {
|
|
90
|
+
const results = [];
|
|
91
|
+
const baseByName = new Map(baseShapes.map((s) => [s.name, s]));
|
|
92
|
+
const currentByName = new Map(currentShapes.map((s) => [s.name, s]));
|
|
93
|
+
for (const [name, baseShape] of baseByName) {
|
|
94
|
+
if (!currentByName.has(name)) {
|
|
95
|
+
results.push({ name, status: 'removed', risk: 'breaking', diffs: [{ kind: 'removed', risk: 'breaking', reason: `Export "${name}" (${baseShape.kind}) was removed`, details: [] }], baseShape });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
for (const [name, currentShape] of currentByName) {
|
|
99
|
+
if (!baseByName.has(name)) {
|
|
100
|
+
results.push({ name, status: 'added', risk: 'safe', diffs: [{ kind: 'added', risk: 'safe', reason: `New export "${name}" (${currentShape.kind})`, details: [] }], currentShape });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
for (const [name, currentShape] of currentByName) {
|
|
104
|
+
const baseShape = baseByName.get(name);
|
|
105
|
+
if (baseShape) {
|
|
106
|
+
const diffs = diffDeclarationShapes(baseShape, currentShape);
|
|
107
|
+
if (diffs.length > 0) {
|
|
108
|
+
results.push({ name, status: 'changed', risk: worstRisk(diffs), diffs, baseShape, currentShape });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return results;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=diffDeclarationShape.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diffDeclarationShape.js","sourceRoot":"","sources":["../../../src/analysis/ts/diffDeclarationShape.ts"],"names":[],"mappings":"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"}
|