snow-ai 0.2.14 → 0.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp/filesystem.d.ts
CHANGED
|
@@ -5,9 +5,6 @@ interface SearchMatch {
|
|
|
5
5
|
lineContent: string;
|
|
6
6
|
column: number;
|
|
7
7
|
matchedText?: string;
|
|
8
|
-
nodeType?: string;
|
|
9
|
-
nodeName?: string;
|
|
10
|
-
language?: string;
|
|
11
8
|
}
|
|
12
9
|
interface SearchResult {
|
|
13
10
|
query: string;
|
|
@@ -151,7 +148,7 @@ export declare class FilesystemMCPService {
|
|
|
151
148
|
* @param maxResults - Maximum number of results to return (default: 100)
|
|
152
149
|
* @returns Search results with file paths, line numbers, and matched content
|
|
153
150
|
*/
|
|
154
|
-
searchCode(query: string, dirPath?: string, fileExtensions?: string[], caseSensitive?: boolean, maxResults?: number, searchMode?: 'text' | 'regex'
|
|
151
|
+
searchCode(query: string, dirPath?: string, fileExtensions?: string[], caseSensitive?: boolean, maxResults?: number, searchMode?: 'text' | 'regex'): Promise<SearchResult>;
|
|
155
152
|
/**
|
|
156
153
|
* Resolve path relative to base path and normalize it
|
|
157
154
|
* @private
|
package/dist/mcp/filesystem.js
CHANGED
|
@@ -3,7 +3,6 @@ import * as path from 'path';
|
|
|
3
3
|
import { execSync } from 'child_process';
|
|
4
4
|
import { vscodeConnection } from '../utils/vscodeConnection.js';
|
|
5
5
|
import { incrementalSnapshotManager } from '../utils/incrementalSnapshot.js';
|
|
6
|
-
import { multiLanguageASTParser } from './multiLanguageASTParser.js';
|
|
7
6
|
const { resolve, dirname, isAbsolute } = path;
|
|
8
7
|
/**
|
|
9
8
|
* Filesystem MCP Service
|
|
@@ -660,37 +659,8 @@ export class FilesystemMCPService {
|
|
|
660
659
|
searchedFiles++;
|
|
661
660
|
try {
|
|
662
661
|
const content = await fs.readFile(fullPath, 'utf-8');
|
|
663
|
-
//
|
|
664
|
-
if (
|
|
665
|
-
// Check if file is supported for AST parsing
|
|
666
|
-
if (multiLanguageASTParser.isSupported(fullPath)) {
|
|
667
|
-
try {
|
|
668
|
-
const astResults = multiLanguageASTParser.searchAST(content, fullPath, query, caseSensitive);
|
|
669
|
-
for (const result of astResults) {
|
|
670
|
-
if (matches.length >= maxResults) {
|
|
671
|
-
break;
|
|
672
|
-
}
|
|
673
|
-
const lineContent = content.split('\n')[result.startPosition.line - 1] ||
|
|
674
|
-
'';
|
|
675
|
-
matches.push({
|
|
676
|
-
filePath: path.relative(this.basePath, fullPath),
|
|
677
|
-
lineNumber: result.startPosition.line,
|
|
678
|
-
lineContent: lineContent.trim(),
|
|
679
|
-
column: result.startPosition.column,
|
|
680
|
-
matchedText: result.name,
|
|
681
|
-
nodeType: result.type,
|
|
682
|
-
nodeName: result.name,
|
|
683
|
-
language: result.language,
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
catch (error) {
|
|
688
|
-
// Skip files with AST parsing errors
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
else if (searchRegex) {
|
|
693
|
-
// Text or Regex search mode
|
|
662
|
+
// Text or Regex search mode
|
|
663
|
+
if (searchRegex) {
|
|
694
664
|
const lines = content.split('\n');
|
|
695
665
|
lines.forEach((line, index) => {
|
|
696
666
|
if (matches.length >= maxResults) {
|
|
@@ -900,8 +870,8 @@ export const mcpTools = [
|
|
|
900
870
|
},
|
|
901
871
|
searchMode: {
|
|
902
872
|
type: 'string',
|
|
903
|
-
enum: ['text', 'regex'
|
|
904
|
-
description: 'Search mode: "text" for literal text search (default), "regex" for regular expression search
|
|
873
|
+
enum: ['text', 'regex'],
|
|
874
|
+
description: 'Search mode: "text" for literal text search (default), "regex" for regular expression search',
|
|
905
875
|
default: 'text',
|
|
906
876
|
},
|
|
907
877
|
},
|
|
@@ -392,8 +392,8 @@ export async function executeMCPTool(toolName, args) {
|
|
|
392
392
|
case 'edit':
|
|
393
393
|
return await filesystemService.editFile(args.filePath, args.startLine, args.endLine, args.newContent, args.contextLines);
|
|
394
394
|
case 'search': {
|
|
395
|
-
//
|
|
396
|
-
const validSearchModes = ['text', 'regex'
|
|
395
|
+
// 兼容性处理:如果 searchMode 不存在或无效,默认使用 'text'
|
|
396
|
+
const validSearchModes = ['text', 'regex'];
|
|
397
397
|
let searchMode = 'text';
|
|
398
398
|
if (args.searchMode && validSearchModes.includes(args.searchMode)) {
|
|
399
399
|
searchMode = args.searchMode;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "snow-ai",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.15",
|
|
4
4
|
"description": "Intelligent Command Line Assistant powered by AI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -59,18 +59,6 @@
|
|
|
59
59
|
"react": "^18.2.0",
|
|
60
60
|
"string-width": "^7.2.0",
|
|
61
61
|
"tiktoken": "^1.0.22",
|
|
62
|
-
"tree-sitter": "^0.25.0",
|
|
63
|
-
"tree-sitter-c": "^0.24.1",
|
|
64
|
-
"tree-sitter-c-sharp": "^0.23.1",
|
|
65
|
-
"tree-sitter-cpp": "^0.23.4",
|
|
66
|
-
"tree-sitter-go": "^0.25.0",
|
|
67
|
-
"tree-sitter-java": "^0.23.5",
|
|
68
|
-
"tree-sitter-javascript": "^0.25.0",
|
|
69
|
-
"tree-sitter-php": "^0.24.2",
|
|
70
|
-
"tree-sitter-python": "^0.25.0",
|
|
71
|
-
"tree-sitter-ruby": "^0.23.1",
|
|
72
|
-
"tree-sitter-rust": "^0.24.0",
|
|
73
|
-
"tree-sitter-typescript": "^0.23.2",
|
|
74
62
|
"ws": "^8.14.2"
|
|
75
63
|
},
|
|
76
64
|
"devDependencies": {
|
package/readme.md
CHANGED
|
@@ -57,9 +57,9 @@ $ npm uninstall --global snow-ai
|
|
|
57
57
|
|
|
58
58
|
## Install VSCode Extension
|
|
59
59
|
|
|
60
|
-
* download [VSIX/snow-cli-0.2.
|
|
60
|
+
* download [VSIX/snow-cli-0.2.6.vsix](https://github.com/MayDay-wpf/snow-cli/blob/main/VSIX/snow-cli-0.2.6.vsix)
|
|
61
61
|
|
|
62
|
-
* open VSCode, click `Extensions` -> `Install from VSIX...` -> select `snow-cli-0.2.
|
|
62
|
+
* open VSCode, click `Extensions` -> `Install from VSIX...` -> select `snow-cli-0.2.6.vsix`
|
|
63
63
|
|
|
64
64
|
## Live View
|
|
65
65
|
* **Welcome & Settings**
|
|
@@ -73,6 +73,8 @@ $ npm uninstall --global snow-ai
|
|
|
73
73
|
|
|
74
74
|
* When mounting: double-click ESC, view the dialogue recorder, select rollback, including file checkpoints
|
|
75
75
|
|
|
76
|
+
* Windows & MacOS:`ctrl + v` Paste image
|
|
77
|
+
|
|
76
78
|
* **Commands**
|
|
77
79
|
|
|
78
80
|

|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Supported programming languages for AST parsing
|
|
3
|
-
*/
|
|
4
|
-
export type SupportedLanguage = 'javascript' | 'typescript' | 'tsx' | 'python' | 'java' | 'go' | 'cpp' | 'c' | 'csharp' | 'rust' | 'ruby' | 'php';
|
|
5
|
-
/**
|
|
6
|
-
* AST node result with metadata
|
|
7
|
-
*/
|
|
8
|
-
export interface ASTNodeResult {
|
|
9
|
-
name: string;
|
|
10
|
-
type: string;
|
|
11
|
-
startPosition: {
|
|
12
|
-
line: number;
|
|
13
|
-
column: number;
|
|
14
|
-
};
|
|
15
|
-
endPosition: {
|
|
16
|
-
line: number;
|
|
17
|
-
column: number;
|
|
18
|
-
};
|
|
19
|
-
text: string;
|
|
20
|
-
language: SupportedLanguage;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Multi-language AST parser using tree-sitter
|
|
24
|
-
* Supports JavaScript, TypeScript, Python, Java, Go, C/C++, C#, Rust, Ruby, PHP
|
|
25
|
-
*/
|
|
26
|
-
export declare class MultiLanguageASTParser {
|
|
27
|
-
private parsers;
|
|
28
|
-
private languageConfigs;
|
|
29
|
-
constructor();
|
|
30
|
-
/**
|
|
31
|
-
* Initialize language configurations
|
|
32
|
-
*/
|
|
33
|
-
private initializeLanguageConfigs;
|
|
34
|
-
/**
|
|
35
|
-
* Initialize parsers for all supported languages
|
|
36
|
-
*/
|
|
37
|
-
private initializeParsers;
|
|
38
|
-
/**
|
|
39
|
-
* Detect language from file extension
|
|
40
|
-
*/
|
|
41
|
-
detectLanguage(filePath: string): SupportedLanguage | null;
|
|
42
|
-
/**
|
|
43
|
-
* Parse source code and search for nodes matching the query
|
|
44
|
-
*/
|
|
45
|
-
searchAST(sourceCode: string, filePath: string, query: string, caseSensitive?: boolean): ASTNodeResult[];
|
|
46
|
-
/**
|
|
47
|
-
* Extract the name/identifier from an AST node based on language
|
|
48
|
-
*/
|
|
49
|
-
private extractNodeName;
|
|
50
|
-
/**
|
|
51
|
-
* Recursively find the first identifier node
|
|
52
|
-
*/
|
|
53
|
-
private findIdentifier;
|
|
54
|
-
/**
|
|
55
|
-
* Get supported file extensions
|
|
56
|
-
*/
|
|
57
|
-
getSupportedExtensions(): string[];
|
|
58
|
-
/**
|
|
59
|
-
* Check if a file is supported for AST parsing
|
|
60
|
-
*/
|
|
61
|
-
isSupported(filePath: string): boolean;
|
|
62
|
-
/**
|
|
63
|
-
* Get node types for a specific language
|
|
64
|
-
*/
|
|
65
|
-
getNodeTypes(language: SupportedLanguage): string[];
|
|
66
|
-
}
|
|
67
|
-
export declare const multiLanguageASTParser: MultiLanguageASTParser;
|
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
import Parser from 'tree-sitter';
|
|
2
|
-
import JavaScript from 'tree-sitter-javascript';
|
|
3
|
-
import TypeScript from 'tree-sitter-typescript';
|
|
4
|
-
import Python from 'tree-sitter-python';
|
|
5
|
-
import Java from 'tree-sitter-java';
|
|
6
|
-
import Go from 'tree-sitter-go';
|
|
7
|
-
import Cpp from 'tree-sitter-cpp';
|
|
8
|
-
import C from 'tree-sitter-c';
|
|
9
|
-
import CSharp from 'tree-sitter-c-sharp';
|
|
10
|
-
import Rust from 'tree-sitter-rust';
|
|
11
|
-
import Ruby from 'tree-sitter-ruby';
|
|
12
|
-
import PHP from 'tree-sitter-php';
|
|
13
|
-
/**
|
|
14
|
-
* Multi-language AST parser using tree-sitter
|
|
15
|
-
* Supports JavaScript, TypeScript, Python, Java, Go, C/C++, C#, Rust, Ruby, PHP
|
|
16
|
-
*/
|
|
17
|
-
export class MultiLanguageASTParser {
|
|
18
|
-
constructor() {
|
|
19
|
-
Object.defineProperty(this, "parsers", {
|
|
20
|
-
enumerable: true,
|
|
21
|
-
configurable: true,
|
|
22
|
-
writable: true,
|
|
23
|
-
value: new Map()
|
|
24
|
-
});
|
|
25
|
-
Object.defineProperty(this, "languageConfigs", {
|
|
26
|
-
enumerable: true,
|
|
27
|
-
configurable: true,
|
|
28
|
-
writable: true,
|
|
29
|
-
value: new Map()
|
|
30
|
-
});
|
|
31
|
-
this.initializeLanguageConfigs();
|
|
32
|
-
this.initializeParsers();
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Initialize language configurations
|
|
36
|
-
*/
|
|
37
|
-
initializeLanguageConfigs() {
|
|
38
|
-
// JavaScript
|
|
39
|
-
this.languageConfigs.set('javascript', {
|
|
40
|
-
extensions: ['.js', '.jsx', '.mjs', '.cjs'],
|
|
41
|
-
parser: JavaScript,
|
|
42
|
-
nodeTypes: [
|
|
43
|
-
'function_declaration',
|
|
44
|
-
'arrow_function',
|
|
45
|
-
'function_expression',
|
|
46
|
-
'class_declaration',
|
|
47
|
-
'method_definition',
|
|
48
|
-
'variable_declarator',
|
|
49
|
-
'lexical_declaration',
|
|
50
|
-
],
|
|
51
|
-
});
|
|
52
|
-
// TypeScript
|
|
53
|
-
this.languageConfigs.set('typescript', {
|
|
54
|
-
extensions: ['.ts'],
|
|
55
|
-
parser: TypeScript.typescript,
|
|
56
|
-
nodeTypes: [
|
|
57
|
-
'function_declaration',
|
|
58
|
-
'arrow_function',
|
|
59
|
-
'function_expression',
|
|
60
|
-
'class_declaration',
|
|
61
|
-
'method_definition',
|
|
62
|
-
'interface_declaration',
|
|
63
|
-
'type_alias_declaration',
|
|
64
|
-
'enum_declaration',
|
|
65
|
-
'variable_declarator',
|
|
66
|
-
'lexical_declaration',
|
|
67
|
-
],
|
|
68
|
-
});
|
|
69
|
-
// TSX
|
|
70
|
-
this.languageConfigs.set('tsx', {
|
|
71
|
-
extensions: ['.tsx'],
|
|
72
|
-
parser: TypeScript.tsx,
|
|
73
|
-
nodeTypes: [
|
|
74
|
-
'function_declaration',
|
|
75
|
-
'arrow_function',
|
|
76
|
-
'function_expression',
|
|
77
|
-
'class_declaration',
|
|
78
|
-
'method_definition',
|
|
79
|
-
'interface_declaration',
|
|
80
|
-
'type_alias_declaration',
|
|
81
|
-
'enum_declaration',
|
|
82
|
-
'variable_declarator',
|
|
83
|
-
'lexical_declaration',
|
|
84
|
-
],
|
|
85
|
-
});
|
|
86
|
-
// Python
|
|
87
|
-
this.languageConfigs.set('python', {
|
|
88
|
-
extensions: ['.py', '.pyw'],
|
|
89
|
-
parser: Python,
|
|
90
|
-
nodeTypes: [
|
|
91
|
-
'function_definition',
|
|
92
|
-
'class_definition',
|
|
93
|
-
'decorated_definition',
|
|
94
|
-
'assignment',
|
|
95
|
-
],
|
|
96
|
-
});
|
|
97
|
-
// Java
|
|
98
|
-
this.languageConfigs.set('java', {
|
|
99
|
-
extensions: ['.java'],
|
|
100
|
-
parser: Java,
|
|
101
|
-
nodeTypes: [
|
|
102
|
-
'method_declaration',
|
|
103
|
-
'class_declaration',
|
|
104
|
-
'interface_declaration',
|
|
105
|
-
'enum_declaration',
|
|
106
|
-
'constructor_declaration',
|
|
107
|
-
'field_declaration',
|
|
108
|
-
],
|
|
109
|
-
});
|
|
110
|
-
// Go
|
|
111
|
-
this.languageConfigs.set('go', {
|
|
112
|
-
extensions: ['.go'],
|
|
113
|
-
parser: Go,
|
|
114
|
-
nodeTypes: [
|
|
115
|
-
'function_declaration',
|
|
116
|
-
'method_declaration',
|
|
117
|
-
'type_declaration',
|
|
118
|
-
'type_spec',
|
|
119
|
-
'var_declaration',
|
|
120
|
-
'const_declaration',
|
|
121
|
-
],
|
|
122
|
-
});
|
|
123
|
-
// C++
|
|
124
|
-
this.languageConfigs.set('cpp', {
|
|
125
|
-
extensions: ['.cpp', '.cc', '.cxx', '.hpp', '.hxx', '.h'],
|
|
126
|
-
parser: Cpp,
|
|
127
|
-
nodeTypes: [
|
|
128
|
-
'function_definition',
|
|
129
|
-
'function_declarator',
|
|
130
|
-
'class_specifier',
|
|
131
|
-
'struct_specifier',
|
|
132
|
-
'enum_specifier',
|
|
133
|
-
'namespace_definition',
|
|
134
|
-
'declaration',
|
|
135
|
-
],
|
|
136
|
-
});
|
|
137
|
-
// C
|
|
138
|
-
this.languageConfigs.set('c', {
|
|
139
|
-
extensions: ['.c', '.h'],
|
|
140
|
-
parser: C,
|
|
141
|
-
nodeTypes: [
|
|
142
|
-
'function_definition',
|
|
143
|
-
'function_declarator',
|
|
144
|
-
'struct_specifier',
|
|
145
|
-
'enum_specifier',
|
|
146
|
-
'declaration',
|
|
147
|
-
],
|
|
148
|
-
});
|
|
149
|
-
// C#
|
|
150
|
-
this.languageConfigs.set('csharp', {
|
|
151
|
-
extensions: ['.cs'],
|
|
152
|
-
parser: CSharp,
|
|
153
|
-
nodeTypes: [
|
|
154
|
-
'method_declaration',
|
|
155
|
-
'class_declaration',
|
|
156
|
-
'interface_declaration',
|
|
157
|
-
'struct_declaration',
|
|
158
|
-
'enum_declaration',
|
|
159
|
-
'property_declaration',
|
|
160
|
-
'field_declaration',
|
|
161
|
-
'constructor_declaration',
|
|
162
|
-
],
|
|
163
|
-
});
|
|
164
|
-
// Rust
|
|
165
|
-
this.languageConfigs.set('rust', {
|
|
166
|
-
extensions: ['.rs'],
|
|
167
|
-
parser: Rust,
|
|
168
|
-
nodeTypes: [
|
|
169
|
-
'function_item',
|
|
170
|
-
'struct_item',
|
|
171
|
-
'enum_item',
|
|
172
|
-
'trait_item',
|
|
173
|
-
'impl_item',
|
|
174
|
-
'mod_item',
|
|
175
|
-
'const_item',
|
|
176
|
-
'static_item',
|
|
177
|
-
],
|
|
178
|
-
});
|
|
179
|
-
// Ruby
|
|
180
|
-
this.languageConfigs.set('ruby', {
|
|
181
|
-
extensions: ['.rb'],
|
|
182
|
-
parser: Ruby,
|
|
183
|
-
nodeTypes: [
|
|
184
|
-
'method',
|
|
185
|
-
'singleton_method',
|
|
186
|
-
'class',
|
|
187
|
-
'module',
|
|
188
|
-
'assignment',
|
|
189
|
-
],
|
|
190
|
-
});
|
|
191
|
-
// PHP
|
|
192
|
-
this.languageConfigs.set('php', {
|
|
193
|
-
extensions: ['.php'],
|
|
194
|
-
parser: PHP.php,
|
|
195
|
-
nodeTypes: [
|
|
196
|
-
'function_definition',
|
|
197
|
-
'method_declaration',
|
|
198
|
-
'class_declaration',
|
|
199
|
-
'interface_declaration',
|
|
200
|
-
'trait_declaration',
|
|
201
|
-
'property_declaration',
|
|
202
|
-
],
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Initialize parsers for all supported languages
|
|
207
|
-
*/
|
|
208
|
-
initializeParsers() {
|
|
209
|
-
for (const [language, config] of this.languageConfigs.entries()) {
|
|
210
|
-
try {
|
|
211
|
-
const parser = new Parser();
|
|
212
|
-
parser.setLanguage(config.parser);
|
|
213
|
-
this.parsers.set(language, parser);
|
|
214
|
-
}
|
|
215
|
-
catch (error) {
|
|
216
|
-
console.error(`Failed to initialize parser for ${language}:`, error instanceof Error ? error.message : 'Unknown error');
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Detect language from file extension
|
|
222
|
-
*/
|
|
223
|
-
detectLanguage(filePath) {
|
|
224
|
-
const ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
|
|
225
|
-
for (const [language, config] of this.languageConfigs.entries()) {
|
|
226
|
-
if (config.extensions.includes(ext)) {
|
|
227
|
-
return language;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Parse source code and search for nodes matching the query
|
|
234
|
-
*/
|
|
235
|
-
searchAST(sourceCode, filePath, query, caseSensitive = false) {
|
|
236
|
-
const language = this.detectLanguage(filePath);
|
|
237
|
-
if (!language) {
|
|
238
|
-
return [];
|
|
239
|
-
}
|
|
240
|
-
const parser = this.parsers.get(language);
|
|
241
|
-
if (!parser) {
|
|
242
|
-
return [];
|
|
243
|
-
}
|
|
244
|
-
try {
|
|
245
|
-
const tree = parser.parse(sourceCode);
|
|
246
|
-
const results = [];
|
|
247
|
-
const searchQuery = caseSensitive ? query : query.toLowerCase();
|
|
248
|
-
// Traverse the AST
|
|
249
|
-
const traverse = (node) => {
|
|
250
|
-
const nodeType = node.type;
|
|
251
|
-
const config = this.languageConfigs.get(language);
|
|
252
|
-
// Check if this is a node type we're interested in
|
|
253
|
-
if (config && config.nodeTypes.includes(nodeType)) {
|
|
254
|
-
const nodeName = this.extractNodeName(node, language);
|
|
255
|
-
if (nodeName) {
|
|
256
|
-
const nameToCheck = caseSensitive
|
|
257
|
-
? nodeName
|
|
258
|
-
: nodeName.toLowerCase();
|
|
259
|
-
if (nameToCheck.includes(searchQuery)) {
|
|
260
|
-
results.push({
|
|
261
|
-
name: nodeName,
|
|
262
|
-
type: nodeType,
|
|
263
|
-
startPosition: {
|
|
264
|
-
line: node.startPosition.row + 1,
|
|
265
|
-
column: node.startPosition.column + 1,
|
|
266
|
-
},
|
|
267
|
-
endPosition: {
|
|
268
|
-
line: node.endPosition.row + 1,
|
|
269
|
-
column: node.endPosition.column + 1,
|
|
270
|
-
},
|
|
271
|
-
text: node.text,
|
|
272
|
-
language,
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
// Recursively traverse children
|
|
278
|
-
for (let i = 0; i < node.childCount; i++) {
|
|
279
|
-
const child = node.child(i);
|
|
280
|
-
if (child) {
|
|
281
|
-
traverse(child);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
};
|
|
285
|
-
traverse(tree.rootNode);
|
|
286
|
-
return results;
|
|
287
|
-
}
|
|
288
|
-
catch (error) {
|
|
289
|
-
console.error(`AST parsing error for ${filePath}:`, error instanceof Error ? error.message : 'Unknown error');
|
|
290
|
-
return [];
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Extract the name/identifier from an AST node based on language
|
|
295
|
-
*/
|
|
296
|
-
extractNodeName(node, _language) {
|
|
297
|
-
// Common patterns for extracting names from different node types
|
|
298
|
-
const nameFields = ['name', 'identifier', 'declarator', 'property'];
|
|
299
|
-
for (const field of nameFields) {
|
|
300
|
-
const nameNode = node.childForFieldName(field);
|
|
301
|
-
if (nameNode) {
|
|
302
|
-
// For some languages, we need to go deeper
|
|
303
|
-
if (nameNode.type === 'identifier') {
|
|
304
|
-
return nameNode.text;
|
|
305
|
-
}
|
|
306
|
-
// Try to find identifier in children
|
|
307
|
-
const identifierChild = this.findIdentifier(nameNode);
|
|
308
|
-
if (identifierChild) {
|
|
309
|
-
return identifierChild.text;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
// Fallback: try to find any identifier child
|
|
314
|
-
const identifier = this.findIdentifier(node);
|
|
315
|
-
return identifier ? identifier.text : null;
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Recursively find the first identifier node
|
|
319
|
-
*/
|
|
320
|
-
findIdentifier(node) {
|
|
321
|
-
if (node.type === 'identifier') {
|
|
322
|
-
return node;
|
|
323
|
-
}
|
|
324
|
-
for (let i = 0; i < node.childCount; i++) {
|
|
325
|
-
const child = node.child(i);
|
|
326
|
-
if (child) {
|
|
327
|
-
const identifier = this.findIdentifier(child);
|
|
328
|
-
if (identifier) {
|
|
329
|
-
return identifier;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
return null;
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Get supported file extensions
|
|
337
|
-
*/
|
|
338
|
-
getSupportedExtensions() {
|
|
339
|
-
const extensions = [];
|
|
340
|
-
for (const config of this.languageConfigs.values()) {
|
|
341
|
-
extensions.push(...config.extensions);
|
|
342
|
-
}
|
|
343
|
-
return [...new Set(extensions)];
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* Check if a file is supported for AST parsing
|
|
347
|
-
*/
|
|
348
|
-
isSupported(filePath) {
|
|
349
|
-
return this.detectLanguage(filePath) !== null;
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Get node types for a specific language
|
|
353
|
-
*/
|
|
354
|
-
getNodeTypes(language) {
|
|
355
|
-
const config = this.languageConfigs.get(language);
|
|
356
|
-
return config ? config.nodeTypes : [];
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
// Export singleton instance
|
|
360
|
-
export const multiLanguageASTParser = new MultiLanguageASTParser();
|