bobs-workshop 0.2.7 → 0.3.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/Claude.md +30 -4
- package/README.md +2 -2
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/prompts/architect.js +6 -1
- package/dist/prompts/architect.js.map +1 -1
- package/dist/prompts/debugger.js +5 -0
- package/dist/prompts/debugger.js.map +1 -1
- package/dist/prompts/engineer.js +6 -1
- package/dist/prompts/engineer.js.map +1 -1
- package/dist/prompts/reviewer.js +6 -1
- package/dist/prompts/reviewer.js.map +1 -1
- package/dist/tools/searchTools.js +82 -75
- package/dist/tools/searchTools.js.map +1 -1
- package/dist/tools/semgrep-patterns.js +296 -0
- package/dist/tools/semgrep-patterns.js.map +1 -0
- package/dist/tools/structural/__tests__/orchestrator.test.js +61 -0
- package/dist/tools/structural/__tests__/orchestrator.test.js.map +1 -0
- package/dist/tools/structural/cache.js +226 -0
- package/dist/tools/structural/cache.js.map +1 -0
- package/dist/tools/structural/engines/python/index.js +118 -0
- package/dist/tools/structural/engines/python/index.js.map +1 -0
- package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js +97 -0
- package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js.map +1 -0
- package/dist/tools/structural/engines/typescript/analyzer.js +433 -0
- package/dist/tools/structural/engines/typescript/analyzer.js.map +1 -0
- package/dist/tools/structural/engines/typescript/index.js +381 -0
- package/dist/tools/structural/engines/typescript/index.js.map +1 -0
- package/dist/tools/structural/engines/typescript/utils.js +279 -0
- package/dist/tools/structural/engines/typescript/utils.js.map +1 -0
- package/dist/tools/structural/index.js +248 -0
- package/dist/tools/structural/index.js.map +1 -0
- package/dist/tools/structural/types.js +18 -0
- package/dist/tools/structural/types.js.map +1 -0
- package/package.json +5 -1
- package/public/.well-known/mcp/manifest.json +6 -5
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { Node, SyntaxKind } from "ts-morph";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { ErrorCode, AnalysisError } from "../../types.js";
|
|
4
|
+
import { analyzeSourceFile } from "./analyzer.js";
|
|
5
|
+
import { createProject, findProjectRoot, findFiles, nodeToLocation, validatePath } from "./utils.js";
|
|
6
|
+
export class TypeScriptEngine {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.projectCache = new Map();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Find all references to a symbol
|
|
12
|
+
*/
|
|
13
|
+
async findReferences(symbolName, scope, options) {
|
|
14
|
+
const results = [];
|
|
15
|
+
try {
|
|
16
|
+
validatePath(scope);
|
|
17
|
+
// Determine if scope is a file or directory
|
|
18
|
+
const isFile = scope.endsWith('.ts') || scope.endsWith('.tsx') || scope.endsWith('.js') || scope.endsWith('.jsx');
|
|
19
|
+
const projectRoot = isFile ? findProjectRoot(scope) : scope;
|
|
20
|
+
const project = this.getOrCreateProject(projectRoot);
|
|
21
|
+
// Load files into project
|
|
22
|
+
const files = isFile ? [scope] : await this.getFilesInScope(scope, 500);
|
|
23
|
+
for (const file of files) {
|
|
24
|
+
try {
|
|
25
|
+
// Check if file is already in project
|
|
26
|
+
if (!project.getSourceFile(file)) {
|
|
27
|
+
project.addSourceFileAtPath(file);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
// Skip files that can't be loaded
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Find the symbol in the scope
|
|
35
|
+
const sourceFiles = isFile ? [project.getSourceFile(scope)] : project.getSourceFiles();
|
|
36
|
+
for (const sourceFile of sourceFiles) {
|
|
37
|
+
if (!sourceFile)
|
|
38
|
+
continue;
|
|
39
|
+
// Search for the symbol in this file
|
|
40
|
+
const symbolNodes = this.findSymbolInFile(sourceFile, symbolName);
|
|
41
|
+
for (const node of symbolNodes) {
|
|
42
|
+
try {
|
|
43
|
+
const identifier = Node.isIdentifier(node)
|
|
44
|
+
? node
|
|
45
|
+
: node.getFirstDescendantByKind(SyntaxKind.Identifier);
|
|
46
|
+
if (identifier && Node.isIdentifier(identifier)) {
|
|
47
|
+
// Force program compilation before language service operations
|
|
48
|
+
const languageService = project.getLanguageService();
|
|
49
|
+
const refs = identifier.findReferences();
|
|
50
|
+
refs.forEach((ref) => {
|
|
51
|
+
ref.getReferences().forEach((refEntry) => {
|
|
52
|
+
try {
|
|
53
|
+
const refNode = refEntry.getNode();
|
|
54
|
+
const location = nodeToLocation(refNode);
|
|
55
|
+
// Skip if not including definitions and this is a definition
|
|
56
|
+
if (!options?.includeDefinition && refEntry.isDefinition()) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
results.push({
|
|
60
|
+
file: location.file,
|
|
61
|
+
line: location.position.line,
|
|
62
|
+
column: location.position.character,
|
|
63
|
+
symbol: symbolName,
|
|
64
|
+
kind: this.getSymbolKindFromNode(refNode),
|
|
65
|
+
context: this.getContext(refNode)
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
// Skip individual reference that fails
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
// Skip nodes that fail to find references
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return results.slice(0, options?.maxResults || 100);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
throw new AnalysisError({
|
|
84
|
+
code: ErrorCode.PARSE_ERROR,
|
|
85
|
+
message: `Failed to find references: ${error}`,
|
|
86
|
+
details: { symbolName, file: scope }
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Find the definition of a symbol
|
|
92
|
+
*/
|
|
93
|
+
async findDefinition(symbolName, scope, options) {
|
|
94
|
+
try {
|
|
95
|
+
validatePath(scope);
|
|
96
|
+
const isFile = scope.endsWith('.ts') || scope.endsWith('.tsx') || scope.endsWith('.js') || scope.endsWith('.jsx');
|
|
97
|
+
const projectRoot = isFile ? findProjectRoot(scope) : scope;
|
|
98
|
+
const project = this.getOrCreateProject(projectRoot);
|
|
99
|
+
const files = isFile ? [scope] : await this.getFilesInScope(scope, 500);
|
|
100
|
+
for (const file of files) {
|
|
101
|
+
try {
|
|
102
|
+
const sourceFile = project.addSourceFileAtPath(file);
|
|
103
|
+
const symbolNodes = this.findSymbolInFile(sourceFile, symbolName);
|
|
104
|
+
for (const node of symbolNodes) {
|
|
105
|
+
const symbol = node.getSymbol();
|
|
106
|
+
if (symbol) {
|
|
107
|
+
const declarations = symbol.getDeclarations();
|
|
108
|
+
if (declarations.length > 0) {
|
|
109
|
+
const declaration = declarations[0];
|
|
110
|
+
const location = nodeToLocation(declaration);
|
|
111
|
+
return {
|
|
112
|
+
file: location.file,
|
|
113
|
+
line: location.position.line,
|
|
114
|
+
column: location.position.character,
|
|
115
|
+
symbol: symbolName,
|
|
116
|
+
kind: this.getSymbolKindFromNode(declaration),
|
|
117
|
+
type: node.getType().getText(),
|
|
118
|
+
context: this.getContext(declaration)
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
// Skip files that can't be loaded
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
throw new AnalysisError({
|
|
132
|
+
code: ErrorCode.PARSE_ERROR,
|
|
133
|
+
message: `Failed to find definition: ${error}`,
|
|
134
|
+
details: { symbolName, file: scope }
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get dependencies of a file or symbol
|
|
140
|
+
*/
|
|
141
|
+
async getDependencies(target, options) {
|
|
142
|
+
try {
|
|
143
|
+
validatePath(target);
|
|
144
|
+
const projectRoot = findProjectRoot(target);
|
|
145
|
+
const project = this.getOrCreateProject(projectRoot);
|
|
146
|
+
const sourceFile = project.addSourceFileAtPath(target);
|
|
147
|
+
const analysis = analyzeSourceFile(sourceFile, "dependencies", 2, false, false);
|
|
148
|
+
const results = [];
|
|
149
|
+
analysis.imports.forEach((imp, index) => {
|
|
150
|
+
results.push({
|
|
151
|
+
file: target,
|
|
152
|
+
line: index,
|
|
153
|
+
symbol: imp.moduleSpecifier,
|
|
154
|
+
kind: "module",
|
|
155
|
+
context: `imports: ${imp.symbols.join(", ")}`
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
return results.slice(0, options?.maxResults || 100);
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
throw new AnalysisError({
|
|
162
|
+
code: ErrorCode.PARSE_ERROR,
|
|
163
|
+
message: `Failed to get dependencies: ${error}`,
|
|
164
|
+
details: { file: target }
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get dependency graph (for Architect role)
|
|
170
|
+
*/
|
|
171
|
+
async getDependencyGraph(filePath, depth = 2) {
|
|
172
|
+
const visited = new Set();
|
|
173
|
+
const dependencies = [];
|
|
174
|
+
const circular = [];
|
|
175
|
+
const buildGraph = async (file, currentDepth, chain) => {
|
|
176
|
+
if (currentDepth > depth || visited.has(file)) {
|
|
177
|
+
// Check for circular dependency
|
|
178
|
+
if (chain.includes(file)) {
|
|
179
|
+
circular.push([...chain, file]);
|
|
180
|
+
}
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
visited.add(file);
|
|
184
|
+
try {
|
|
185
|
+
const projectRoot = findProjectRoot(file);
|
|
186
|
+
const project = this.getOrCreateProject(projectRoot);
|
|
187
|
+
const sourceFile = project.addSourceFileAtPath(file);
|
|
188
|
+
const analysis = analyzeSourceFile(sourceFile, "dependencies", 1, false, false);
|
|
189
|
+
const imports = analysis.imports.map(imp => imp.moduleSpecifier);
|
|
190
|
+
dependencies.push({
|
|
191
|
+
file,
|
|
192
|
+
imports,
|
|
193
|
+
depth: currentDepth
|
|
194
|
+
});
|
|
195
|
+
// Recursively process imports
|
|
196
|
+
for (const imp of imports) {
|
|
197
|
+
if (imp.startsWith('.')) {
|
|
198
|
+
const resolvedPath = path.resolve(path.dirname(file), imp);
|
|
199
|
+
await buildGraph(resolvedPath, currentDepth + 1, [...chain, file]);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
// Skip files that can't be analyzed
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
await buildGraph(filePath, 0, []);
|
|
208
|
+
return {
|
|
209
|
+
root: filePath,
|
|
210
|
+
dependencies,
|
|
211
|
+
circular: circular.length > 0 ? circular.map(cycle => ({ cycle })) : undefined
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Find architectural issues (for Architect role)
|
|
216
|
+
*/
|
|
217
|
+
async findArchitecturalIssues(scope) {
|
|
218
|
+
const issues = [];
|
|
219
|
+
try {
|
|
220
|
+
const files = await this.getFilesInScope(scope, 500);
|
|
221
|
+
for (const file of files) {
|
|
222
|
+
const graph = await this.getDependencyGraph(file, 3);
|
|
223
|
+
// Check for circular dependencies
|
|
224
|
+
if (graph.circular && graph.circular.length > 0) {
|
|
225
|
+
issues.push({
|
|
226
|
+
type: "circular-dependency",
|
|
227
|
+
severity: "error",
|
|
228
|
+
message: `Circular dependency detected: ${graph.circular[0].cycle.join(" -> ")}`,
|
|
229
|
+
location: { file, position: { line: 0 } },
|
|
230
|
+
suggestion: "Consider breaking the circular dependency by introducing an interface or moving shared code to a separate module"
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
// Check for high coupling (too many imports)
|
|
234
|
+
const mainDep = graph.dependencies.find(d => d.file === file);
|
|
235
|
+
if (mainDep && mainDep.imports.length > 15) {
|
|
236
|
+
issues.push({
|
|
237
|
+
type: "high-coupling",
|
|
238
|
+
severity: "warning",
|
|
239
|
+
message: `High coupling detected: ${mainDep.imports.length} imports`,
|
|
240
|
+
location: { file, position: { line: 0 } },
|
|
241
|
+
suggestion: "Consider splitting this file into smaller, more focused modules"
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return issues;
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
return [];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Find unused exports (for Engineer role)
|
|
253
|
+
*/
|
|
254
|
+
async findUnusedExports(scope) {
|
|
255
|
+
const unused = [];
|
|
256
|
+
try {
|
|
257
|
+
const files = await this.getFilesInScope(scope, 500);
|
|
258
|
+
const project = this.getOrCreateProject(scope);
|
|
259
|
+
// Load all files
|
|
260
|
+
for (const file of files) {
|
|
261
|
+
try {
|
|
262
|
+
project.addSourceFileAtPath(file);
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
// Skip
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
for (const file of files) {
|
|
269
|
+
try {
|
|
270
|
+
const sourceFile = project.getSourceFile(file);
|
|
271
|
+
if (!sourceFile)
|
|
272
|
+
continue;
|
|
273
|
+
const analysis = analyzeSourceFile(sourceFile, "all", 1, false, false);
|
|
274
|
+
for (const exportName of analysis.exports) {
|
|
275
|
+
// Check if this export is used anywhere
|
|
276
|
+
const refs = await this.findReferences(exportName, scope, { maxResults: 2 });
|
|
277
|
+
if (refs.length === 0) {
|
|
278
|
+
unused.push({
|
|
279
|
+
name: exportName,
|
|
280
|
+
kind: "variable",
|
|
281
|
+
location: { file, position: { line: 0 } },
|
|
282
|
+
exportedFrom: file
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
// Skip
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return unused;
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
return [];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Get refactor impact (for Engineer role)
|
|
299
|
+
*/
|
|
300
|
+
async getRefactorImpact(symbol, scope) {
|
|
301
|
+
const refs = await this.findReferences(symbol, scope, { maxResults: 1000 });
|
|
302
|
+
const affectedFiles = [...new Set(refs.map(r => r.file))];
|
|
303
|
+
const testFiles = affectedFiles.filter(f => f.includes('test') || f.includes('spec'));
|
|
304
|
+
return {
|
|
305
|
+
symbol,
|
|
306
|
+
referenceCount: refs.length,
|
|
307
|
+
affectedFiles,
|
|
308
|
+
testFiles
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
// Private helper methods
|
|
312
|
+
getOrCreateProject(rootPath) {
|
|
313
|
+
if (this.projectCache.has(rootPath)) {
|
|
314
|
+
return this.projectCache.get(rootPath);
|
|
315
|
+
}
|
|
316
|
+
const project = createProject(rootPath, false);
|
|
317
|
+
this.projectCache.set(rootPath, project);
|
|
318
|
+
return project;
|
|
319
|
+
}
|
|
320
|
+
async getFilesInScope(scope, maxFiles = 500) {
|
|
321
|
+
const files = await findFiles("**/*.{ts,tsx,js,jsx}", scope);
|
|
322
|
+
// Sort by modification time (most recent first) for better cache hits
|
|
323
|
+
const filesWithStats = await Promise.all(files.map(async (file) => {
|
|
324
|
+
try {
|
|
325
|
+
const fs = await import('fs/promises');
|
|
326
|
+
const stats = await fs.stat(file);
|
|
327
|
+
return { file, mtime: stats.mtimeMs };
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
return { file, mtime: 0 };
|
|
331
|
+
}
|
|
332
|
+
}));
|
|
333
|
+
filesWithStats.sort((a, b) => b.mtime - a.mtime);
|
|
334
|
+
return filesWithStats.slice(0, maxFiles).map(f => f.file);
|
|
335
|
+
}
|
|
336
|
+
findSymbolInFile(sourceFile, symbolName) {
|
|
337
|
+
const nodes = [];
|
|
338
|
+
sourceFile.forEachDescendant(node => {
|
|
339
|
+
try {
|
|
340
|
+
if (node.getSymbol()?.getName() === symbolName) {
|
|
341
|
+
nodes.push(node);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
// Skip nodes where getSymbol() fails due to incomplete type information
|
|
346
|
+
// This can happen when not all dependencies are loaded in the project
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
return nodes;
|
|
350
|
+
}
|
|
351
|
+
getSymbolKindFromNode(node) {
|
|
352
|
+
if (Node.isClassDeclaration(node))
|
|
353
|
+
return "class";
|
|
354
|
+
if (Node.isInterfaceDeclaration(node))
|
|
355
|
+
return "interface";
|
|
356
|
+
if (Node.isEnumDeclaration(node))
|
|
357
|
+
return "enum";
|
|
358
|
+
if (Node.isFunctionDeclaration(node))
|
|
359
|
+
return "function";
|
|
360
|
+
if (Node.isMethodDeclaration(node))
|
|
361
|
+
return "method";
|
|
362
|
+
if (Node.isPropertyDeclaration(node))
|
|
363
|
+
return "property";
|
|
364
|
+
if (Node.isVariableDeclaration(node))
|
|
365
|
+
return "variable";
|
|
366
|
+
if (Node.isTypeAliasDeclaration(node))
|
|
367
|
+
return "type";
|
|
368
|
+
// Check for parameter using getKind()
|
|
369
|
+
if (node.getKind() === SyntaxKind.Parameter)
|
|
370
|
+
return "parameter";
|
|
371
|
+
return "variable";
|
|
372
|
+
}
|
|
373
|
+
getContext(node) {
|
|
374
|
+
const parent = node.getParent();
|
|
375
|
+
if (!parent)
|
|
376
|
+
return node.getText().substring(0, 100);
|
|
377
|
+
const parentText = parent.getText();
|
|
378
|
+
return parentText.substring(0, 100);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/tools/structural/engines/typescript/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { Project, SyntaxKind, ts } from "ts-morph";
|
|
2
|
+
import { glob } from "glob";
|
|
3
|
+
import { minimatch } from "minimatch";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import { cacheManager } from "../../cache.js";
|
|
7
|
+
// Re-export for backward compatibility
|
|
8
|
+
export const fileCache = {
|
|
9
|
+
get: (key) => {
|
|
10
|
+
const cached = cacheManager.getCachedFile(key);
|
|
11
|
+
return cached?.then(c => c?.sourceFile);
|
|
12
|
+
},
|
|
13
|
+
set: (key, value) => {
|
|
14
|
+
cacheManager.setCachedFile(key, value);
|
|
15
|
+
},
|
|
16
|
+
clear: () => cacheManager.clearFileCache()
|
|
17
|
+
};
|
|
18
|
+
export const symbolCache = {
|
|
19
|
+
get: (key) => cacheManager.getCachedSymbol(key),
|
|
20
|
+
set: (key, value) => cacheManager.setCachedSymbol(key, value),
|
|
21
|
+
clear: () => cacheManager.clearSymbolCache()
|
|
22
|
+
};
|
|
23
|
+
export const performanceConfig = {
|
|
24
|
+
maxMemoryMB: 2048,
|
|
25
|
+
batchSize: 50,
|
|
26
|
+
cacheStrategy: "memory",
|
|
27
|
+
gcInterval: 100
|
|
28
|
+
};
|
|
29
|
+
export const timeoutLimits = {
|
|
30
|
+
singleFile: 5000,
|
|
31
|
+
symbolSearch: 10000,
|
|
32
|
+
projectAnalysis: 60000,
|
|
33
|
+
impactAnalysis: 30000,
|
|
34
|
+
};
|
|
35
|
+
export const securityConfig = {
|
|
36
|
+
allowedPaths: ["./src", "./tests", "./lib"],
|
|
37
|
+
excludePatterns: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/build/**"],
|
|
38
|
+
maxFileSize: 5 * 1024 * 1024,
|
|
39
|
+
maxPathDepth: 10,
|
|
40
|
+
};
|
|
41
|
+
export function findProjectRoot(filePath) {
|
|
42
|
+
let currentDir = path.dirname(path.resolve(filePath));
|
|
43
|
+
// First priority: look for tsconfig.json (closest to the file)
|
|
44
|
+
let tsConfigDir = null;
|
|
45
|
+
let tempDir = currentDir;
|
|
46
|
+
while (tempDir !== path.dirname(tempDir)) {
|
|
47
|
+
if (fs.existsSync(path.join(tempDir, 'tsconfig.json'))) {
|
|
48
|
+
tsConfigDir = tempDir;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
tempDir = path.dirname(tempDir);
|
|
52
|
+
}
|
|
53
|
+
// If we found a tsconfig.json, use it
|
|
54
|
+
if (tsConfigDir) {
|
|
55
|
+
return tsConfigDir;
|
|
56
|
+
}
|
|
57
|
+
// Fallback: look for package.json or .git
|
|
58
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
59
|
+
if (fs.existsSync(path.join(currentDir, 'package.json')) ||
|
|
60
|
+
fs.existsSync(path.join(currentDir, '.git'))) {
|
|
61
|
+
return currentDir;
|
|
62
|
+
}
|
|
63
|
+
currentDir = path.dirname(currentDir);
|
|
64
|
+
}
|
|
65
|
+
// Final fallback to the directory containing the file
|
|
66
|
+
return path.dirname(path.resolve(filePath));
|
|
67
|
+
}
|
|
68
|
+
export function createProject(rootPath, includeNodeModules = false) {
|
|
69
|
+
const workingDir = rootPath || process.cwd();
|
|
70
|
+
// Check if there's a tsconfig.json file
|
|
71
|
+
const tsConfigPath = path.join(workingDir, 'tsconfig.json');
|
|
72
|
+
const hasTsConfig = fs.existsSync(tsConfigPath);
|
|
73
|
+
// If we have a tsconfig and we're not doing symbol analysis (includeNodeModules), use it
|
|
74
|
+
if (hasTsConfig && !includeNodeModules) {
|
|
75
|
+
try {
|
|
76
|
+
const project = new Project({
|
|
77
|
+
tsConfigFilePath: tsConfigPath,
|
|
78
|
+
skipAddingFilesFromTsConfig: true,
|
|
79
|
+
useInMemoryFileSystem: false,
|
|
80
|
+
skipFileDependencyResolution: false // Enable for language service operations
|
|
81
|
+
});
|
|
82
|
+
return project;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
// If tsconfig parsing fails, fall back to default options
|
|
86
|
+
console.error('Failed to parse tsconfig.json, using defaults:', error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Use default compiler options for symbol analysis or when tsconfig is not available
|
|
90
|
+
const baseOptions = {
|
|
91
|
+
target: ts.ScriptTarget.ES2022,
|
|
92
|
+
module: ts.ModuleKind.ESNext,
|
|
93
|
+
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
94
|
+
allowJs: true,
|
|
95
|
+
declaration: true,
|
|
96
|
+
esModuleInterop: true,
|
|
97
|
+
allowSyntheticDefaultImports: true,
|
|
98
|
+
strict: false, // Disable strict mode for better compatibility
|
|
99
|
+
skipLibCheck: true,
|
|
100
|
+
noEmit: true,
|
|
101
|
+
resolveJsonModule: true,
|
|
102
|
+
isolatedModules: true,
|
|
103
|
+
allowImportingTsExtensions: false,
|
|
104
|
+
noResolve: false,
|
|
105
|
+
jsx: ts.JsxEmit.ReactJSX,
|
|
106
|
+
};
|
|
107
|
+
if (includeNodeModules) {
|
|
108
|
+
const projectRoot = workingDir;
|
|
109
|
+
baseOptions.typeRoots = [
|
|
110
|
+
path.join(projectRoot, "node_modules/@types"),
|
|
111
|
+
path.join(projectRoot, "node_modules")
|
|
112
|
+
];
|
|
113
|
+
baseOptions.baseUrl = projectRoot;
|
|
114
|
+
baseOptions.paths = {
|
|
115
|
+
"*": ["node_modules/*", "node_modules/@types/*"]
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const project = new Project({
|
|
119
|
+
compilerOptions: baseOptions,
|
|
120
|
+
skipAddingFilesFromTsConfig: true,
|
|
121
|
+
useInMemoryFileSystem: false,
|
|
122
|
+
skipFileDependencyResolution: false // Enable for language service operations
|
|
123
|
+
});
|
|
124
|
+
return project;
|
|
125
|
+
}
|
|
126
|
+
export function findClosestTsConfig(filePath) {
|
|
127
|
+
let currentDir = path.dirname(path.resolve(filePath));
|
|
128
|
+
// Walk up from the target path looking only for tsconfig.json
|
|
129
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
130
|
+
const tsConfigPath = path.join(currentDir, 'tsconfig.json');
|
|
131
|
+
if (fs.existsSync(tsConfigPath)) {
|
|
132
|
+
return currentDir;
|
|
133
|
+
}
|
|
134
|
+
currentDir = path.dirname(currentDir);
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
export function nodeToLocation(node) {
|
|
139
|
+
const sourceFile = node.getSourceFile();
|
|
140
|
+
const start = sourceFile.getLineAndColumnAtPos(node.getStart());
|
|
141
|
+
const end = sourceFile.getLineAndColumnAtPos(node.getEnd());
|
|
142
|
+
return {
|
|
143
|
+
file: sourceFile.getFilePath(),
|
|
144
|
+
position: {
|
|
145
|
+
line: start.line - 1,
|
|
146
|
+
character: start.column - 1
|
|
147
|
+
},
|
|
148
|
+
endPosition: {
|
|
149
|
+
line: end.line - 1,
|
|
150
|
+
character: end.column - 1
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
export function positionToOffset(sourceFile, position) {
|
|
155
|
+
const character = position.character ?? 0;
|
|
156
|
+
const pos = sourceFile.compilerNode.getPositionOfLineAndCharacter(position.line, character);
|
|
157
|
+
return pos;
|
|
158
|
+
}
|
|
159
|
+
export function getSymbolKind(node) {
|
|
160
|
+
const kind = node.getKind();
|
|
161
|
+
switch (kind) {
|
|
162
|
+
case SyntaxKind.ClassDeclaration:
|
|
163
|
+
return "class";
|
|
164
|
+
case SyntaxKind.InterfaceDeclaration:
|
|
165
|
+
return "interface";
|
|
166
|
+
case SyntaxKind.EnumDeclaration:
|
|
167
|
+
return "enum";
|
|
168
|
+
case SyntaxKind.FunctionDeclaration:
|
|
169
|
+
case SyntaxKind.FunctionExpression:
|
|
170
|
+
case SyntaxKind.ArrowFunction:
|
|
171
|
+
return "function";
|
|
172
|
+
case SyntaxKind.MethodDeclaration:
|
|
173
|
+
case SyntaxKind.MethodSignature:
|
|
174
|
+
return "method";
|
|
175
|
+
case SyntaxKind.PropertyDeclaration:
|
|
176
|
+
case SyntaxKind.PropertySignature:
|
|
177
|
+
return "property";
|
|
178
|
+
case SyntaxKind.VariableDeclaration:
|
|
179
|
+
return "variable";
|
|
180
|
+
case SyntaxKind.Parameter:
|
|
181
|
+
return "parameter";
|
|
182
|
+
case SyntaxKind.TypeAliasDeclaration:
|
|
183
|
+
return "type";
|
|
184
|
+
case SyntaxKind.ModuleDeclaration:
|
|
185
|
+
return "module";
|
|
186
|
+
case SyntaxKind.NamespaceKeyword:
|
|
187
|
+
return "namespace";
|
|
188
|
+
default:
|
|
189
|
+
return "variable";
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
export async function findFiles(pattern, basePath = process.cwd()) {
|
|
193
|
+
const files = await glob(pattern, {
|
|
194
|
+
cwd: basePath,
|
|
195
|
+
absolute: true,
|
|
196
|
+
ignore: securityConfig.excludePatterns,
|
|
197
|
+
});
|
|
198
|
+
return files.filter(file => {
|
|
199
|
+
const relativePath = path.relative(basePath, file);
|
|
200
|
+
const depth = relativePath.split(path.sep).length;
|
|
201
|
+
return depth <= securityConfig.maxPathDepth;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
export function matchesScope(filePath, scope) {
|
|
205
|
+
if (!scope)
|
|
206
|
+
return true;
|
|
207
|
+
if (scope.fileTypes) {
|
|
208
|
+
const ext = path.extname(filePath);
|
|
209
|
+
if (!scope.fileTypes.includes(ext))
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
if (scope.excludeFiles) {
|
|
213
|
+
for (const pattern of scope.excludeFiles) {
|
|
214
|
+
if (minimatch(filePath, pattern))
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (scope.includeFiles) {
|
|
219
|
+
for (const pattern of scope.includeFiles) {
|
|
220
|
+
if (minimatch(filePath, pattern))
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
export function validatePath(filePath, allowNodeModules = false) {
|
|
228
|
+
// Path validation removed - allow analyzing files from any location
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
export function getNodeComplexity(node) {
|
|
232
|
+
let complexity = 1;
|
|
233
|
+
node.forEachDescendant(child => {
|
|
234
|
+
const kind = child.getKind();
|
|
235
|
+
if (kind === SyntaxKind.IfStatement ||
|
|
236
|
+
kind === SyntaxKind.ForStatement ||
|
|
237
|
+
kind === SyntaxKind.ForInStatement ||
|
|
238
|
+
kind === SyntaxKind.ForOfStatement ||
|
|
239
|
+
kind === SyntaxKind.WhileStatement ||
|
|
240
|
+
kind === SyntaxKind.DoStatement ||
|
|
241
|
+
kind === SyntaxKind.ConditionalExpression ||
|
|
242
|
+
kind === SyntaxKind.CatchClause ||
|
|
243
|
+
kind === SyntaxKind.CaseClause ||
|
|
244
|
+
kind === SyntaxKind.BinaryExpression) {
|
|
245
|
+
complexity++;
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
return complexity;
|
|
249
|
+
}
|
|
250
|
+
export function getTypeString(type, maxLength = 500) {
|
|
251
|
+
const typeText = type.getText();
|
|
252
|
+
if (typeText.length > maxLength) {
|
|
253
|
+
return typeText.substring(0, maxLength - 3) + "...";
|
|
254
|
+
}
|
|
255
|
+
return typeText;
|
|
256
|
+
}
|
|
257
|
+
export async function checkMemoryUsage() {
|
|
258
|
+
const usage = process.memoryUsage();
|
|
259
|
+
const heapUsedMB = usage.heapUsed / 1024 / 1024;
|
|
260
|
+
const cacheMemoryMB = cacheManager.getMemoryUsage() / 1024 / 1024;
|
|
261
|
+
if (heapUsedMB + cacheMemoryMB > performanceConfig.maxMemoryMB * 0.9) {
|
|
262
|
+
if (global.gc) {
|
|
263
|
+
global.gc();
|
|
264
|
+
}
|
|
265
|
+
await cacheManager.clearAll();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
export class TimeoutError extends Error {
|
|
269
|
+
constructor(operation, limit) {
|
|
270
|
+
super(`Operation '${operation}' timed out after ${limit}ms`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
export function withTimeout(promise, operation, limit) {
|
|
274
|
+
return Promise.race([
|
|
275
|
+
promise,
|
|
276
|
+
new Promise((_, reject) => setTimeout(() => reject(new TimeoutError(operation, limit)), limit))
|
|
277
|
+
]);
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=utils.js.map
|