lsp-intelligence 0.2.1 → 0.3.2
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/.claude-plugin/marketplace.json +18 -0
- package/.claude-plugin/plugin.json +11 -0
- package/CLAUDE.md +75 -0
- package/README.md +15 -38
- 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/hooks/hooks.json +25 -0
- package/hooks/post-edit-check.sh +23 -0
- package/package.json +20 -4
- package/scripts/launch.mjs +29 -0
- package/skills/api-check/SKILL.md +34 -0
- package/skills/check/SKILL.md +25 -0
- package/skills/context/SKILL.md +24 -0
- package/skills/diff/SKILL.md +27 -0
- package/skills/find/SKILL.md +63 -0
- package/skills/impact/SKILL.md +21 -0
- package/skills/verify/SKILL.md +54 -0
- package/skills/why/SKILL.md +31 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { QueryIR, SearchRecipe } from '../search/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Phase 2E — IntelligenceAdapter v2 interface.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the narrow SearchAdapter (search-recipe-only) with a composable
|
|
6
|
+
* adapter that can contribute to every layer of the engine:
|
|
7
|
+
* search, graph, explain, guard, verify.
|
|
8
|
+
*
|
|
9
|
+
* Migration policy:
|
|
10
|
+
* When an adapter contributes at least one non-recipe capability (e.g. graph.denylist),
|
|
11
|
+
* the corresponding old src/search/adapters/* file must be reduced to a thin
|
|
12
|
+
* re-export within one sprint.
|
|
13
|
+
*/
|
|
14
|
+
export interface IntelligenceAdapter {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
/**
|
|
17
|
+
* Emit search recipes for queries that match this adapter's domain.
|
|
18
|
+
* Equivalent to the old SearchAdapter.detect().
|
|
19
|
+
*/
|
|
20
|
+
detect?(ir: QueryIR): SearchRecipe[];
|
|
21
|
+
/**
|
|
22
|
+
* Contribute additional IR enrichment beyond what the query parser produces.
|
|
23
|
+
* Useful for framework-specific token classification.
|
|
24
|
+
*/
|
|
25
|
+
enrichQuery?(ir: QueryIR): AdapterQueryContribution;
|
|
26
|
+
graph?: {
|
|
27
|
+
/**
|
|
28
|
+
* Symbols that should NEVER be promoted as implementation roots.
|
|
29
|
+
* The engine skips these during graph expansion.
|
|
30
|
+
* React: memo, forwardRef, createContext, etc.
|
|
31
|
+
* Express: Router, app.use, etc.
|
|
32
|
+
*/
|
|
33
|
+
denylist?: string[];
|
|
34
|
+
/**
|
|
35
|
+
* Symbol name patterns that ARE likely real implementation roots for this domain.
|
|
36
|
+
* Used to boost candidates during graph expansion.
|
|
37
|
+
*/
|
|
38
|
+
rootHints?: string[];
|
|
39
|
+
};
|
|
40
|
+
explain?: {
|
|
41
|
+
/**
|
|
42
|
+
* Hints that help root_cause_trace identify likely cause categories
|
|
43
|
+
* for framework-specific error patterns.
|
|
44
|
+
*/
|
|
45
|
+
causeHints?: AdapterCauseHint[];
|
|
46
|
+
};
|
|
47
|
+
guard?: {
|
|
48
|
+
/**
|
|
49
|
+
* Extra rules that api_guard applies when checking contracts.
|
|
50
|
+
* E.g. React: prop type changes are always consumer-breaking.
|
|
51
|
+
*/
|
|
52
|
+
rules?: AdapterGuardRule[];
|
|
53
|
+
};
|
|
54
|
+
verify?: {
|
|
55
|
+
/**
|
|
56
|
+
* Checks that verify_changes runs for this framework's idioms.
|
|
57
|
+
* E.g. React: no conditional hooks, exhaustive useEffect deps.
|
|
58
|
+
*/
|
|
59
|
+
checks?: AdapterVerifyCheck[];
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export interface AdapterQueryContribution {
|
|
63
|
+
/** Additional exact identifiers to include */
|
|
64
|
+
extraIdentifiers?: string[];
|
|
65
|
+
/** Additional behavior terms to score against */
|
|
66
|
+
extraBehaviorTerms?: string[];
|
|
67
|
+
/** Additional config terms for config/env retrieval */
|
|
68
|
+
extraConfigTerms?: string[];
|
|
69
|
+
}
|
|
70
|
+
export interface AdapterCauseHint {
|
|
71
|
+
/** TypeScript diagnostic code this hint applies to (e.g. '2345') */
|
|
72
|
+
matchCode?: string;
|
|
73
|
+
/** Pattern matched against the diagnostic message */
|
|
74
|
+
matchMessage?: RegExp;
|
|
75
|
+
/** Short human-readable category label */
|
|
76
|
+
causeCategory: string;
|
|
77
|
+
/** Actionable hint for the developer */
|
|
78
|
+
hint: string;
|
|
79
|
+
/** Score boost applied to candidates matching this hint */
|
|
80
|
+
scoreBoost: number;
|
|
81
|
+
}
|
|
82
|
+
export interface AdapterGuardRule {
|
|
83
|
+
id: string;
|
|
84
|
+
description: string;
|
|
85
|
+
}
|
|
86
|
+
export interface AdapterVerifyCheck {
|
|
87
|
+
id: string;
|
|
88
|
+
description: string;
|
|
89
|
+
/** Run the check and return issues found */
|
|
90
|
+
run(filePaths: string[]): AdapterVerifyIssue[];
|
|
91
|
+
}
|
|
92
|
+
export interface AdapterVerifyIssue {
|
|
93
|
+
filePath: string;
|
|
94
|
+
line?: number;
|
|
95
|
+
message: string;
|
|
96
|
+
severity: 'error' | 'warning';
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ChangeRecipe } from './changeRecipes.js';
|
|
2
|
+
/**
|
|
3
|
+
* Phase 3B — Apply a change recipe to source text without touching disk.
|
|
4
|
+
*
|
|
5
|
+
* Returns modified source content as a string, or null if the recipe
|
|
6
|
+
* cannot be applied (symbol not found, ambiguous match, etc.).
|
|
7
|
+
*
|
|
8
|
+
* The output is used to build a SnapshotResolver overlay so the TypeScript
|
|
9
|
+
* program reflects the hypothetical change for semantic analysis.
|
|
10
|
+
*/
|
|
11
|
+
export interface VirtualEditResult {
|
|
12
|
+
/** The modified source text */
|
|
13
|
+
modifiedSource: string;
|
|
14
|
+
/** Original signature text (for diff display) */
|
|
15
|
+
originalSignature: string;
|
|
16
|
+
/** New signature text after the change */
|
|
17
|
+
newSignature: string;
|
|
18
|
+
/** 0-indexed start position of the edit in the original source */
|
|
19
|
+
editStart: number;
|
|
20
|
+
/** 0-indexed end position (exclusive) in the original source */
|
|
21
|
+
editEnd: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Apply a change recipe to source text.
|
|
25
|
+
* Returns null if the target symbol cannot be found.
|
|
26
|
+
*/
|
|
27
|
+
export declare function applyVirtualEdit(source: string, filePath: string, recipe: ChangeRecipe): VirtualEditResult | null;
|
|
@@ -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[];
|