skannr 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +22 -0
- package/README.md +109 -0
- package/dist/agent-cli.d.ts +7 -0
- package/dist/agent-cli.d.ts.map +1 -0
- package/dist/agent-cli.js +364 -0
- package/dist/agent-cli.js.map +1 -0
- package/dist/agent.d.ts +115 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +340 -0
- package/dist/agent.js.map +1 -0
- package/dist/benchmark.d.ts +53 -0
- package/dist/benchmark.d.ts.map +1 -0
- package/dist/benchmark.js +307 -0
- package/dist/benchmark.js.map +1 -0
- package/dist/cache.d.ts +97 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +284 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +238 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +52 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +176 -0
- package/dist/index.js.map +1 -0
- package/dist/languages/GenericAdapter.d.ts +10 -0
- package/dist/languages/GenericAdapter.d.ts.map +1 -0
- package/dist/languages/GenericAdapter.js +41 -0
- package/dist/languages/GenericAdapter.js.map +1 -0
- package/dist/languages/LanguageAdapter.d.ts +14 -0
- package/dist/languages/LanguageAdapter.d.ts.map +1 -0
- package/dist/languages/LanguageAdapter.js +3 -0
- package/dist/languages/LanguageAdapter.js.map +1 -0
- package/dist/languages/PythonAdapter.d.ts +10 -0
- package/dist/languages/PythonAdapter.d.ts.map +1 -0
- package/dist/languages/PythonAdapter.js +98 -0
- package/dist/languages/PythonAdapter.js.map +1 -0
- package/dist/languages/TypeScriptAdapter.d.ts +17 -0
- package/dist/languages/TypeScriptAdapter.d.ts.map +1 -0
- package/dist/languages/TypeScriptAdapter.js +321 -0
- package/dist/languages/TypeScriptAdapter.js.map +1 -0
- package/dist/languages/registry.d.ts +4 -0
- package/dist/languages/registry.d.ts.map +1 -0
- package/dist/languages/registry.js +86 -0
- package/dist/languages/registry.js.map +1 -0
- package/dist/mapper.d.ts +49 -0
- package/dist/mapper.d.ts.map +1 -0
- package/dist/mapper.js +386 -0
- package/dist/mapper.js.map +1 -0
- package/dist/ranker-enhanced.d.ts +37 -0
- package/dist/ranker-enhanced.d.ts.map +1 -0
- package/dist/ranker-enhanced.js +395 -0
- package/dist/ranker-enhanced.js.map +1 -0
- package/dist/ranker.d.ts +14 -0
- package/dist/ranker.d.ts.map +1 -0
- package/dist/ranker.js +105 -0
- package/dist/ranker.js.map +1 -0
- package/dist/rocket-chat-scope.d.ts +7 -0
- package/dist/rocket-chat-scope.d.ts.map +1 -0
- package/dist/rocket-chat-scope.js +95 -0
- package/dist/rocket-chat-scope.js.map +1 -0
- package/dist/scanner.d.ts +16 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +228 -0
- package/dist/scanner.js.map +1 -0
- package/dist/skeletonizer.d.ts +5 -0
- package/dist/skeletonizer.d.ts.map +1 -0
- package/dist/skeletonizer.js +52 -0
- package/dist/skeletonizer.js.map +1 -0
- package/dist/tokenizer.d.ts +9 -0
- package/dist/tokenizer.d.ts.map +1 -0
- package/dist/tokenizer.js +21 -0
- package/dist/tokenizer.js.map +1 -0
- package/dist/types.d.ts +68 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/gemini-extension/GEMINI.md +26 -0
- package/gemini-extension/gemini-extension.json +12 -0
- package/gemini-extension/package.json +14 -0
- package/gemini-extension/src/server.ts +63 -0
- package/gemini-extension/tsconfig.json +14 -0
- package/jest.config.js +5 -0
- package/package.json +46 -0
- package/src/agent-cli.ts +383 -0
- package/src/agent.ts +344 -0
- package/src/benchmark.ts +389 -0
- package/src/cache.ts +317 -0
- package/src/cli.ts +223 -0
- package/src/config.ts +22 -0
- package/src/index.ts +215 -0
- package/src/languages/GenericAdapter.ts +44 -0
- package/src/languages/LanguageAdapter.ts +14 -0
- package/src/languages/PythonAdapter.ts +74 -0
- package/src/languages/TypeScriptAdapter.ts +338 -0
- package/src/languages/registry.ts +49 -0
- package/src/mapper.ts +448 -0
- package/src/ranker-enhanced.ts +460 -0
- package/src/ranker.ts +92 -0
- package/src/scanner.ts +201 -0
- package/src/skeletonizer.ts +16 -0
- package/src/tokenizer.ts +20 -0
- package/src/types.ts +71 -0
- package/tests/agent.tools.test.ts +81 -0
- package/tests/benchmark.test.ts +31 -0
- package/tests/fixtures/sample.py +17 -0
- package/tests/fixtures/sample.ts +13 -0
- package/tests/fixtures/src/api/routes.ts +1 -0
- package/tests/fixtures/src/auth/permission.ts +3 -0
- package/tests/ranker-enhanced.test.ts +68 -0
- package/tests/ranker.test.ts +75 -0
- package/tests/scanner.scope.test.ts +41 -0
- package/tests/setup-fixtures.js +29 -0
- package/tests/skeletonizer.test.ts +142 -0
- package/tsconfig.json +21 -0
- package/uca-landing/index.html +17 -0
- package/uca-landing/package.json +23 -0
- package/uca-landing/postcss.config.js +6 -0
- package/uca-landing/src/App.jsx +43 -0
- package/uca-landing/src/components/AgentMode.jsx +45 -0
- package/uca-landing/src/components/CliReference.jsx +49 -0
- package/uca-landing/src/components/Features.jsx +63 -0
- package/uca-landing/src/components/Footer.jsx +35 -0
- package/uca-landing/src/components/Hero.jsx +124 -0
- package/uca-landing/src/components/HowItWorks.jsx +60 -0
- package/uca-landing/src/components/Install.jsx +90 -0
- package/uca-landing/src/components/LanguageSupport.jsx +63 -0
- package/uca-landing/src/components/Navbar.jsx +86 -0
- package/uca-landing/src/components/Problem.jsx +51 -0
- package/uca-landing/src/components/Reveal.jsx +40 -0
- package/uca-landing/src/components/WorksWith.jsx +59 -0
- package/uca-landing/src/hooks/useScrollNav.js +13 -0
- package/uca-landing/src/hooks/useTypewriter.js +41 -0
- package/uca-landing/src/index.css +13 -0
- package/uca-landing/src/main.jsx +10 -0
- package/uca-landing/tailwind.config.js +68 -0
- package/uca-landing/vite.config.js +6 -0
package/src/mapper.ts
ADDED
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Symbol mapping system for on-demand code retrieval
|
|
3
|
+
* Tracks locations of all code blocks that were trimmed in skeletons
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Project, SourceFile, SyntaxKind } from 'ts-morph';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import * as fs from 'fs';
|
|
9
|
+
|
|
10
|
+
export interface SymbolLocation {
|
|
11
|
+
symbolId: string;
|
|
12
|
+
symbolName: string;
|
|
13
|
+
symbolType: 'function' | 'method' | 'constructor' | 'arrow-function' | 'variable';
|
|
14
|
+
filePath: string;
|
|
15
|
+
startLine: number;
|
|
16
|
+
endLine: number;
|
|
17
|
+
startPos: number;
|
|
18
|
+
endPos: number;
|
|
19
|
+
parentClass?: string;
|
|
20
|
+
signature?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface SymbolMapping {
|
|
24
|
+
generatedAt: string;
|
|
25
|
+
rootPath: string;
|
|
26
|
+
files: {
|
|
27
|
+
[filePath: string]: {
|
|
28
|
+
originalPath: string;
|
|
29
|
+
symbols: SymbolLocation[];
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Build skeleton with symbol mapping for on-demand retrieval
|
|
36
|
+
*/
|
|
37
|
+
export function buildSkeletonWithMapping(
|
|
38
|
+
filePath: string,
|
|
39
|
+
rootPath: string
|
|
40
|
+
): { skeleton: string; symbols: SymbolLocation[] } {
|
|
41
|
+
const symbols: SymbolLocation[] = [];
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const project = new Project({
|
|
45
|
+
skipAddingFilesFromTsConfig: true,
|
|
46
|
+
compilerOptions: {
|
|
47
|
+
allowJs: true,
|
|
48
|
+
checkJs: false,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const sourceFile = project.addSourceFileAtPath(filePath);
|
|
53
|
+
const skeleton = generateSkeletonWithMapping(sourceFile, filePath, symbols, rootPath);
|
|
54
|
+
|
|
55
|
+
return { skeleton, symbols };
|
|
56
|
+
} catch (error) {
|
|
57
|
+
return {
|
|
58
|
+
skeleton: `/* Failed to parse file: ${error instanceof Error ? error.message : 'Unknown error'} */`,
|
|
59
|
+
symbols: [],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Generate skeleton and populate symbol mapping
|
|
66
|
+
*/
|
|
67
|
+
function generateSkeletonWithMapping(
|
|
68
|
+
sourceFile: SourceFile,
|
|
69
|
+
filePath: string,
|
|
70
|
+
symbols: SymbolLocation[],
|
|
71
|
+
rootPath: string
|
|
72
|
+
): string {
|
|
73
|
+
const lines: string[] = [];
|
|
74
|
+
const fileName = path.basename(filePath);
|
|
75
|
+
|
|
76
|
+
lines.push(`/* Skeleton of ${fileName} - Generated with symbol mapping */\n`);
|
|
77
|
+
|
|
78
|
+
// Imports
|
|
79
|
+
const imports = sourceFile.getImportDeclarations();
|
|
80
|
+
for (const imp of imports) {
|
|
81
|
+
lines.push(imp.getText());
|
|
82
|
+
}
|
|
83
|
+
if (imports.length > 0) lines.push('');
|
|
84
|
+
|
|
85
|
+
// Classes
|
|
86
|
+
const classes = sourceFile.getClasses();
|
|
87
|
+
for (const cls of classes) {
|
|
88
|
+
lines.push(processClassWithMapping(cls, filePath, symbols, rootPath));
|
|
89
|
+
lines.push('');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Interfaces (no mapping needed - no implementation)
|
|
93
|
+
const interfaces = sourceFile.getInterfaces();
|
|
94
|
+
for (const iface of interfaces) {
|
|
95
|
+
lines.push(iface.getText());
|
|
96
|
+
lines.push('');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Type aliases
|
|
100
|
+
const typeAliases = sourceFile.getTypeAliases();
|
|
101
|
+
for (const typeAlias of typeAliases) {
|
|
102
|
+
lines.push(typeAlias.getText());
|
|
103
|
+
lines.push('');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Enums
|
|
107
|
+
const enums = sourceFile.getEnums();
|
|
108
|
+
for (const enumDecl of enums) {
|
|
109
|
+
lines.push(enumDecl.getText());
|
|
110
|
+
lines.push('');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Top-level functions
|
|
114
|
+
const functions = sourceFile.getFunctions();
|
|
115
|
+
for (const func of functions) {
|
|
116
|
+
lines.push(processFunctionWithMapping(func, filePath, symbols, rootPath));
|
|
117
|
+
lines.push('');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Variables (including arrow functions)
|
|
121
|
+
const variables = sourceFile.getVariableStatements();
|
|
122
|
+
for (const varStatement of variables) {
|
|
123
|
+
lines.push(processVariableStatementWithMapping(varStatement, filePath, symbols, rootPath));
|
|
124
|
+
lines.push('');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Export declarations
|
|
128
|
+
const exportDeclarations = sourceFile.getExportDeclarations();
|
|
129
|
+
for (const exportDecl of exportDeclarations) {
|
|
130
|
+
lines.push(exportDecl.getText());
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const exportAssignments = sourceFile.getExportAssignments();
|
|
134
|
+
for (const exportAssign of exportAssignments) {
|
|
135
|
+
lines.push(exportAssign.getText());
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return lines.join('\n').trim();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Process class and map methods
|
|
143
|
+
*/
|
|
144
|
+
function processClassWithMapping(
|
|
145
|
+
cls: any,
|
|
146
|
+
filePath: string,
|
|
147
|
+
symbols: SymbolLocation[],
|
|
148
|
+
rootPath: string
|
|
149
|
+
): string {
|
|
150
|
+
const lines: string[] = [];
|
|
151
|
+
const className = cls.getName() || 'Anonymous';
|
|
152
|
+
|
|
153
|
+
const modifiers = cls.getModifiers().map((m: any) => m.getText()).join(' ');
|
|
154
|
+
let classDecl = modifiers ? `${modifiers} class` : 'class';
|
|
155
|
+
classDecl += ` ${className}`;
|
|
156
|
+
|
|
157
|
+
const typeParams = cls.getTypeParameters();
|
|
158
|
+
if (typeParams.length > 0) {
|
|
159
|
+
classDecl += `<${typeParams.map((tp: any) => tp.getText()).join(', ')}>`;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const extendsClause = cls.getExtends();
|
|
163
|
+
if (extendsClause) {
|
|
164
|
+
classDecl += ` extends ${extendsClause.getText()}`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const implementsClauses = cls.getImplements();
|
|
168
|
+
if (implementsClauses.length > 0) {
|
|
169
|
+
classDecl += ` implements ${implementsClauses.map((ic: any) => ic.getText()).join(', ')}`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
classDecl += ' {';
|
|
173
|
+
lines.push(classDecl);
|
|
174
|
+
|
|
175
|
+
// Properties
|
|
176
|
+
const properties = cls.getProperties();
|
|
177
|
+
for (const prop of properties) {
|
|
178
|
+
const propModifiers = prop.getModifiers().map((m: any) => m.getText()).join(' ');
|
|
179
|
+
const propName = prop.getName();
|
|
180
|
+
const propType = prop.getType().getText();
|
|
181
|
+
const propLine = propModifiers
|
|
182
|
+
? ` ${propModifiers} ${propName}: ${propType};`
|
|
183
|
+
: ` ${propName}: ${propType};`;
|
|
184
|
+
lines.push(propLine);
|
|
185
|
+
}
|
|
186
|
+
if (properties.length > 0) lines.push('');
|
|
187
|
+
|
|
188
|
+
// Methods
|
|
189
|
+
const methods = cls.getMethods();
|
|
190
|
+
for (const method of methods) {
|
|
191
|
+
const methodName = method.getName();
|
|
192
|
+
const symbolId = `${className}.${methodName}`;
|
|
193
|
+
|
|
194
|
+
// Record symbol location
|
|
195
|
+
const startLineNum = method.getStartLineNumber();
|
|
196
|
+
const endLineNum = method.getEndLineNumber();
|
|
197
|
+
const startPos = method.getStart();
|
|
198
|
+
const endPos = method.getEnd();
|
|
199
|
+
|
|
200
|
+
symbols.push({
|
|
201
|
+
symbolId,
|
|
202
|
+
symbolName: methodName,
|
|
203
|
+
symbolType: 'method',
|
|
204
|
+
filePath: path.relative(rootPath, filePath),
|
|
205
|
+
startLine: startLineNum,
|
|
206
|
+
endLine: endLineNum,
|
|
207
|
+
startPos,
|
|
208
|
+
endPos,
|
|
209
|
+
parentClass: className,
|
|
210
|
+
signature: method.getText().split('{')[0].trim(),
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
lines.push(processMethodSignature(method, symbolId));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Constructors
|
|
217
|
+
const constructors = cls.getConstructors();
|
|
218
|
+
for (const ctor of constructors) {
|
|
219
|
+
const symbolId = `${className}.constructor`;
|
|
220
|
+
|
|
221
|
+
const startLineNum = ctor.getStartLineNumber();
|
|
222
|
+
const endLineNum = ctor.getEndLineNumber();
|
|
223
|
+
|
|
224
|
+
symbols.push({
|
|
225
|
+
symbolId,
|
|
226
|
+
symbolName: 'constructor',
|
|
227
|
+
symbolType: 'constructor',
|
|
228
|
+
filePath: path.relative(rootPath, filePath),
|
|
229
|
+
startLine: startLineNum,
|
|
230
|
+
endLine: endLineNum,
|
|
231
|
+
startPos: ctor.getStart(),
|
|
232
|
+
endPos: ctor.getEnd(),
|
|
233
|
+
parentClass: className,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
lines.push(processConstructorSignature(ctor, symbolId));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
lines.push('}');
|
|
240
|
+
return lines.join('\n');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Process method signature with symbol placeholder
|
|
245
|
+
*/
|
|
246
|
+
function processMethodSignature(method: any, symbolId: string): string {
|
|
247
|
+
const lines: string[] = [];
|
|
248
|
+
|
|
249
|
+
const modifiers = method.getModifiers().map((m: any) => m.getText()).join(' ');
|
|
250
|
+
const name = method.getName();
|
|
251
|
+
const params = method.getParameters()
|
|
252
|
+
.map((p: any) => {
|
|
253
|
+
const pName = p.getName();
|
|
254
|
+
const pType = p.getType().getText();
|
|
255
|
+
const optional = p.isOptional() ? '?' : '';
|
|
256
|
+
return `${pName}${optional}: ${pType}`;
|
|
257
|
+
})
|
|
258
|
+
.join(', ');
|
|
259
|
+
const returnType = method.getReturnType().getText();
|
|
260
|
+
|
|
261
|
+
let signature = modifiers ? ` ${modifiers} ${name}` : ` ${name}`;
|
|
262
|
+
signature += `(${params}): ${returnType} {`;
|
|
263
|
+
lines.push(signature);
|
|
264
|
+
lines.push(` /* [SYMBOL:${symbolId}] - Implementation available via get_symbol_details */`);
|
|
265
|
+
lines.push(' }');
|
|
266
|
+
lines.push('');
|
|
267
|
+
|
|
268
|
+
return lines.join('\n');
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Process constructor signature
|
|
273
|
+
*/
|
|
274
|
+
function processConstructorSignature(ctor: any, symbolId: string): string {
|
|
275
|
+
const lines: string[] = [];
|
|
276
|
+
|
|
277
|
+
const params = ctor.getParameters()
|
|
278
|
+
.map((p: any) => {
|
|
279
|
+
const modifiers = p.getModifiers().map((m: any) => m.getText()).join(' ');
|
|
280
|
+
const pName = p.getName();
|
|
281
|
+
const pType = p.getType().getText();
|
|
282
|
+
const optional = p.isOptional() ? '?' : '';
|
|
283
|
+
const paramStr = `${pName}${optional}: ${pType}`;
|
|
284
|
+
return modifiers ? `${modifiers} ${paramStr}` : paramStr;
|
|
285
|
+
})
|
|
286
|
+
.join(', ');
|
|
287
|
+
|
|
288
|
+
lines.push(` constructor(${params}) {`);
|
|
289
|
+
lines.push(` /* [SYMBOL:${symbolId}] - Implementation available via get_symbol_details */`);
|
|
290
|
+
lines.push(' }');
|
|
291
|
+
lines.push('');
|
|
292
|
+
|
|
293
|
+
return lines.join('\n');
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Process function with mapping
|
|
298
|
+
*/
|
|
299
|
+
function processFunctionWithMapping(
|
|
300
|
+
func: any,
|
|
301
|
+
filePath: string,
|
|
302
|
+
symbols: SymbolLocation[],
|
|
303
|
+
rootPath: string
|
|
304
|
+
): string {
|
|
305
|
+
const lines: string[] = [];
|
|
306
|
+
const funcName = func.getName() || 'anonymous';
|
|
307
|
+
const symbolId = funcName;
|
|
308
|
+
|
|
309
|
+
// Record symbol
|
|
310
|
+
symbols.push({
|
|
311
|
+
symbolId,
|
|
312
|
+
symbolName: funcName,
|
|
313
|
+
symbolType: 'function',
|
|
314
|
+
filePath: path.relative(rootPath, filePath),
|
|
315
|
+
startLine: func.getStartLineNumber(),
|
|
316
|
+
endLine: func.getEndLineNumber(),
|
|
317
|
+
startPos: func.getStart(),
|
|
318
|
+
endPos: func.getEnd(),
|
|
319
|
+
signature: func.getText().split('{')[0].trim(),
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
const modifiers = func.getModifiers().map((m: any) => m.getText()).join(' ');
|
|
323
|
+
const params = func.getParameters()
|
|
324
|
+
.map((p: any) => {
|
|
325
|
+
const pName = p.getName();
|
|
326
|
+
const pType = p.getType().getText();
|
|
327
|
+
const optional = p.isOptional() ? '?' : '';
|
|
328
|
+
return `${pName}${optional}: ${pType}`;
|
|
329
|
+
})
|
|
330
|
+
.join(', ');
|
|
331
|
+
const returnType = func.getReturnType().getText();
|
|
332
|
+
|
|
333
|
+
let signature = modifiers ? `${modifiers} function` : 'function';
|
|
334
|
+
signature += ` ${funcName}(${params}): ${returnType} {`;
|
|
335
|
+
lines.push(signature);
|
|
336
|
+
lines.push(` /* [SYMBOL:${symbolId}] - Implementation available via get_symbol_details */`);
|
|
337
|
+
lines.push('}');
|
|
338
|
+
|
|
339
|
+
return lines.join('\n');
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Process variable statements (handles arrow functions)
|
|
344
|
+
*/
|
|
345
|
+
function processVariableStatementWithMapping(
|
|
346
|
+
varStatement: any,
|
|
347
|
+
filePath: string,
|
|
348
|
+
symbols: SymbolLocation[],
|
|
349
|
+
rootPath: string
|
|
350
|
+
): string {
|
|
351
|
+
const lines: string[] = [];
|
|
352
|
+
|
|
353
|
+
const modifiers = varStatement.getModifiers().map((m: any) => m.getText()).join(' ');
|
|
354
|
+
const declarations = varStatement.getDeclarations();
|
|
355
|
+
const declarationKind = varStatement.getDeclarationKind();
|
|
356
|
+
|
|
357
|
+
for (const decl of declarations) {
|
|
358
|
+
const name = decl.getName();
|
|
359
|
+
const type = decl.getType().getText();
|
|
360
|
+
const initializer = decl.getInitializer();
|
|
361
|
+
|
|
362
|
+
if (initializer) {
|
|
363
|
+
const initText = initializer.getText();
|
|
364
|
+
|
|
365
|
+
// Check if it's an arrow function
|
|
366
|
+
if (initText.includes('=>') || initializer.getKind() === SyntaxKind.ArrowFunction) {
|
|
367
|
+
const symbolId = name;
|
|
368
|
+
|
|
369
|
+
symbols.push({
|
|
370
|
+
symbolId,
|
|
371
|
+
symbolName: name,
|
|
372
|
+
symbolType: 'arrow-function',
|
|
373
|
+
filePath: path.relative(rootPath, filePath),
|
|
374
|
+
startLine: decl.getStartLineNumber(),
|
|
375
|
+
endLine: decl.getEndLineNumber(),
|
|
376
|
+
startPos: decl.getStart(),
|
|
377
|
+
endPos: decl.getEnd(),
|
|
378
|
+
signature: `${declarationKind} ${name}: ${type}`,
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
const line = modifiers
|
|
382
|
+
? `${modifiers} ${declarationKind} ${name}: ${type} = /* [SYMBOL:${symbolId}] */;`
|
|
383
|
+
: `${declarationKind} ${name}: ${type} = /* [SYMBOL:${symbolId}] */;`;
|
|
384
|
+
lines.push(line);
|
|
385
|
+
} else if (initText.length < 50 && !initText.includes('{')) {
|
|
386
|
+
// Simple value - keep it
|
|
387
|
+
const line = modifiers
|
|
388
|
+
? `${modifiers} ${declarationKind} ${name}: ${type} = ${initText};`
|
|
389
|
+
: `${declarationKind} ${name}: ${type} = ${initText};`;
|
|
390
|
+
lines.push(line);
|
|
391
|
+
} else {
|
|
392
|
+
// Complex value - stub it
|
|
393
|
+
const line = modifiers
|
|
394
|
+
? `${modifiers} ${declarationKind} ${name}: ${type} = /* trimmed */;`
|
|
395
|
+
: `${declarationKind} ${name}: ${type} = /* trimmed */;`;
|
|
396
|
+
lines.push(line);
|
|
397
|
+
}
|
|
398
|
+
} else {
|
|
399
|
+
const line = modifiers
|
|
400
|
+
? `${modifiers} ${declarationKind} ${name}: ${type};`
|
|
401
|
+
: `${declarationKind} ${name}: ${type};`;
|
|
402
|
+
lines.push(line);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return lines.join('\n');
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Get symbol details by ID from mapping
|
|
411
|
+
*/
|
|
412
|
+
export function getSymbolDetails(
|
|
413
|
+
symbolId: string,
|
|
414
|
+
mapping: SymbolMapping
|
|
415
|
+
): { content: string; location: SymbolLocation } | null {
|
|
416
|
+
for (const fileInfo of Object.values(mapping.files)) {
|
|
417
|
+
const symbol = fileInfo.symbols.find(s => s.symbolId === symbolId);
|
|
418
|
+
if (symbol) {
|
|
419
|
+
const fullPath = path.join(mapping.rootPath, symbol.filePath);
|
|
420
|
+
const fileContent = fs.readFileSync(fullPath, 'utf-8');
|
|
421
|
+
const lines = fileContent.split('\n');
|
|
422
|
+
const symbolContent = lines
|
|
423
|
+
.slice(symbol.startLine - 1, symbol.endLine)
|
|
424
|
+
.join('\n');
|
|
425
|
+
|
|
426
|
+
return {
|
|
427
|
+
content: symbolContent,
|
|
428
|
+
location: symbol,
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Save mapping to JSON file
|
|
437
|
+
*/
|
|
438
|
+
export function saveMappingToFile(mapping: SymbolMapping, outputPath: string): void {
|
|
439
|
+
fs.writeFileSync(outputPath, JSON.stringify(mapping, null, 2), 'utf-8');
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Load mapping from JSON file
|
|
444
|
+
*/
|
|
445
|
+
export function loadMappingFromFile(mappingPath: string): SymbolMapping {
|
|
446
|
+
const content = fs.readFileSync(mappingPath, 'utf-8');
|
|
447
|
+
return JSON.parse(content);
|
|
448
|
+
}
|