neuronlayer 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of neuronlayer might be problematic. Click here for more details.
- package/README.md +3 -2
- package/dist/index.js +172 -90
- package/dist/index.js.map +7 -0
- package/package.json +6 -1
- package/esbuild.config.js +0 -26
- package/src/cli/commands.ts +0 -573
- package/src/core/adr-exporter.ts +0 -253
- package/src/core/architecture/architecture-enforcement.ts +0 -228
- package/src/core/architecture/duplicate-detector.ts +0 -288
- package/src/core/architecture/index.ts +0 -6
- package/src/core/architecture/pattern-learner.ts +0 -306
- package/src/core/architecture/pattern-library.ts +0 -403
- package/src/core/architecture/pattern-validator.ts +0 -324
- package/src/core/change-intelligence/bug-correlator.ts +0 -544
- package/src/core/change-intelligence/change-intelligence.ts +0 -264
- package/src/core/change-intelligence/change-tracker.ts +0 -334
- package/src/core/change-intelligence/fix-suggester.ts +0 -340
- package/src/core/change-intelligence/index.ts +0 -5
- package/src/core/code-verifier.ts +0 -843
- package/src/core/confidence/confidence-scorer.ts +0 -251
- package/src/core/confidence/conflict-checker.ts +0 -289
- package/src/core/confidence/index.ts +0 -5
- package/src/core/confidence/source-tracker.ts +0 -263
- package/src/core/confidence/warning-detector.ts +0 -241
- package/src/core/context-rot/compaction.ts +0 -284
- package/src/core/context-rot/context-health.ts +0 -243
- package/src/core/context-rot/context-rot-prevention.ts +0 -213
- package/src/core/context-rot/critical-context.ts +0 -221
- package/src/core/context-rot/drift-detector.ts +0 -255
- package/src/core/context-rot/index.ts +0 -7
- package/src/core/context.ts +0 -263
- package/src/core/decision-extractor.ts +0 -339
- package/src/core/decisions.ts +0 -69
- package/src/core/deja-vu.ts +0 -421
- package/src/core/engine.ts +0 -1646
- package/src/core/feature-context.ts +0 -726
- package/src/core/ghost-mode.ts +0 -465
- package/src/core/learning.ts +0 -519
- package/src/core/living-docs/activity-tracker.ts +0 -296
- package/src/core/living-docs/architecture-generator.ts +0 -428
- package/src/core/living-docs/changelog-generator.ts +0 -348
- package/src/core/living-docs/component-generator.ts +0 -230
- package/src/core/living-docs/doc-engine.ts +0 -134
- package/src/core/living-docs/doc-validator.ts +0 -282
- package/src/core/living-docs/index.ts +0 -8
- package/src/core/project-manager.ts +0 -301
- package/src/core/refresh/activity-gate.ts +0 -256
- package/src/core/refresh/git-staleness-checker.ts +0 -108
- package/src/core/refresh/index.ts +0 -27
- package/src/core/summarizer.ts +0 -290
- package/src/core/test-awareness/change-validator.ts +0 -499
- package/src/core/test-awareness/index.ts +0 -5
- package/src/index.ts +0 -90
- package/src/indexing/ast.ts +0 -868
- package/src/indexing/embeddings.ts +0 -85
- package/src/indexing/indexer.ts +0 -270
- package/src/indexing/watcher.ts +0 -78
- package/src/server/gateways/aggregator.ts +0 -374
- package/src/server/gateways/index.ts +0 -473
- package/src/server/gateways/memory-ghost.ts +0 -343
- package/src/server/gateways/memory-query.ts +0 -452
- package/src/server/gateways/memory-record.ts +0 -346
- package/src/server/gateways/memory-review.ts +0 -410
- package/src/server/gateways/memory-status.ts +0 -517
- package/src/server/gateways/memory-verify.ts +0 -392
- package/src/server/gateways/router.ts +0 -434
- package/src/server/gateways/types.ts +0 -610
- package/src/server/http.ts +0 -228
- package/src/server/mcp.ts +0 -154
- package/src/server/resources.ts +0 -85
- package/src/server/tools.ts +0 -2460
- package/src/storage/database.ts +0 -271
- package/src/storage/tier1.ts +0 -135
- package/src/storage/tier2.ts +0 -972
- package/src/storage/tier3.ts +0 -123
- package/src/types/documentation.ts +0 -619
- package/src/types/index.ts +0 -222
- package/src/utils/config.ts +0 -194
- package/src/utils/files.ts +0 -117
- package/src/utils/time.ts +0 -37
- package/src/utils/tokens.ts +0 -52
package/src/indexing/ast.ts
DELETED
|
@@ -1,868 +0,0 @@
|
|
|
1
|
-
import Parser from 'web-tree-sitter';
|
|
2
|
-
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
3
|
-
import { join, dirname } from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import type { CodeSymbol, Import, Export, SymbolKind } from '../types/index.js';
|
|
6
|
-
|
|
7
|
-
// Language configurations for parsing
|
|
8
|
-
interface LanguageConfig {
|
|
9
|
-
wasmFile: string;
|
|
10
|
-
extensions: string[];
|
|
11
|
-
queries: {
|
|
12
|
-
functions?: string;
|
|
13
|
-
classes?: string;
|
|
14
|
-
interfaces?: string;
|
|
15
|
-
types?: string;
|
|
16
|
-
imports?: string;
|
|
17
|
-
exports?: string;
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const LANGUAGE_CONFIGS: Record<string, LanguageConfig> = {
|
|
22
|
-
typescript: {
|
|
23
|
-
wasmFile: 'tree-sitter-typescript.wasm',
|
|
24
|
-
extensions: ['.ts', '.tsx'],
|
|
25
|
-
queries: {
|
|
26
|
-
functions: `
|
|
27
|
-
(function_declaration name: (identifier) @name) @func
|
|
28
|
-
(arrow_function) @func
|
|
29
|
-
(method_definition name: (property_identifier) @name) @func
|
|
30
|
-
`,
|
|
31
|
-
classes: `
|
|
32
|
-
(class_declaration name: (type_identifier) @name) @class
|
|
33
|
-
`,
|
|
34
|
-
interfaces: `
|
|
35
|
-
(interface_declaration name: (type_identifier) @name) @interface
|
|
36
|
-
`,
|
|
37
|
-
types: `
|
|
38
|
-
(type_alias_declaration name: (type_identifier) @name) @type
|
|
39
|
-
`,
|
|
40
|
-
imports: `
|
|
41
|
-
(import_statement) @import
|
|
42
|
-
`,
|
|
43
|
-
exports: `
|
|
44
|
-
(export_statement) @export
|
|
45
|
-
`
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
javascript: {
|
|
49
|
-
wasmFile: 'tree-sitter-javascript.wasm',
|
|
50
|
-
extensions: ['.js', '.jsx', '.mjs', '.cjs'],
|
|
51
|
-
queries: {
|
|
52
|
-
functions: `
|
|
53
|
-
(function_declaration name: (identifier) @name) @func
|
|
54
|
-
(arrow_function) @func
|
|
55
|
-
(method_definition name: (property_identifier) @name) @func
|
|
56
|
-
`,
|
|
57
|
-
classes: `
|
|
58
|
-
(class_declaration name: (identifier) @name) @class
|
|
59
|
-
`,
|
|
60
|
-
imports: `
|
|
61
|
-
(import_statement) @import
|
|
62
|
-
`,
|
|
63
|
-
exports: `
|
|
64
|
-
(export_statement) @export
|
|
65
|
-
`
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
python: {
|
|
69
|
-
wasmFile: 'tree-sitter-python.wasm',
|
|
70
|
-
extensions: ['.py'],
|
|
71
|
-
queries: {
|
|
72
|
-
functions: `
|
|
73
|
-
(function_definition name: (identifier) @name) @func
|
|
74
|
-
`,
|
|
75
|
-
classes: `
|
|
76
|
-
(class_definition name: (identifier) @name) @class
|
|
77
|
-
`,
|
|
78
|
-
imports: `
|
|
79
|
-
(import_statement) @import
|
|
80
|
-
(import_from_statement) @import
|
|
81
|
-
`
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
go: {
|
|
85
|
-
wasmFile: 'tree-sitter-go.wasm',
|
|
86
|
-
extensions: ['.go'],
|
|
87
|
-
queries: {
|
|
88
|
-
functions: `(function_declaration name: (identifier) @name) @func`,
|
|
89
|
-
classes: `(type_declaration (type_spec name: (type_identifier) @name type: (struct_type))) @class`
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
rust: {
|
|
93
|
-
wasmFile: 'tree-sitter-rust.wasm',
|
|
94
|
-
extensions: ['.rs'],
|
|
95
|
-
queries: {
|
|
96
|
-
functions: `(function_item name: (identifier) @name) @func`,
|
|
97
|
-
classes: `(struct_item name: (type_identifier) @name) @class`
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
java: {
|
|
101
|
-
wasmFile: 'tree-sitter-java.wasm',
|
|
102
|
-
extensions: ['.java'],
|
|
103
|
-
queries: {
|
|
104
|
-
functions: `(method_declaration name: (identifier) @name) @func`,
|
|
105
|
-
classes: `(class_declaration name: (identifier) @name) @class`
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export class ASTParser {
|
|
111
|
-
private parser: Parser | null = null;
|
|
112
|
-
private languages: Map<string, Parser.Language> = new Map();
|
|
113
|
-
private initialized = false;
|
|
114
|
-
private dataDir: string;
|
|
115
|
-
|
|
116
|
-
constructor(dataDir: string) {
|
|
117
|
-
this.dataDir = dataDir;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async initialize(): Promise<void> {
|
|
121
|
-
if (this.initialized) return;
|
|
122
|
-
// Using regex-based parsing for reliable cross-platform support
|
|
123
|
-
// Tree-sitter WASM support reserved for future enhancement
|
|
124
|
-
this.initialized = true;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
private async loadLanguage(_langName: string): Promise<Parser.Language | null> {
|
|
128
|
-
// Tree-sitter WASM loading not implemented - using regex fallback
|
|
129
|
-
// Language configs are retained for future tree-sitter support
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
getLanguageForFile(filePath: string): string | null {
|
|
134
|
-
const ext = filePath.slice(filePath.lastIndexOf('.')).toLowerCase();
|
|
135
|
-
|
|
136
|
-
for (const [lang, config] of Object.entries(LANGUAGE_CONFIGS)) {
|
|
137
|
-
if (config.extensions.includes(ext)) {
|
|
138
|
-
return lang;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async parseFile(filePath: string, content: string): Promise<{
|
|
145
|
-
symbols: CodeSymbol[];
|
|
146
|
-
imports: Import[];
|
|
147
|
-
exports: Export[];
|
|
148
|
-
} | null> {
|
|
149
|
-
if (!this.initialized) {
|
|
150
|
-
await this.initialize();
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Regex-based parsing - reliable cross-platform symbol extraction
|
|
154
|
-
return this.parseWithRegex(filePath, content);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Regex-based parsing for symbol extraction
|
|
158
|
-
// Handles: functions, classes, interfaces, types, imports, exports
|
|
159
|
-
// Supports: TypeScript, JavaScript, Python, Go, Rust, Java
|
|
160
|
-
private parseWithRegex(filePath: string, content: string): {
|
|
161
|
-
symbols: CodeSymbol[];
|
|
162
|
-
imports: Import[];
|
|
163
|
-
exports: Export[];
|
|
164
|
-
} {
|
|
165
|
-
const symbols: CodeSymbol[] = [];
|
|
166
|
-
const imports: Import[] = [];
|
|
167
|
-
const exports: Export[] = [];
|
|
168
|
-
const lines = content.split('\n');
|
|
169
|
-
const lang = this.getLanguageForFile(filePath);
|
|
170
|
-
|
|
171
|
-
if (lang === 'typescript' || lang === 'javascript') {
|
|
172
|
-
this.parseTypeScriptJS(filePath, content, lines, symbols, imports, exports);
|
|
173
|
-
} else if (lang === 'python') {
|
|
174
|
-
this.parsePython(filePath, content, lines, symbols, imports, exports);
|
|
175
|
-
} else if (lang === 'go') {
|
|
176
|
-
this.parseGo(filePath, content, lines, symbols, imports, exports);
|
|
177
|
-
} else if (lang === 'rust') {
|
|
178
|
-
this.parseRust(filePath, content, lines, symbols, imports, exports);
|
|
179
|
-
} else if (lang === 'java') {
|
|
180
|
-
this.parseJava(filePath, content, lines, symbols, imports, exports);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return { symbols, imports, exports };
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
private parseTypeScriptJS(
|
|
187
|
-
filePath: string,
|
|
188
|
-
content: string,
|
|
189
|
-
lines: string[],
|
|
190
|
-
symbols: CodeSymbol[],
|
|
191
|
-
imports: Import[],
|
|
192
|
-
exports: Export[]
|
|
193
|
-
): void {
|
|
194
|
-
// Patterns for TypeScript/JavaScript
|
|
195
|
-
const patterns = {
|
|
196
|
-
// Functions: function name(), export default function name(), const name = () =>
|
|
197
|
-
function: /^(?:export\s+)?(?:default\s+)?(?:async\s+)?function\s+(\w+)/,
|
|
198
|
-
// Arrow functions: handles type annotations and destructured params
|
|
199
|
-
arrowFunc: /^(?:export\s+)?(?:const|let|var)\s+(\w+)\s*(?::\s*[^=]+)?\s*=\s*(?:async\s+)?(?:\([^)]*\)|[a-zA-Z_]\w*)\s*(?::\s*[^=]+)?\s*=>/,
|
|
200
|
-
// Classes
|
|
201
|
-
class: /^(?:export\s+)?(?:default\s+)?(?:abstract\s+)?class\s+(\w+)/,
|
|
202
|
-
// Interfaces (TS only)
|
|
203
|
-
interface: /^(?:export\s+)?interface\s+(\w+)/,
|
|
204
|
-
// Types (TS only)
|
|
205
|
-
type: /^(?:export\s+)?type\s+(\w+)\s*(?:<[^>]*>)?\s*=/,
|
|
206
|
-
// Imports - supports 'import type'
|
|
207
|
-
import: /^import\s+(?:type\s+)?(?:(\w+)(?:\s*,\s*)?)?(?:\{([^}]+)\})?\s*from\s*['"]([^'"]+)['"]/,
|
|
208
|
-
importAll: /^import\s+(?:type\s+)?\*\s+as\s+(\w+)\s+from\s*['"]([^'"]+)['"]/,
|
|
209
|
-
importSideEffect: /^import\s*['"]([^'"]+)['"]/,
|
|
210
|
-
// Exports
|
|
211
|
-
exportNamed: /^export\s+(?:type\s+)?\{([^}]+)\}/,
|
|
212
|
-
exportDefault: /^export\s+default\s+(?:class|function|const|let|var)?\s*(\w+)?/,
|
|
213
|
-
exportDirect: /^export\s+(?:const|let|var|function|class|interface|type|enum|async\s+function)\s+(\w+)/,
|
|
214
|
-
// Enums (TS)
|
|
215
|
-
enum: /^(?:export\s+)?(?:const\s+)?enum\s+(\w+)/,
|
|
216
|
-
// Methods inside classes - handles generics, readonly, and all modifiers
|
|
217
|
-
method: /^\s+(?:async\s+)?(?:static\s+)?(?:readonly\s+)?(?:private\s+|public\s+|protected\s+)?(?:get\s+|set\s+)?(\w+)\s*(?:<[^>]+>)?\s*\(/,
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
let currentClass: { name: string; startLine: number } | null = null;
|
|
221
|
-
let braceDepth = 0;
|
|
222
|
-
let inBlockComment = false;
|
|
223
|
-
|
|
224
|
-
for (let i = 0; i < lines.length; i++) {
|
|
225
|
-
const line = lines[i] || '';
|
|
226
|
-
const trimmed = line.trim();
|
|
227
|
-
const lineNum = i + 1;
|
|
228
|
-
|
|
229
|
-
// Track block comments properly
|
|
230
|
-
if (inBlockComment) {
|
|
231
|
-
if (trimmed.includes('*/')) {
|
|
232
|
-
inBlockComment = false;
|
|
233
|
-
}
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Skip single-line comments
|
|
238
|
-
if (trimmed.startsWith('//')) {
|
|
239
|
-
continue;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Handle block comment start
|
|
243
|
-
if (trimmed.startsWith('/*')) {
|
|
244
|
-
if (!trimmed.includes('*/')) {
|
|
245
|
-
inBlockComment = true;
|
|
246
|
-
}
|
|
247
|
-
continue;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Track brace depth for class scope
|
|
251
|
-
braceDepth += (line.match(/\{/g) || []).length;
|
|
252
|
-
braceDepth -= (line.match(/\}/g) || []).length;
|
|
253
|
-
|
|
254
|
-
if (currentClass && braceDepth === 0) {
|
|
255
|
-
// Class ended
|
|
256
|
-
const existingSymbol = symbols.find(s => s.name === currentClass!.name && s.kind === 'class');
|
|
257
|
-
if (existingSymbol) {
|
|
258
|
-
existingSymbol.lineEnd = lineNum;
|
|
259
|
-
}
|
|
260
|
-
currentClass = null;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// Functions
|
|
264
|
-
let match = trimmed.match(patterns.function);
|
|
265
|
-
if (match && match[1]) {
|
|
266
|
-
symbols.push({
|
|
267
|
-
fileId: 0,
|
|
268
|
-
filePath,
|
|
269
|
-
kind: 'function',
|
|
270
|
-
name: match[1],
|
|
271
|
-
lineStart: lineNum,
|
|
272
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
273
|
-
exported: trimmed.startsWith('export'),
|
|
274
|
-
signature: this.extractSignature(trimmed)
|
|
275
|
-
});
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Arrow functions
|
|
280
|
-
match = trimmed.match(patterns.arrowFunc);
|
|
281
|
-
if (match && match[1]) {
|
|
282
|
-
symbols.push({
|
|
283
|
-
fileId: 0,
|
|
284
|
-
filePath,
|
|
285
|
-
kind: 'function',
|
|
286
|
-
name: match[1],
|
|
287
|
-
lineStart: lineNum,
|
|
288
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
289
|
-
exported: trimmed.startsWith('export'),
|
|
290
|
-
signature: this.extractSignature(trimmed)
|
|
291
|
-
});
|
|
292
|
-
continue;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// Classes
|
|
296
|
-
match = trimmed.match(patterns.class);
|
|
297
|
-
if (match && match[1]) {
|
|
298
|
-
currentClass = { name: match[1], startLine: lineNum };
|
|
299
|
-
braceDepth = 1; // Reset for class tracking
|
|
300
|
-
symbols.push({
|
|
301
|
-
fileId: 0,
|
|
302
|
-
filePath,
|
|
303
|
-
kind: 'class',
|
|
304
|
-
name: match[1],
|
|
305
|
-
lineStart: lineNum,
|
|
306
|
-
lineEnd: lineNum, // Will be updated when class ends
|
|
307
|
-
exported: trimmed.startsWith('export')
|
|
308
|
-
});
|
|
309
|
-
continue;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// Interfaces
|
|
313
|
-
match = trimmed.match(patterns.interface);
|
|
314
|
-
if (match && match[1]) {
|
|
315
|
-
symbols.push({
|
|
316
|
-
fileId: 0,
|
|
317
|
-
filePath,
|
|
318
|
-
kind: 'interface',
|
|
319
|
-
name: match[1],
|
|
320
|
-
lineStart: lineNum,
|
|
321
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
322
|
-
exported: trimmed.startsWith('export')
|
|
323
|
-
});
|
|
324
|
-
continue;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// Types
|
|
328
|
-
match = trimmed.match(patterns.type);
|
|
329
|
-
if (match && match[1]) {
|
|
330
|
-
symbols.push({
|
|
331
|
-
fileId: 0,
|
|
332
|
-
filePath,
|
|
333
|
-
kind: 'type',
|
|
334
|
-
name: match[1],
|
|
335
|
-
lineStart: lineNum,
|
|
336
|
-
lineEnd: this.findStatementEnd(lines, i),
|
|
337
|
-
exported: trimmed.startsWith('export')
|
|
338
|
-
});
|
|
339
|
-
continue;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// Enums
|
|
343
|
-
match = trimmed.match(patterns.enum);
|
|
344
|
-
if (match && match[1]) {
|
|
345
|
-
symbols.push({
|
|
346
|
-
fileId: 0,
|
|
347
|
-
filePath,
|
|
348
|
-
kind: 'enum',
|
|
349
|
-
name: match[1],
|
|
350
|
-
lineStart: lineNum,
|
|
351
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
352
|
-
exported: trimmed.startsWith('export')
|
|
353
|
-
});
|
|
354
|
-
continue;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// Methods (when inside a class)
|
|
358
|
-
if (currentClass) {
|
|
359
|
-
match = trimmed.match(patterns.method);
|
|
360
|
-
if (match && match[1] && !['if', 'for', 'while', 'switch', 'catch', 'constructor'].includes(match[1])) {
|
|
361
|
-
symbols.push({
|
|
362
|
-
fileId: 0,
|
|
363
|
-
filePath,
|
|
364
|
-
kind: 'method',
|
|
365
|
-
name: `${currentClass.name}.${match[1]}`,
|
|
366
|
-
lineStart: lineNum,
|
|
367
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
368
|
-
exported: false // Methods inherit class export status
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Imports
|
|
374
|
-
match = trimmed.match(patterns.import);
|
|
375
|
-
if (match) {
|
|
376
|
-
const defaultImport = match[1];
|
|
377
|
-
const namedImports = match[2]?.split(',').map(s => s.trim().split(/\s+as\s+/)[0]?.trim()).filter((s): s is string => !!s) || [];
|
|
378
|
-
const from = match[3] || '';
|
|
379
|
-
|
|
380
|
-
imports.push({
|
|
381
|
-
fileId: 0,
|
|
382
|
-
filePath,
|
|
383
|
-
importedFrom: from,
|
|
384
|
-
importedSymbols: defaultImport ? [defaultImport, ...namedImports] : namedImports,
|
|
385
|
-
isDefault: !!defaultImport,
|
|
386
|
-
isNamespace: false,
|
|
387
|
-
lineNumber: lineNum
|
|
388
|
-
});
|
|
389
|
-
continue;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
match = trimmed.match(patterns.importAll);
|
|
393
|
-
if (match) {
|
|
394
|
-
imports.push({
|
|
395
|
-
fileId: 0,
|
|
396
|
-
filePath,
|
|
397
|
-
importedFrom: match[2] || '',
|
|
398
|
-
importedSymbols: ['*'],
|
|
399
|
-
isDefault: false,
|
|
400
|
-
isNamespace: true,
|
|
401
|
-
lineNumber: lineNum
|
|
402
|
-
});
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
// Exports
|
|
407
|
-
match = trimmed.match(patterns.exportDirect);
|
|
408
|
-
if (match && match[1]) {
|
|
409
|
-
exports.push({
|
|
410
|
-
fileId: 0,
|
|
411
|
-
filePath,
|
|
412
|
-
exportedName: match[1],
|
|
413
|
-
isDefault: false,
|
|
414
|
-
lineNumber: lineNum
|
|
415
|
-
});
|
|
416
|
-
continue;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
match = trimmed.match(patterns.exportDefault);
|
|
420
|
-
if (match) {
|
|
421
|
-
exports.push({
|
|
422
|
-
fileId: 0,
|
|
423
|
-
filePath,
|
|
424
|
-
exportedName: match[1] || 'default',
|
|
425
|
-
isDefault: true,
|
|
426
|
-
lineNumber: lineNum
|
|
427
|
-
});
|
|
428
|
-
continue;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
match = trimmed.match(patterns.exportNamed);
|
|
432
|
-
if (match && match[1]) {
|
|
433
|
-
const names = match[1].split(',').map(s => {
|
|
434
|
-
const parts = s.trim().split(/\s+as\s+/);
|
|
435
|
-
return parts[parts.length - 1]?.trim();
|
|
436
|
-
}).filter((n): n is string => !!n);
|
|
437
|
-
|
|
438
|
-
for (const name of names) {
|
|
439
|
-
exports.push({
|
|
440
|
-
fileId: 0,
|
|
441
|
-
filePath,
|
|
442
|
-
exportedName: name,
|
|
443
|
-
isDefault: false,
|
|
444
|
-
lineNumber: lineNum
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
private parsePython(
|
|
452
|
-
filePath: string,
|
|
453
|
-
content: string,
|
|
454
|
-
lines: string[],
|
|
455
|
-
symbols: CodeSymbol[],
|
|
456
|
-
imports: Import[],
|
|
457
|
-
exports: Export[]
|
|
458
|
-
): void {
|
|
459
|
-
const patterns = {
|
|
460
|
-
function: /^(?:async\s+)?def\s+(\w+)\s*\(/,
|
|
461
|
-
class: /^class\s+(\w+)/,
|
|
462
|
-
import: /^import\s+(\w+(?:\.\w+)*)/,
|
|
463
|
-
fromImport: /^from\s+(\w+(?:\.\w+)*)\s+import\s+(.+)/,
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
for (let i = 0; i < lines.length; i++) {
|
|
467
|
-
const line = lines[i] || '';
|
|
468
|
-
const trimmed = line.trim();
|
|
469
|
-
const lineNum = i + 1;
|
|
470
|
-
const indent = line.length - line.trimStart().length;
|
|
471
|
-
|
|
472
|
-
// Skip comments
|
|
473
|
-
if (trimmed.startsWith('#')) continue;
|
|
474
|
-
|
|
475
|
-
// Functions
|
|
476
|
-
let match = trimmed.match(patterns.function);
|
|
477
|
-
if (match && match[1]) {
|
|
478
|
-
symbols.push({
|
|
479
|
-
fileId: 0,
|
|
480
|
-
filePath,
|
|
481
|
-
kind: 'function',
|
|
482
|
-
name: match[1],
|
|
483
|
-
lineStart: lineNum,
|
|
484
|
-
lineEnd: this.findPythonBlockEnd(lines, i, indent),
|
|
485
|
-
exported: !match[1].startsWith('_'),
|
|
486
|
-
signature: trimmed.split(':')[0]
|
|
487
|
-
});
|
|
488
|
-
continue;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// Classes
|
|
492
|
-
match = trimmed.match(patterns.class);
|
|
493
|
-
if (match && match[1]) {
|
|
494
|
-
symbols.push({
|
|
495
|
-
fileId: 0,
|
|
496
|
-
filePath,
|
|
497
|
-
kind: 'class',
|
|
498
|
-
name: match[1],
|
|
499
|
-
lineStart: lineNum,
|
|
500
|
-
lineEnd: this.findPythonBlockEnd(lines, i, indent),
|
|
501
|
-
exported: !match[1].startsWith('_')
|
|
502
|
-
});
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// Imports
|
|
507
|
-
match = trimmed.match(patterns.import);
|
|
508
|
-
if (match && match[1]) {
|
|
509
|
-
imports.push({
|
|
510
|
-
fileId: 0,
|
|
511
|
-
filePath,
|
|
512
|
-
importedFrom: match[1],
|
|
513
|
-
importedSymbols: [match[1].split('.').pop() || match[1]],
|
|
514
|
-
isDefault: false,
|
|
515
|
-
isNamespace: true,
|
|
516
|
-
lineNumber: lineNum
|
|
517
|
-
});
|
|
518
|
-
continue;
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
match = trimmed.match(patterns.fromImport);
|
|
522
|
-
if (match) {
|
|
523
|
-
const from = match[1] || '';
|
|
524
|
-
const imported = match[2]?.split(',').map(s => s.trim().split(/\s+as\s+/)[0]?.trim()).filter((s): s is string => !!s) || [];
|
|
525
|
-
imports.push({
|
|
526
|
-
fileId: 0,
|
|
527
|
-
filePath,
|
|
528
|
-
importedFrom: from,
|
|
529
|
-
importedSymbols: imported,
|
|
530
|
-
isDefault: false,
|
|
531
|
-
isNamespace: imported.includes('*'),
|
|
532
|
-
lineNumber: lineNum
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
private parseGo(
|
|
539
|
-
filePath: string,
|
|
540
|
-
content: string,
|
|
541
|
-
lines: string[],
|
|
542
|
-
symbols: CodeSymbol[],
|
|
543
|
-
imports: Import[],
|
|
544
|
-
exports: Export[]
|
|
545
|
-
): void {
|
|
546
|
-
let inImportBlock = false;
|
|
547
|
-
|
|
548
|
-
for (let i = 0; i < lines.length; i++) {
|
|
549
|
-
const line = lines[i] || '';
|
|
550
|
-
const trimmed = line.trim();
|
|
551
|
-
const lineNum = i + 1;
|
|
552
|
-
|
|
553
|
-
// Skip comments
|
|
554
|
-
if (trimmed.startsWith('//')) continue;
|
|
555
|
-
|
|
556
|
-
// Handle import blocks
|
|
557
|
-
if (trimmed === 'import (') {
|
|
558
|
-
inImportBlock = true;
|
|
559
|
-
continue;
|
|
560
|
-
}
|
|
561
|
-
if (inImportBlock && trimmed === ')') {
|
|
562
|
-
inImportBlock = false;
|
|
563
|
-
continue;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
// Single import or import block item
|
|
567
|
-
const importMatch = inImportBlock
|
|
568
|
-
? trimmed.match(/^(?:(\w+)\s+)?"([^"]+)"/)
|
|
569
|
-
: trimmed.match(/^import\s+(?:(\w+)\s+)?"([^"]+)"/);
|
|
570
|
-
if (importMatch) {
|
|
571
|
-
const alias = importMatch[1];
|
|
572
|
-
const path = importMatch[2] || '';
|
|
573
|
-
const pkg = alias || path.split('/').pop() || '';
|
|
574
|
-
imports.push({
|
|
575
|
-
fileId: 0,
|
|
576
|
-
filePath,
|
|
577
|
-
importedFrom: path,
|
|
578
|
-
importedSymbols: [pkg],
|
|
579
|
-
isDefault: false,
|
|
580
|
-
isNamespace: false,
|
|
581
|
-
lineNumber: lineNum
|
|
582
|
-
});
|
|
583
|
-
continue;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// Functions and methods
|
|
587
|
-
const funcMatch = trimmed.match(/^func\s+(?:\((\w+)\s+\*?(\w+)\)\s+)?(\w+)\s*\(/);
|
|
588
|
-
if (funcMatch) {
|
|
589
|
-
const receiver = funcMatch[2];
|
|
590
|
-
const name = receiver ? `${receiver}.${funcMatch[3]}` : (funcMatch[3] || '');
|
|
591
|
-
symbols.push({
|
|
592
|
-
fileId: 0,
|
|
593
|
-
filePath,
|
|
594
|
-
kind: receiver ? 'method' : 'function',
|
|
595
|
-
name,
|
|
596
|
-
lineStart: lineNum,
|
|
597
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
598
|
-
exported: /^[A-Z]/.test(funcMatch[3] || ''),
|
|
599
|
-
signature: trimmed.split('{')[0]?.trim()
|
|
600
|
-
});
|
|
601
|
-
continue;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
// Structs
|
|
605
|
-
const structMatch = trimmed.match(/^type\s+(\w+)\s+struct\s*\{?/);
|
|
606
|
-
if (structMatch) {
|
|
607
|
-
symbols.push({
|
|
608
|
-
fileId: 0,
|
|
609
|
-
filePath,
|
|
610
|
-
kind: 'class',
|
|
611
|
-
name: structMatch[1] || '',
|
|
612
|
-
lineStart: lineNum,
|
|
613
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
614
|
-
exported: /^[A-Z]/.test(structMatch[1] || '')
|
|
615
|
-
});
|
|
616
|
-
continue;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
// Interfaces
|
|
620
|
-
const ifaceMatch = trimmed.match(/^type\s+(\w+)\s+interface\s*\{?/);
|
|
621
|
-
if (ifaceMatch) {
|
|
622
|
-
symbols.push({
|
|
623
|
-
fileId: 0,
|
|
624
|
-
filePath,
|
|
625
|
-
kind: 'interface',
|
|
626
|
-
name: ifaceMatch[1] || '',
|
|
627
|
-
lineStart: lineNum,
|
|
628
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
629
|
-
exported: /^[A-Z]/.test(ifaceMatch[1] || '')
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
private parseRust(
|
|
636
|
-
filePath: string,
|
|
637
|
-
content: string,
|
|
638
|
-
lines: string[],
|
|
639
|
-
symbols: CodeSymbol[],
|
|
640
|
-
imports: Import[],
|
|
641
|
-
exports: Export[]
|
|
642
|
-
): void {
|
|
643
|
-
for (let i = 0; i < lines.length; i++) {
|
|
644
|
-
const line = lines[i] || '';
|
|
645
|
-
const trimmed = line.trim();
|
|
646
|
-
const lineNum = i + 1;
|
|
647
|
-
|
|
648
|
-
// Skip comments
|
|
649
|
-
if (trimmed.startsWith('//')) continue;
|
|
650
|
-
|
|
651
|
-
// Functions
|
|
652
|
-
const fnMatch = trimmed.match(/^(?:pub\s+)?(?:async\s+)?fn\s+(\w+)/);
|
|
653
|
-
if (fnMatch) {
|
|
654
|
-
symbols.push({
|
|
655
|
-
fileId: 0,
|
|
656
|
-
filePath,
|
|
657
|
-
kind: 'function',
|
|
658
|
-
name: fnMatch[1] || '',
|
|
659
|
-
lineStart: lineNum,
|
|
660
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
661
|
-
exported: trimmed.startsWith('pub'),
|
|
662
|
-
signature: trimmed.split('{')[0]?.trim()
|
|
663
|
-
});
|
|
664
|
-
continue;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
// Structs
|
|
668
|
-
const structMatch = trimmed.match(/^(?:pub\s+)?struct\s+(\w+)/);
|
|
669
|
-
if (structMatch) {
|
|
670
|
-
symbols.push({
|
|
671
|
-
fileId: 0,
|
|
672
|
-
filePath,
|
|
673
|
-
kind: 'class',
|
|
674
|
-
name: structMatch[1] || '',
|
|
675
|
-
lineStart: lineNum,
|
|
676
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
677
|
-
exported: trimmed.startsWith('pub')
|
|
678
|
-
});
|
|
679
|
-
continue;
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
// Enums
|
|
683
|
-
const enumMatch = trimmed.match(/^(?:pub\s+)?enum\s+(\w+)/);
|
|
684
|
-
if (enumMatch) {
|
|
685
|
-
symbols.push({
|
|
686
|
-
fileId: 0,
|
|
687
|
-
filePath,
|
|
688
|
-
kind: 'enum',
|
|
689
|
-
name: enumMatch[1] || '',
|
|
690
|
-
lineStart: lineNum,
|
|
691
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
692
|
-
exported: trimmed.startsWith('pub')
|
|
693
|
-
});
|
|
694
|
-
continue;
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
// Traits (similar to interfaces)
|
|
698
|
-
const traitMatch = trimmed.match(/^(?:pub\s+)?trait\s+(\w+)/);
|
|
699
|
-
if (traitMatch) {
|
|
700
|
-
symbols.push({
|
|
701
|
-
fileId: 0,
|
|
702
|
-
filePath,
|
|
703
|
-
kind: 'interface',
|
|
704
|
-
name: traitMatch[1] || '',
|
|
705
|
-
lineStart: lineNum,
|
|
706
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
707
|
-
exported: trimmed.startsWith('pub')
|
|
708
|
-
});
|
|
709
|
-
continue;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
// Impl blocks
|
|
713
|
-
const implMatch = trimmed.match(/^impl\s+(?:<[^>]+>\s+)?(?:(\w+)\s+for\s+)?(\w+)/);
|
|
714
|
-
if (implMatch) {
|
|
715
|
-
const traitName = implMatch[1];
|
|
716
|
-
const typeName = implMatch[2] || '';
|
|
717
|
-
const name = traitName ? `${traitName} for ${typeName}` : typeName;
|
|
718
|
-
symbols.push({
|
|
719
|
-
fileId: 0,
|
|
720
|
-
filePath,
|
|
721
|
-
kind: 'class',
|
|
722
|
-
name: `impl ${name}`,
|
|
723
|
-
lineStart: lineNum,
|
|
724
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
725
|
-
exported: false
|
|
726
|
-
});
|
|
727
|
-
continue;
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
// use statements
|
|
731
|
-
const useMatch = trimmed.match(/^(?:pub\s+)?use\s+(.+);/);
|
|
732
|
-
if (useMatch) {
|
|
733
|
-
const path = (useMatch[1] || '').replace(/::/g, '/');
|
|
734
|
-
imports.push({
|
|
735
|
-
fileId: 0,
|
|
736
|
-
filePath,
|
|
737
|
-
importedFrom: path,
|
|
738
|
-
importedSymbols: [path.split('/').pop()?.replace(/[{}]/g, '') || ''],
|
|
739
|
-
isDefault: false,
|
|
740
|
-
isNamespace: path.includes('*'),
|
|
741
|
-
lineNumber: lineNum
|
|
742
|
-
});
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
private parseJava(
|
|
748
|
-
filePath: string,
|
|
749
|
-
content: string,
|
|
750
|
-
lines: string[],
|
|
751
|
-
symbols: CodeSymbol[],
|
|
752
|
-
imports: Import[],
|
|
753
|
-
exports: Export[]
|
|
754
|
-
): void {
|
|
755
|
-
let currentClass: string | null = null;
|
|
756
|
-
|
|
757
|
-
for (let i = 0; i < lines.length; i++) {
|
|
758
|
-
const line = lines[i] || '';
|
|
759
|
-
const trimmed = line.trim();
|
|
760
|
-
const lineNum = i + 1;
|
|
761
|
-
|
|
762
|
-
// Skip comments
|
|
763
|
-
if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*')) continue;
|
|
764
|
-
|
|
765
|
-
// Imports
|
|
766
|
-
const importMatch = trimmed.match(/^import\s+(?:static\s+)?([^;]+);/);
|
|
767
|
-
if (importMatch) {
|
|
768
|
-
const path = importMatch[1] || '';
|
|
769
|
-
imports.push({
|
|
770
|
-
fileId: 0,
|
|
771
|
-
filePath,
|
|
772
|
-
importedFrom: path,
|
|
773
|
-
importedSymbols: [path.split('.').pop() || ''],
|
|
774
|
-
isDefault: false,
|
|
775
|
-
isNamespace: path.endsWith('*'),
|
|
776
|
-
lineNumber: lineNum
|
|
777
|
-
});
|
|
778
|
-
continue;
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
// Classes and interfaces
|
|
782
|
-
const classMatch = trimmed.match(/^(?:public\s+|private\s+|protected\s+)?(?:abstract\s+)?(?:final\s+)?(class|interface|enum)\s+(\w+)/);
|
|
783
|
-
if (classMatch) {
|
|
784
|
-
currentClass = classMatch[2] || '';
|
|
785
|
-
symbols.push({
|
|
786
|
-
fileId: 0,
|
|
787
|
-
filePath,
|
|
788
|
-
kind: classMatch[1] === 'interface' ? 'interface' : classMatch[1] === 'enum' ? 'enum' : 'class',
|
|
789
|
-
name: currentClass,
|
|
790
|
-
lineStart: lineNum,
|
|
791
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
792
|
-
exported: trimmed.includes('public')
|
|
793
|
-
});
|
|
794
|
-
continue;
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
// Methods
|
|
798
|
-
const methodMatch = trimmed.match(/^(?:public\s+|private\s+|protected\s+)?(?:static\s+)?(?:final\s+)?(?:synchronized\s+)?(?:abstract\s+)?(?:<[^>]+>\s+)?(\w+(?:<[^>]+>)?)\s+(\w+)\s*\(/);
|
|
799
|
-
if (methodMatch && currentClass && !['if', 'for', 'while', 'switch', 'catch', 'class', 'interface', 'enum'].includes(methodMatch[2] || '')) {
|
|
800
|
-
const returnType = methodMatch[1];
|
|
801
|
-
const methodName = methodMatch[2] || '';
|
|
802
|
-
// Skip constructors (name matches class name)
|
|
803
|
-
if (methodName !== currentClass) {
|
|
804
|
-
symbols.push({
|
|
805
|
-
fileId: 0,
|
|
806
|
-
filePath,
|
|
807
|
-
kind: 'method',
|
|
808
|
-
name: `${currentClass}.${methodName}`,
|
|
809
|
-
lineStart: lineNum,
|
|
810
|
-
lineEnd: this.findBlockEnd(lines, i),
|
|
811
|
-
exported: trimmed.includes('public'),
|
|
812
|
-
signature: `${returnType} ${methodName}(...)`
|
|
813
|
-
});
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
private findBlockEnd(lines: string[], startIndex: number): number {
|
|
820
|
-
let braceCount = 0;
|
|
821
|
-
let started = false;
|
|
822
|
-
|
|
823
|
-
for (let i = startIndex; i < lines.length; i++) {
|
|
824
|
-
const line = lines[i] || '';
|
|
825
|
-
for (const char of line) {
|
|
826
|
-
if (char === '{') {
|
|
827
|
-
braceCount++;
|
|
828
|
-
started = true;
|
|
829
|
-
} else if (char === '}') {
|
|
830
|
-
braceCount--;
|
|
831
|
-
if (started && braceCount === 0) {
|
|
832
|
-
return i + 1;
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
return startIndex + 1;
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
private findStatementEnd(lines: string[], startIndex: number): number {
|
|
841
|
-
for (let i = startIndex; i < lines.length; i++) {
|
|
842
|
-
const line = lines[i] || '';
|
|
843
|
-
if (line.includes(';') || (i > startIndex && !line.trim().startsWith('|') && !line.trim().startsWith('&'))) {
|
|
844
|
-
return i + 1;
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
return startIndex + 1;
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
private findPythonBlockEnd(lines: string[], startIndex: number, baseIndent: number): number {
|
|
851
|
-
for (let i = startIndex + 1; i < lines.length; i++) {
|
|
852
|
-
const line = lines[i] || '';
|
|
853
|
-
if (line.trim() === '') continue;
|
|
854
|
-
|
|
855
|
-
const indent = line.length - line.trimStart().length;
|
|
856
|
-
if (indent <= baseIndent) {
|
|
857
|
-
return i;
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
return lines.length;
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
private extractSignature(line: string): string {
|
|
864
|
-
// Extract function signature from line
|
|
865
|
-
const match = line.match(/(?:function\s+\w+|const\s+\w+\s*=\s*(?:async\s+)?)\s*(\([^)]*\))/);
|
|
866
|
-
return match?.[1] || '';
|
|
867
|
-
}
|
|
868
|
-
}
|