@esankhan3/code-search-mcp 0.0.2 → 0.1.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.
- package/README.md +203 -263
- package/dist/resources/resources.js +3 -3
- package/dist/server.js +2 -2
- package/dist/tools/graph.js +1 -1
- package/dist/tools/index-tools.js +1 -1
- package/dist/tools/profile.js +2 -2
- package/dist/tools/search.js +1 -1
- package/package.json +16 -9
- package/dist/core/ast-graph-builder.js +0 -800
- package/dist/core/chunker.js +0 -368
- package/dist/core/claude-runner.js +0 -173
- package/dist/core/config.js +0 -59
- package/dist/core/cross-repo-detector.js +0 -887
- package/dist/core/embedder.js +0 -334
- package/dist/core/file-walker.js +0 -186
- package/dist/core/git-diff.js +0 -160
- package/dist/core/graph-metrics.js +0 -233
- package/dist/core/indexer.js +0 -552
- package/dist/core/project-graph-builder.js +0 -202
- package/dist/core/query-classifier.js +0 -144
- package/dist/core/query-router.js +0 -210
- package/dist/core/rag-evaluator.js +0 -213
- package/dist/core/repo-profiler.js +0 -383
- package/dist/core/reranker.js +0 -218
- package/dist/core/retriever.js +0 -242
- package/dist/core/semantic-edge-detector.js +0 -147
- package/dist/core/service-mesh-inferrer.js +0 -241
- package/dist/core/structural-hasher.js +0 -316
- package/dist/core/tree-sitter-parser.js +0 -539
- package/dist/core/types.js +0 -0
- package/dist/core/vector-store.js +0 -259
- package/dist/core/workspace-detector.js +0 -481
|
@@ -1,539 +0,0 @@
|
|
|
1
|
-
import { Parser as TSParser, Language as TSLanguage, Query as TSQuery } from "web-tree-sitter";
|
|
2
|
-
import { createHash } from "node:crypto";
|
|
3
|
-
import { createRequire } from "node:module";
|
|
4
|
-
const require2 = createRequire(import.meta.url);
|
|
5
|
-
const GRAMMAR_MAP = {
|
|
6
|
-
typescript: "tree-sitter-typescript.wasm",
|
|
7
|
-
javascript: "tree-sitter-javascript.wasm",
|
|
8
|
-
tsx: "tree-sitter-tsx.wasm",
|
|
9
|
-
go: "tree-sitter-go.wasm",
|
|
10
|
-
python: "tree-sitter-python.wasm",
|
|
11
|
-
rust: "tree-sitter-rust.wasm",
|
|
12
|
-
java: "tree-sitter-java.wasm",
|
|
13
|
-
php: "tree-sitter-php.wasm"
|
|
14
|
-
};
|
|
15
|
-
let parserReady = false;
|
|
16
|
-
const languageParsers = /* @__PURE__ */ new Map();
|
|
17
|
-
async function initTreeSitter() {
|
|
18
|
-
if (parserReady) return;
|
|
19
|
-
await TSParser.init();
|
|
20
|
-
parserReady = true;
|
|
21
|
-
}
|
|
22
|
-
async function getParserAndLang(language) {
|
|
23
|
-
if (languageParsers.has(language)) return languageParsers.get(language);
|
|
24
|
-
const wasmFile = GRAMMAR_MAP[language];
|
|
25
|
-
if (!wasmFile) return null;
|
|
26
|
-
try {
|
|
27
|
-
const wasmPath = require2.resolve(`tree-sitter-wasms/out/${wasmFile}`);
|
|
28
|
-
const lang = await TSLanguage.load(wasmPath);
|
|
29
|
-
const parser = new TSParser();
|
|
30
|
-
parser.setLanguage(lang);
|
|
31
|
-
const entry = { parser, lang };
|
|
32
|
-
languageParsers.set(language, entry);
|
|
33
|
-
return entry;
|
|
34
|
-
} catch {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
const TS_QUERIES = {
|
|
39
|
-
entities: `
|
|
40
|
-
(function_declaration name: (identifier) @name) @entity
|
|
41
|
-
(class_declaration name: (type_identifier) @name) @entity
|
|
42
|
-
(interface_declaration name: (type_identifier) @name) @entity
|
|
43
|
-
(type_alias_declaration name: (type_identifier) @name) @entity
|
|
44
|
-
(enum_declaration name: (identifier) @name) @entity
|
|
45
|
-
(method_definition name: (property_identifier) @name) @entity
|
|
46
|
-
(export_statement declaration: (function_declaration name: (identifier) @name) @entity) @export
|
|
47
|
-
(export_statement declaration: (class_declaration name: (type_identifier) @name) @entity) @export
|
|
48
|
-
(export_statement declaration: (interface_declaration name: (type_identifier) @name) @entity) @export
|
|
49
|
-
(export_statement declaration: (type_alias_declaration name: (type_identifier) @name) @entity) @export
|
|
50
|
-
(export_statement declaration: (enum_declaration name: (identifier) @name) @entity) @export
|
|
51
|
-
(export_statement declaration: (lexical_declaration (variable_declarator name: (identifier) @name value: (arrow_function) @entity))) @export
|
|
52
|
-
`,
|
|
53
|
-
imports: `
|
|
54
|
-
(import_statement source: (string) @source) @import
|
|
55
|
-
`,
|
|
56
|
-
calls: `
|
|
57
|
-
(call_expression function: (identifier) @callee) @call
|
|
58
|
-
(call_expression function: (member_expression property: (property_identifier) @callee)) @call
|
|
59
|
-
`
|
|
60
|
-
};
|
|
61
|
-
const GO_QUERIES = {
|
|
62
|
-
entities: `
|
|
63
|
-
(function_declaration name: (identifier) @name) @entity
|
|
64
|
-
(method_declaration name: (field_identifier) @name) @entity
|
|
65
|
-
(type_declaration (type_spec name: (type_identifier) @name type: (struct_type))) @entity
|
|
66
|
-
(type_declaration (type_spec name: (type_identifier) @name type: (interface_type))) @entity
|
|
67
|
-
`,
|
|
68
|
-
imports: `
|
|
69
|
-
(import_spec path: (interpreted_string_literal) @source) @import
|
|
70
|
-
`,
|
|
71
|
-
calls: `
|
|
72
|
-
(call_expression function: (identifier) @callee) @call
|
|
73
|
-
(call_expression function: (selector_expression field: (field_identifier) @callee)) @call
|
|
74
|
-
`
|
|
75
|
-
};
|
|
76
|
-
const PY_QUERIES = {
|
|
77
|
-
entities: `
|
|
78
|
-
(function_definition name: (identifier) @name) @entity
|
|
79
|
-
(class_definition name: (identifier) @name) @entity
|
|
80
|
-
`,
|
|
81
|
-
imports: `
|
|
82
|
-
(import_from_statement module_name: (dotted_name) @source) @import
|
|
83
|
-
(import_statement name: (dotted_name) @source) @import
|
|
84
|
-
`,
|
|
85
|
-
calls: `
|
|
86
|
-
(call function: (identifier) @callee) @call
|
|
87
|
-
(call function: (attribute attribute: (identifier) @callee)) @call
|
|
88
|
-
`
|
|
89
|
-
};
|
|
90
|
-
const RUST_QUERIES = {
|
|
91
|
-
entities: `
|
|
92
|
-
(function_item name: (identifier) @name) @entity
|
|
93
|
-
(struct_item name: (type_identifier) @name) @entity
|
|
94
|
-
(impl_item type: (type_identifier) @name) @entity
|
|
95
|
-
(trait_item name: (type_identifier) @name) @entity
|
|
96
|
-
(enum_item name: (type_identifier) @name) @entity
|
|
97
|
-
`,
|
|
98
|
-
imports: `
|
|
99
|
-
(use_declaration argument: (scoped_identifier) @source) @import
|
|
100
|
-
`,
|
|
101
|
-
calls: `
|
|
102
|
-
(call_expression function: (identifier) @callee) @call
|
|
103
|
-
(call_expression function: (field_expression field: (field_identifier) @callee)) @call
|
|
104
|
-
`
|
|
105
|
-
};
|
|
106
|
-
const JAVA_QUERIES = {
|
|
107
|
-
entities: `
|
|
108
|
-
(class_declaration name: (identifier) @name) @entity
|
|
109
|
-
(interface_declaration name: (identifier) @name) @entity
|
|
110
|
-
(method_declaration name: (identifier) @name) @entity
|
|
111
|
-
(enum_declaration name: (identifier) @name) @entity
|
|
112
|
-
`,
|
|
113
|
-
imports: `
|
|
114
|
-
(import_declaration (scoped_identifier) @source) @import
|
|
115
|
-
`,
|
|
116
|
-
calls: `
|
|
117
|
-
(method_invocation name: (identifier) @callee) @call
|
|
118
|
-
`
|
|
119
|
-
};
|
|
120
|
-
const PHP_QUERIES = {
|
|
121
|
-
entities: `
|
|
122
|
-
(function_definition name: (name) @name) @entity
|
|
123
|
-
(class_declaration name: (name) @name) @entity
|
|
124
|
-
(method_declaration name: (name) @name) @entity
|
|
125
|
-
(interface_declaration name: (name) @name) @entity
|
|
126
|
-
(trait_declaration name: (name) @name) @entity
|
|
127
|
-
`,
|
|
128
|
-
imports: `
|
|
129
|
-
(namespace_use_declaration (namespace_use_clause (qualified_name) @source)) @import
|
|
130
|
-
`,
|
|
131
|
-
calls: `
|
|
132
|
-
(function_call_expression function: (name) @callee) @call
|
|
133
|
-
(member_call_expression name: (name) @callee) @call
|
|
134
|
-
`
|
|
135
|
-
};
|
|
136
|
-
function queriesForLanguage(language) {
|
|
137
|
-
switch (language) {
|
|
138
|
-
case "typescript":
|
|
139
|
-
case "javascript":
|
|
140
|
-
case "tsx":
|
|
141
|
-
return TS_QUERIES;
|
|
142
|
-
case "go":
|
|
143
|
-
return GO_QUERIES;
|
|
144
|
-
case "python":
|
|
145
|
-
return PY_QUERIES;
|
|
146
|
-
case "rust":
|
|
147
|
-
return RUST_QUERIES;
|
|
148
|
-
case "java":
|
|
149
|
-
return JAVA_QUERIES;
|
|
150
|
-
case "php":
|
|
151
|
-
return PHP_QUERIES;
|
|
152
|
-
default:
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
const NODE_TYPE_TO_ENTITY = {
|
|
157
|
-
// TypeScript / JavaScript
|
|
158
|
-
function_declaration: "function",
|
|
159
|
-
arrow_function: "function",
|
|
160
|
-
class_declaration: "class",
|
|
161
|
-
method_definition: "method",
|
|
162
|
-
interface_declaration: "interface",
|
|
163
|
-
type_alias_declaration: "type",
|
|
164
|
-
enum_declaration: "enum",
|
|
165
|
-
// Python
|
|
166
|
-
function_definition: "function",
|
|
167
|
-
class_definition: "class",
|
|
168
|
-
// Go (type_spec handled separately via child type)
|
|
169
|
-
// Rust
|
|
170
|
-
function_item: "function",
|
|
171
|
-
struct_item: "struct",
|
|
172
|
-
impl_item: "module",
|
|
173
|
-
// impl blocks act as module-level grouping
|
|
174
|
-
trait_item: "trait",
|
|
175
|
-
enum_item: "enum",
|
|
176
|
-
// Java
|
|
177
|
-
method_declaration: "method",
|
|
178
|
-
// PHP (uses same names as TS for class/interface + 'trait_declaration')
|
|
179
|
-
function_definition_php: "function",
|
|
180
|
-
trait_declaration: "trait"
|
|
181
|
-
};
|
|
182
|
-
function detectEntityType(node, _language) {
|
|
183
|
-
const t = node.type;
|
|
184
|
-
const mapped = NODE_TYPE_TO_ENTITY[t];
|
|
185
|
-
if (mapped) return mapped;
|
|
186
|
-
if (t === "type_declaration" || t === "type_spec") {
|
|
187
|
-
const spec = t === "type_declaration" ? node.namedChildren.find((c) => c.type === "type_spec") : node;
|
|
188
|
-
if (spec) {
|
|
189
|
-
const typeChild = spec.namedChildren.find(
|
|
190
|
-
(c) => c.type === "struct_type" || c.type === "interface_type"
|
|
191
|
-
);
|
|
192
|
-
if (typeChild?.type === "struct_type") return "struct";
|
|
193
|
-
if (typeChild?.type === "interface_type") return "interface";
|
|
194
|
-
}
|
|
195
|
-
return "type";
|
|
196
|
-
}
|
|
197
|
-
if (t.includes("class")) return "class";
|
|
198
|
-
if (t.includes("interface")) return "interface";
|
|
199
|
-
if (t.includes("method")) return "method";
|
|
200
|
-
if (t.includes("function") || t.includes("func")) return "function";
|
|
201
|
-
if (t.includes("struct")) return "struct";
|
|
202
|
-
if (t.includes("enum")) return "enum";
|
|
203
|
-
if (t.includes("trait")) return "trait";
|
|
204
|
-
return "function";
|
|
205
|
-
}
|
|
206
|
-
function isExported(entityNode, language, content) {
|
|
207
|
-
if (language === "typescript" || language === "javascript" || language === "tsx") {
|
|
208
|
-
let cursor = entityNode.parent;
|
|
209
|
-
while (cursor) {
|
|
210
|
-
if (cursor.type === "export_statement") return true;
|
|
211
|
-
cursor = cursor.parent;
|
|
212
|
-
}
|
|
213
|
-
return false;
|
|
214
|
-
}
|
|
215
|
-
if (language === "rust") {
|
|
216
|
-
const text = content.slice(entityNode.startIndex, entityNode.startIndex + 10);
|
|
217
|
-
return text.trimStart().startsWith("pub");
|
|
218
|
-
}
|
|
219
|
-
if (language === "go") {
|
|
220
|
-
const nameChild = entityNode.namedChildren.find(
|
|
221
|
-
(c) => c.type === "identifier" || c.type === "type_identifier" || c.type === "field_identifier"
|
|
222
|
-
);
|
|
223
|
-
if (nameChild) {
|
|
224
|
-
const name = nameChild.text;
|
|
225
|
-
return name.length > 0 && name[0] === name[0].toUpperCase() && name[0] !== name[0].toLowerCase();
|
|
226
|
-
}
|
|
227
|
-
return false;
|
|
228
|
-
}
|
|
229
|
-
if (language === "java") {
|
|
230
|
-
const modifiers = entityNode.namedChildren.find((c) => c.type === "modifiers");
|
|
231
|
-
if (modifiers) return modifiers.text.includes("public");
|
|
232
|
-
return false;
|
|
233
|
-
}
|
|
234
|
-
return true;
|
|
235
|
-
}
|
|
236
|
-
function findContainingEntity(node) {
|
|
237
|
-
let cursor = node.parent;
|
|
238
|
-
while (cursor) {
|
|
239
|
-
const t = cursor.type;
|
|
240
|
-
if (t === "class_declaration" || t === "class_definition" || t === "class_body" || t === "impl_item" || t === "struct_item" || t === "trait_item" || t === "interface_declaration" || t === "trait_declaration") {
|
|
241
|
-
const target = t === "class_body" && cursor.parent ? cursor.parent : cursor;
|
|
242
|
-
const nameChild = target.namedChildren.find(
|
|
243
|
-
(c) => c.type === "identifier" || c.type === "type_identifier" || c.type === "name"
|
|
244
|
-
);
|
|
245
|
-
if (nameChild) return nameChild.text;
|
|
246
|
-
}
|
|
247
|
-
cursor = cursor.parent;
|
|
248
|
-
}
|
|
249
|
-
return void 0;
|
|
250
|
-
}
|
|
251
|
-
function extractSignature(entityNode, entityType, _content) {
|
|
252
|
-
if (entityType !== "function" && entityType !== "method") return void 0;
|
|
253
|
-
const params = entityNode.namedChildren.find(
|
|
254
|
-
(c) => c.type === "formal_parameters" || c.type === "parameters" || c.type === "parameter_list" || c.type === "typed_parameters"
|
|
255
|
-
);
|
|
256
|
-
const returnType = entityNode.namedChildren.find(
|
|
257
|
-
(c) => c.type === "type_annotation" || c.type === "return_type"
|
|
258
|
-
);
|
|
259
|
-
if (!params) return void 0;
|
|
260
|
-
let sig = params.text;
|
|
261
|
-
if (returnType) sig += `: ${returnType.text}`;
|
|
262
|
-
return sig;
|
|
263
|
-
}
|
|
264
|
-
function runQuery(language, querySource, rootNode) {
|
|
265
|
-
try {
|
|
266
|
-
const query = new TSQuery(language, querySource);
|
|
267
|
-
return query.matches(rootNode);
|
|
268
|
-
} catch {
|
|
269
|
-
return [];
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
function runQueryWithFallback(language, querySource, rootNode) {
|
|
273
|
-
const fullResult = runQuery(language, querySource, rootNode);
|
|
274
|
-
if (fullResult.length > 0) return fullResult;
|
|
275
|
-
const patterns = querySource.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("("));
|
|
276
|
-
const results = [];
|
|
277
|
-
for (const pattern of patterns) {
|
|
278
|
-
try {
|
|
279
|
-
const q = new TSQuery(language, pattern);
|
|
280
|
-
results.push(...q.matches(rootNode));
|
|
281
|
-
} catch {
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
return results;
|
|
285
|
-
}
|
|
286
|
-
function parseImportMatches(matches, language, _content, _rootNode) {
|
|
287
|
-
const imports = [];
|
|
288
|
-
for (const match of matches) {
|
|
289
|
-
const sourceCapture = match.captures.find((c) => c.name === "source");
|
|
290
|
-
const importCapture = match.captures.find((c) => c.name === "import");
|
|
291
|
-
if (!sourceCapture) continue;
|
|
292
|
-
let source = sourceCapture.node.text.replace(/^['"`]|['"`]$/g, "");
|
|
293
|
-
const startLine = (importCapture ?? sourceCapture).node.startPosition.row;
|
|
294
|
-
const isRelative = source.startsWith("./") || source.startsWith("../");
|
|
295
|
-
const names = [];
|
|
296
|
-
if (language === "typescript" || language === "javascript" || language === "tsx") {
|
|
297
|
-
const importNode = importCapture?.node ?? sourceCapture.node.parent;
|
|
298
|
-
if (importNode) {
|
|
299
|
-
const walk = (n) => {
|
|
300
|
-
if (n.type === "import_specifier") {
|
|
301
|
-
const nameNode = n.namedChildren.find((c) => c.type === "identifier");
|
|
302
|
-
if (nameNode) names.push(nameNode.text);
|
|
303
|
-
}
|
|
304
|
-
if (n.type === "identifier" && n.parent?.type === "import_clause") {
|
|
305
|
-
names.push(n.text);
|
|
306
|
-
}
|
|
307
|
-
for (const child of n.namedChildren) walk(child);
|
|
308
|
-
};
|
|
309
|
-
walk(importNode);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
if (language === "python") {
|
|
313
|
-
const importNode = importCapture?.node ?? sourceCapture.node.parent;
|
|
314
|
-
if (importNode && importNode.type === "import_from_statement") {
|
|
315
|
-
for (const child of importNode.namedChildren) {
|
|
316
|
-
if (child.type === "dotted_name" && child !== sourceCapture.node) {
|
|
317
|
-
names.push(child.text);
|
|
318
|
-
}
|
|
319
|
-
if (child.type === "aliased_import") {
|
|
320
|
-
const nameNode = child.namedChildren.find((c) => c.type === "dotted_name");
|
|
321
|
-
if (nameNode) names.push(nameNode.text);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
imports.push({ source, names, startLine, isRelative });
|
|
327
|
-
}
|
|
328
|
-
return imports;
|
|
329
|
-
}
|
|
330
|
-
function parseCallMatches(matches, entities) {
|
|
331
|
-
const callSites = [];
|
|
332
|
-
for (const match of matches) {
|
|
333
|
-
const calleeCapture = match.captures.find((c) => c.name === "callee");
|
|
334
|
-
if (!calleeCapture) continue;
|
|
335
|
-
const callee = calleeCapture.node.text;
|
|
336
|
-
const startLine = calleeCapture.node.startPosition.row;
|
|
337
|
-
const containingEntity = entities.find(
|
|
338
|
-
(e) => startLine >= e.startLine && startLine <= e.endLine
|
|
339
|
-
)?.name;
|
|
340
|
-
callSites.push({ callee, startLine, containingEntity });
|
|
341
|
-
}
|
|
342
|
-
return callSites;
|
|
343
|
-
}
|
|
344
|
-
function extractTypeReferences(entities) {
|
|
345
|
-
const typeRefs = /* @__PURE__ */ new Set();
|
|
346
|
-
const typeRefPattern = /(?<!['"@/\\])\b([A-Z][A-Za-z0-9]*(?:<[^>]+>)?)\b/g;
|
|
347
|
-
for (const entity of entities) {
|
|
348
|
-
if (entity.signature) {
|
|
349
|
-
let m;
|
|
350
|
-
while ((m = typeRefPattern.exec(entity.signature)) !== null) {
|
|
351
|
-
const ref = m[1].replace(/<.*>$/, "");
|
|
352
|
-
if (!BUILTIN_TYPES.has(ref)) typeRefs.add(ref);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
return [...typeRefs];
|
|
357
|
-
}
|
|
358
|
-
const BUILTIN_TYPES = /* @__PURE__ */ new Set([
|
|
359
|
-
"String",
|
|
360
|
-
"Number",
|
|
361
|
-
"Boolean",
|
|
362
|
-
"Object",
|
|
363
|
-
"Array",
|
|
364
|
-
"Function",
|
|
365
|
-
"Symbol",
|
|
366
|
-
"Promise",
|
|
367
|
-
"Map",
|
|
368
|
-
"Set",
|
|
369
|
-
"WeakMap",
|
|
370
|
-
"WeakSet",
|
|
371
|
-
"Date",
|
|
372
|
-
"RegExp",
|
|
373
|
-
"Error",
|
|
374
|
-
"Record",
|
|
375
|
-
"Partial",
|
|
376
|
-
"Required",
|
|
377
|
-
"Readonly",
|
|
378
|
-
"Pick",
|
|
379
|
-
"Omit",
|
|
380
|
-
"Exclude",
|
|
381
|
-
"Extract",
|
|
382
|
-
"NonNullable",
|
|
383
|
-
"ReturnType",
|
|
384
|
-
"Parameters",
|
|
385
|
-
"InstanceType",
|
|
386
|
-
"Awaited",
|
|
387
|
-
"Uint8Array",
|
|
388
|
-
"Int32Array",
|
|
389
|
-
"Float64Array",
|
|
390
|
-
"ArrayBuffer",
|
|
391
|
-
"Iterator",
|
|
392
|
-
"AsyncIterator",
|
|
393
|
-
"Generator",
|
|
394
|
-
"AsyncGenerator"
|
|
395
|
-
]);
|
|
396
|
-
async function parseFile(filePath, content, language) {
|
|
397
|
-
await initTreeSitter();
|
|
398
|
-
const parserEntry = await getParserAndLang(language);
|
|
399
|
-
if (!parserEntry) return null;
|
|
400
|
-
const queries = queriesForLanguage(language);
|
|
401
|
-
if (!queries) return null;
|
|
402
|
-
let tree;
|
|
403
|
-
try {
|
|
404
|
-
tree = parserEntry.parser.parse(content);
|
|
405
|
-
} catch {
|
|
406
|
-
return null;
|
|
407
|
-
}
|
|
408
|
-
if (!tree) return null;
|
|
409
|
-
const rootNode = tree.rootNode;
|
|
410
|
-
const lang = parserEntry.lang;
|
|
411
|
-
const entityMatches = runQueryWithFallback(lang, queries.entities, rootNode);
|
|
412
|
-
const entities = [];
|
|
413
|
-
const seenEntityKeys = /* @__PURE__ */ new Set();
|
|
414
|
-
for (const match of entityMatches) {
|
|
415
|
-
const nameCapture = match.captures.find((c) => c.name === "name");
|
|
416
|
-
const entityCapture = match.captures.find((c) => c.name === "entity");
|
|
417
|
-
if (!nameCapture || !entityCapture) continue;
|
|
418
|
-
const entityNode = entityCapture.node;
|
|
419
|
-
const name = nameCapture.node.text;
|
|
420
|
-
const type = detectEntityType(entityNode, language);
|
|
421
|
-
const startLine = entityNode.startPosition.row;
|
|
422
|
-
const endLine = entityNode.endPosition.row;
|
|
423
|
-
const key = `${name}:${startLine}`;
|
|
424
|
-
if (seenEntityKeys.has(key)) {
|
|
425
|
-
const existing = entities.find((e) => e.name === name && e.startLine === startLine);
|
|
426
|
-
const hasExportCapture2 = match.captures.some((c) => c.name === "export");
|
|
427
|
-
if (existing && hasExportCapture2) {
|
|
428
|
-
existing.isExported = true;
|
|
429
|
-
}
|
|
430
|
-
continue;
|
|
431
|
-
}
|
|
432
|
-
seenEntityKeys.add(key);
|
|
433
|
-
const hasExportCapture = match.captures.some((c) => c.name === "export");
|
|
434
|
-
const exported = hasExportCapture || isExported(entityNode, language, content);
|
|
435
|
-
const parentName = type === "method" ? findContainingEntity(entityNode) : void 0;
|
|
436
|
-
const signature = extractSignature(entityNode, type, content);
|
|
437
|
-
const body = content.slice(entityNode.startIndex, entityNode.endIndex);
|
|
438
|
-
entities.push({
|
|
439
|
-
name,
|
|
440
|
-
type,
|
|
441
|
-
startLine,
|
|
442
|
-
endLine,
|
|
443
|
-
startByte: entityNode.startIndex,
|
|
444
|
-
endByte: entityNode.endIndex,
|
|
445
|
-
parent: parentName,
|
|
446
|
-
signature,
|
|
447
|
-
isExported: exported,
|
|
448
|
-
body
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
const importMatches = runQueryWithFallback(lang, queries.imports, rootNode);
|
|
452
|
-
const imports = parseImportMatches(importMatches, language, content, rootNode);
|
|
453
|
-
const callMatches = runQueryWithFallback(lang, queries.calls, rootNode);
|
|
454
|
-
const callSites = parseCallMatches(callMatches, entities);
|
|
455
|
-
const typeReferences = extractTypeReferences(entities);
|
|
456
|
-
tree.delete();
|
|
457
|
-
return {
|
|
458
|
-
filePath,
|
|
459
|
-
language,
|
|
460
|
-
entities,
|
|
461
|
-
imports,
|
|
462
|
-
callSites,
|
|
463
|
-
typeReferences
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
async function parseFiles(files) {
|
|
467
|
-
await initTreeSitter();
|
|
468
|
-
const results = [];
|
|
469
|
-
for (const file of files) {
|
|
470
|
-
const result = await parseFile(file.path, file.content, file.language);
|
|
471
|
-
if (result) results.push(result);
|
|
472
|
-
}
|
|
473
|
-
return results;
|
|
474
|
-
}
|
|
475
|
-
async function computeStructuralHash(_content, entity, language) {
|
|
476
|
-
await initTreeSitter();
|
|
477
|
-
const parserEntry = await getParserAndLang(language);
|
|
478
|
-
if (!parserEntry) return null;
|
|
479
|
-
let tree;
|
|
480
|
-
try {
|
|
481
|
-
tree = parserEntry.parser.parse(entity.body);
|
|
482
|
-
} catch {
|
|
483
|
-
return null;
|
|
484
|
-
}
|
|
485
|
-
if (!tree) return null;
|
|
486
|
-
const identifierMap = /* @__PURE__ */ new Map();
|
|
487
|
-
let identifierCounter = 0;
|
|
488
|
-
const tokens = [];
|
|
489
|
-
const SKIP_TYPES = /* @__PURE__ */ new Set([
|
|
490
|
-
"comment",
|
|
491
|
-
"line_comment",
|
|
492
|
-
"block_comment",
|
|
493
|
-
"doc_comment"
|
|
494
|
-
// Whitespace nodes are typically not named, but include for safety
|
|
495
|
-
]);
|
|
496
|
-
const IDENTIFIER_TYPES = /* @__PURE__ */ new Set([
|
|
497
|
-
"identifier",
|
|
498
|
-
"type_identifier",
|
|
499
|
-
"property_identifier",
|
|
500
|
-
"field_identifier",
|
|
501
|
-
"shorthand_field_identifier",
|
|
502
|
-
"name",
|
|
503
|
-
"dotted_name"
|
|
504
|
-
]);
|
|
505
|
-
function walk(node) {
|
|
506
|
-
if (SKIP_TYPES.has(node.type)) return;
|
|
507
|
-
if (node.namedChildCount === 0) {
|
|
508
|
-
if (IDENTIFIER_TYPES.has(node.type)) {
|
|
509
|
-
const text = node.text;
|
|
510
|
-
if (!identifierMap.has(text)) {
|
|
511
|
-
identifierMap.set(text, `v${identifierCounter++}`);
|
|
512
|
-
}
|
|
513
|
-
tokens.push(`${node.type}:${identifierMap.get(text)}`);
|
|
514
|
-
} else {
|
|
515
|
-
tokens.push(`${node.type}:${node.text}`);
|
|
516
|
-
}
|
|
517
|
-
} else {
|
|
518
|
-
tokens.push(`(${node.type}`);
|
|
519
|
-
for (const child of node.namedChildren) {
|
|
520
|
-
walk(child);
|
|
521
|
-
}
|
|
522
|
-
tokens.push(")");
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
walk(tree.rootNode);
|
|
526
|
-
tree.delete();
|
|
527
|
-
const canonical = tokens.join(" ");
|
|
528
|
-
return createHash("sha256").update(canonical).digest("hex");
|
|
529
|
-
}
|
|
530
|
-
function supportedLanguages() {
|
|
531
|
-
return Object.keys(GRAMMAR_MAP);
|
|
532
|
-
}
|
|
533
|
-
export {
|
|
534
|
-
computeStructuralHash,
|
|
535
|
-
initTreeSitter,
|
|
536
|
-
parseFile,
|
|
537
|
-
parseFiles,
|
|
538
|
-
supportedLanguages
|
|
539
|
-
};
|
package/dist/core/types.js
DELETED
|
File without changes
|