@codemap-ai/code-index 1.0.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.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/dist/file-discovery.d.ts +36 -0
  3. package/dist/file-discovery.d.ts.map +1 -0
  4. package/dist/file-discovery.js +204 -0
  5. package/dist/index.d.ts +6 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +26 -0
  8. package/dist/language-utils.d.ts +10 -0
  9. package/dist/language-utils.d.ts.map +1 -0
  10. package/dist/language-utils.js +75 -0
  11. package/dist/parsers/dart.d.ts +4 -0
  12. package/dist/parsers/dart.d.ts.map +1 -0
  13. package/dist/parsers/dart.js +353 -0
  14. package/dist/parsers/index.d.ts +11 -0
  15. package/dist/parsers/index.d.ts.map +1 -0
  16. package/dist/parsers/index.js +32 -0
  17. package/dist/parsers/java.d.ts +4 -0
  18. package/dist/parsers/java.d.ts.map +1 -0
  19. package/dist/parsers/java.js +222 -0
  20. package/dist/parsers/kotlin.d.ts +4 -0
  21. package/dist/parsers/kotlin.d.ts.map +1 -0
  22. package/dist/parsers/kotlin.js +221 -0
  23. package/dist/parsers/php.d.ts +4 -0
  24. package/dist/parsers/php.d.ts.map +1 -0
  25. package/dist/parsers/php.js +215 -0
  26. package/dist/parsers/python.d.ts +4 -0
  27. package/dist/parsers/python.d.ts.map +1 -0
  28. package/dist/parsers/python.js +200 -0
  29. package/dist/parsers/shared.d.ts +30 -0
  30. package/dist/parsers/shared.d.ts.map +1 -0
  31. package/dist/parsers/shared.js +200 -0
  32. package/dist/parsers/types.d.ts +93 -0
  33. package/dist/parsers/types.d.ts.map +1 -0
  34. package/dist/parsers/types.js +12 -0
  35. package/dist/parsers/typescript.d.ts +5 -0
  36. package/dist/parsers/typescript.d.ts.map +1 -0
  37. package/dist/parsers/typescript.js +549 -0
  38. package/dist/ts-resolver.d.ts +17 -0
  39. package/dist/ts-resolver.d.ts.map +1 -0
  40. package/dist/ts-resolver.js +110 -0
  41. package/package.json +30 -0
@@ -0,0 +1,353 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseDartFile = parseDartFile;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const web_tree_sitter_1 = require("web-tree-sitter");
9
+ const shared_js_1 = require("./shared.js");
10
+ const types_js_1 = require("./types.js");
11
+ let parserReady = null;
12
+ function getDartParser() {
13
+ if (!parserReady) {
14
+ parserReady = (async () => {
15
+ await web_tree_sitter_1.Parser.init();
16
+ const wasmPath = node_path_1.default.resolve(node_path_1.default.dirname(require.resolve("tree-sitter-wasms/package.json")), "out", "tree-sitter-dart.wasm");
17
+ const language = await web_tree_sitter_1.Language.load(wasmPath);
18
+ const parser = new web_tree_sitter_1.Parser();
19
+ parser.setLanguage(language);
20
+ return { parser, language };
21
+ })();
22
+ }
23
+ return parserReady;
24
+ }
25
+ async function parseDartFile(file, filePathSet, projectImportId) {
26
+ const content = file.content ?? "";
27
+ if (!content.trim())
28
+ return { ...types_js_1.EMPTY_SEMANTICS };
29
+ let parser;
30
+ try {
31
+ ({ parser } = await getDartParser());
32
+ }
33
+ catch {
34
+ return parseDartFileWithRegexFallback(file, filePathSet, projectImportId);
35
+ }
36
+ const tree = parser.parse(content);
37
+ if (!tree)
38
+ return parseDartFileWithRegexFallback(file, filePathSet, projectImportId);
39
+ const semantics = {
40
+ symbols: [],
41
+ imports: [],
42
+ exports: [],
43
+ relationships: [],
44
+ calls: [],
45
+ issues: [],
46
+ externalSymbols: [],
47
+ };
48
+ const lines = content.split(/\r?\n/);
49
+ const seenImportKeys = new Set();
50
+ const seenSymbolKeys = new Set();
51
+ walkDartAst(tree.rootNode, (node) => {
52
+ const directive = parseDartDirective(node.text);
53
+ if (directive) {
54
+ addDartImport({
55
+ directive,
56
+ file,
57
+ filePathSet,
58
+ projectImportId,
59
+ semantics,
60
+ seenImportKeys,
61
+ line: node.startPosition.row + 1,
62
+ col: node.startPosition.column,
63
+ endLine: node.endPosition.row + 1,
64
+ endCol: node.endPosition.column,
65
+ });
66
+ return;
67
+ }
68
+ const symbol = parseDartSymbol(node.text, node.type, isDartMemberNode(node));
69
+ if (!symbol)
70
+ return;
71
+ const line = node.startPosition.row + 1;
72
+ const localKey = (0, shared_js_1.buildLocalSymbolKey)(file.path, symbol.kind, symbol.displayName);
73
+ const stableKey = (0, shared_js_1.buildStableSymbolKey)(file.path, symbol.kind, symbol.displayName, line);
74
+ if (seenSymbolKeys.has(stableKey))
75
+ return;
76
+ seenSymbolKeys.add(stableKey);
77
+ semantics.symbols.push({
78
+ localKey,
79
+ stableKey,
80
+ displayName: symbol.displayName,
81
+ kind: symbol.kind,
82
+ language: file.language,
83
+ signature: lines[node.startPosition.row]?.trim() ?? null,
84
+ returnType: null,
85
+ doc: null,
86
+ isExported: true,
87
+ isDefaultExport: false,
88
+ line,
89
+ col: Math.max(node.startPosition.column, 0),
90
+ endLine: node.endPosition.row + 1,
91
+ endCol: node.endPosition.column,
92
+ parentSymbolLocalKey: findParentDartSymbolLocalKey(node, file.path),
93
+ });
94
+ });
95
+ return semantics;
96
+ }
97
+ function walkDartAst(node, visitor) {
98
+ visitor(node);
99
+ for (let i = 0; i < node.childCount; i++) {
100
+ const child = node.child(i);
101
+ if (child)
102
+ walkDartAst(child, visitor);
103
+ }
104
+ }
105
+ function parseDartDirective(text) {
106
+ const match = text.match(/^\s*(import|export|part)\s+['"]([^'"]+)['"]/);
107
+ if (!match?.[1] || !match[2])
108
+ return null;
109
+ return {
110
+ kind: match[1],
111
+ moduleSpecifier: match[2],
112
+ };
113
+ }
114
+ function addDartImport(input) {
115
+ const importKind = input.directive.kind === "part"
116
+ ? "include"
117
+ : input.directive.kind === "export"
118
+ ? "export_from"
119
+ : "import";
120
+ const localKey = (0, shared_js_1.buildImportLocalKey)(input.file.path, importKind, input.directive.moduleSpecifier, input.line, input.col);
121
+ if (input.seenImportKeys.has(localKey))
122
+ return;
123
+ input.seenImportKeys.add(localKey);
124
+ const resolution = resolveDartImport(input.file.path, input.directive.moduleSpecifier, input.file.language, input.filePathSet);
125
+ const importDraft = {
126
+ localKey,
127
+ moduleSpecifier: input.directive.moduleSpecifier,
128
+ importKind,
129
+ isTypeOnly: false,
130
+ importedNames: [],
131
+ line: input.line,
132
+ col: input.col,
133
+ endLine: input.endLine,
134
+ endCol: input.endCol,
135
+ resolutionKind: resolution.resolutionKind,
136
+ targetPathText: resolution.targetPathText,
137
+ targetExternalSymbolKey: resolution.targetExternalSymbolKey,
138
+ };
139
+ input.semantics.imports.push(importDraft);
140
+ if (resolution.targetExternalSymbolKey) {
141
+ input.semantics.externalSymbols.push((0, shared_js_1.createExternalSymbolDraft)(input.projectImportId, input.file.language, input.directive.moduleSpecifier));
142
+ }
143
+ if (resolution.resolutionKind === "unresolved") {
144
+ input.semantics.issues.push({
145
+ projectImportId: input.projectImportId,
146
+ severity: "warning",
147
+ code: "UNRESOLVED_IMPORT",
148
+ message: `Unable to resolve ${input.directive.kind} "${input.directive.moduleSpecifier}" from ${input.file.path}`,
149
+ detailJson: {
150
+ filePath: input.file.path,
151
+ moduleSpecifier: input.directive.moduleSpecifier,
152
+ kind: input.directive.kind,
153
+ },
154
+ });
155
+ }
156
+ if (input.directive.kind === "export") {
157
+ input.semantics.exports.push({
158
+ exportName: input.directive.moduleSpecifier,
159
+ exportKind: "re_export",
160
+ line: input.line,
161
+ col: input.col,
162
+ endLine: input.endLine,
163
+ endCol: input.endCol,
164
+ sourceImportLocalKey: localKey,
165
+ targetExternalSymbolKey: resolution.targetExternalSymbolKey,
166
+ });
167
+ }
168
+ }
169
+ function resolveDartImport(filePath, moduleSpecifier, language, filePathSet) {
170
+ if (moduleSpecifier.startsWith("dart:")) {
171
+ return {
172
+ resolutionKind: "builtin",
173
+ targetPathText: null,
174
+ targetExternalSymbolKey: `dart:${moduleSpecifier}`,
175
+ };
176
+ }
177
+ if (moduleSpecifier.startsWith("package:")) {
178
+ const packagePath = moduleSpecifier.replace(/^package:[^/]+\//, "");
179
+ const internalTarget = packagePath ? `lib/${packagePath}` : null;
180
+ if (internalTarget && filePathSet.has(internalTarget)) {
181
+ return {
182
+ resolutionKind: "relative_path",
183
+ targetPathText: internalTarget,
184
+ targetExternalSymbolKey: null,
185
+ };
186
+ }
187
+ return {
188
+ resolutionKind: "package",
189
+ targetPathText: null,
190
+ targetExternalSymbolKey: `dart:${moduleSpecifier}`,
191
+ };
192
+ }
193
+ const resolution = (0, shared_js_1.resolveRelativeTargetPath)(filePath, moduleSpecifier, language, filePathSet);
194
+ return {
195
+ resolutionKind: resolution.resolvedPath ? "relative_path" : "unresolved",
196
+ targetPathText: resolution.resolvedPath ?? resolution.attemptedPath,
197
+ targetExternalSymbolKey: null,
198
+ };
199
+ }
200
+ function parseDartSymbol(text, nodeType, isMemberNode) {
201
+ const trimmed = text.trim();
202
+ const declarationMatch = trimmed.match(/^(?:(?:abstract|base|final|interface|sealed)\s+)*(class|mixin|enum)\s+([A-Za-z_]\w*)/);
203
+ if (declarationMatch?.[1] && declarationMatch[2]) {
204
+ return {
205
+ kind: declarationMatch[1] === "mixin" ? "mixin" : declarationMatch[1],
206
+ displayName: declarationMatch[2],
207
+ };
208
+ }
209
+ const extensionMatch = trimmed.match(/^extension(?:\s+type)?\s+([A-Za-z_]\w*)\b/);
210
+ if (extensionMatch?.[1] && extensionMatch[1] !== "on") {
211
+ return { kind: "mixin", displayName: extensionMatch[1] };
212
+ }
213
+ const typeAliasMatch = trimmed.match(/^typedef\s+([A-Za-z_]\w*)\b/);
214
+ if (typeAliasMatch?.[1]) {
215
+ return { kind: "type_alias", displayName: typeAliasMatch[1] };
216
+ }
217
+ if (!/\b(function|method|constructor|declaration|signature)\b/i.test(nodeType)) {
218
+ return null;
219
+ }
220
+ const callableMatch = trimmed.match(/^(?:(?:static|external|abstract|factory|const|late|final)\s+)*(?:[A-Za-z_]\w*(?:<[^>{}]+>)?(?:[?*])?\s+)?([A-Za-z_]\w*)\s*(?:<[^>{}]+>)?\(/);
221
+ if (!callableMatch?.[1] || ["if", "for", "while", "switch", "catch", "assert"].includes(callableMatch[1])) {
222
+ return null;
223
+ }
224
+ return {
225
+ kind: isMemberNode ? "method" : "function",
226
+ displayName: callableMatch[1],
227
+ };
228
+ }
229
+ function isDartMemberNode(node) {
230
+ let current = node.parent;
231
+ while (current) {
232
+ const trimmed = current.text.trimStart();
233
+ if (/^(?:(?:abstract|base|final|interface|sealed)\s+)*class\s+/.test(trimmed))
234
+ return true;
235
+ if (/^(?:base\s+)?mixin\s+/.test(trimmed))
236
+ return true;
237
+ if (/^extension(?:\s+type)?\s+/.test(trimmed))
238
+ return true;
239
+ current = current.parent;
240
+ }
241
+ return false;
242
+ }
243
+ function findParentDartSymbolLocalKey(node, filePath) {
244
+ let current = node.parent;
245
+ while (current) {
246
+ const parentSymbol = parseDartSymbol(current.text, current.type, false);
247
+ if (parentSymbol && ["class", "mixin", "enum"].includes(parentSymbol.kind)) {
248
+ return (0, shared_js_1.buildLocalSymbolKey)(filePath, parentSymbol.kind, parentSymbol.displayName);
249
+ }
250
+ current = current.parent;
251
+ }
252
+ return undefined;
253
+ }
254
+ function parseDartFileWithRegexFallback(file, filePathSet, projectImportId) {
255
+ const semantics = {
256
+ symbols: [],
257
+ imports: [],
258
+ exports: [],
259
+ relationships: [],
260
+ calls: [],
261
+ issues: [],
262
+ externalSymbols: [],
263
+ };
264
+ const originalLines = (file.content ?? "").split(/\r?\n/);
265
+ const lines = (0, shared_js_1.maskCommentsAndTemplateLiterals)(file.content ?? "").split(/\r?\n/);
266
+ const seenImportKeys = new Set();
267
+ const containerStack = [];
268
+ let braceDepth = 0;
269
+ lines.forEach((line, index) => {
270
+ const originalLine = originalLines[index] ?? line;
271
+ const lineNumber = index + 1;
272
+ while (containerStack.length > 0 && braceDepth < containerStack[containerStack.length - 1].depth) {
273
+ containerStack.pop();
274
+ }
275
+ const parentContainer = containerStack[containerStack.length - 1];
276
+ let matchedContainerSymbol = null;
277
+ for (const match of line.matchAll(/^\s*(import|export|part)\s+['"]([^'"]+)['"]/g)) {
278
+ const kind = match[1];
279
+ const moduleSpecifier = match[2];
280
+ if (!kind || !moduleSpecifier)
281
+ continue;
282
+ addDartImport({
283
+ directive: { kind, moduleSpecifier },
284
+ file,
285
+ filePathSet,
286
+ projectImportId,
287
+ semantics,
288
+ seenImportKeys,
289
+ line: lineNumber,
290
+ col: match.index ?? 0,
291
+ endLine: lineNumber,
292
+ endCol: (match.index ?? 0) + match[0].length,
293
+ });
294
+ }
295
+ const symbolPatterns = [
296
+ { regex: /^\s*(?:(?:abstract|base|final|interface|sealed)\s+)*class\s+([A-Za-z_]\w*)/, kind: "class" },
297
+ { regex: /^\s*(?:base\s+)?mixin\s+([A-Za-z_]\w*)/, kind: "mixin" },
298
+ { regex: /^\s*extension(?:\s+type)?\s+([A-Za-z_]\w*)/, kind: "mixin" },
299
+ { regex: /^\s*enum\s+([A-Za-z_]\w*)/, kind: "enum" },
300
+ { regex: /^\s*typedef\s+([A-Za-z_]\w*)/, kind: "type_alias" },
301
+ ];
302
+ for (const pattern of symbolPatterns) {
303
+ const match = line.match(pattern.regex);
304
+ if (!match?.[1] || match[1] === "on")
305
+ continue;
306
+ const displayName = match[1];
307
+ const col = line.indexOf(displayName);
308
+ const symbol = buildDartRegexSymbol(file, pattern.kind, displayName, originalLine, lineNumber, col);
309
+ semantics.symbols.push(symbol);
310
+ if (pattern.kind === "class" || pattern.kind === "mixin" || pattern.kind === "enum") {
311
+ matchedContainerSymbol = { kind: pattern.kind, displayName };
312
+ }
313
+ break;
314
+ }
315
+ const functionMatch = line.match(/^\s*(?:(?:static|external|factory|const)\s+)*(?:[A-Za-z_]\w*(?:<[^>{}]+>)?(?:[?*])?\s+)?([A-Za-z_]\w*)\s*(?:<[^>{}]+>)?\([^;{}]*\)\s*(?:async\s*)?(?:=>|{|$)/);
316
+ if (functionMatch?.[1] && !["if", "for", "while", "switch", "catch", "assert"].includes(functionMatch[1])) {
317
+ const displayName = functionMatch[1];
318
+ const kind = parentContainer ? "method" : "function";
319
+ const col = line.indexOf(displayName);
320
+ const symbol = buildDartRegexSymbol(file, kind, displayName, originalLine, lineNumber, col);
321
+ if (parentContainer) {
322
+ symbol.parentSymbolLocalKey = (0, shared_js_1.buildLocalSymbolKey)(file.path, parentContainer.kind, parentContainer.displayName);
323
+ }
324
+ semantics.symbols.push(symbol);
325
+ }
326
+ const openBraces = (line.match(/{/g) ?? []).length;
327
+ const closeBraces = (line.match(/}/g) ?? []).length;
328
+ const nextBraceDepth = braceDepth + openBraces - closeBraces;
329
+ if (matchedContainerSymbol && openBraces > 0) {
330
+ containerStack.push({ ...matchedContainerSymbol, depth: braceDepth + 1 });
331
+ }
332
+ braceDepth = nextBraceDepth;
333
+ });
334
+ return semantics;
335
+ }
336
+ function buildDartRegexSymbol(file, kind, displayName, line, lineNumber, col) {
337
+ return {
338
+ localKey: (0, shared_js_1.buildLocalSymbolKey)(file.path, kind, displayName),
339
+ stableKey: (0, shared_js_1.buildStableSymbolKey)(file.path, kind, displayName, lineNumber),
340
+ displayName,
341
+ kind,
342
+ language: file.language,
343
+ signature: line.trim(),
344
+ returnType: null,
345
+ doc: null,
346
+ isExported: false,
347
+ isDefaultExport: false,
348
+ line: lineNumber,
349
+ col: Math.max(col, 0),
350
+ endLine: lineNumber,
351
+ endCol: Math.max(col, 0) + displayName.length,
352
+ };
353
+ }
@@ -0,0 +1,11 @@
1
+ import type { WorkspaceFileCandidate } from "../file-discovery.js";
2
+ import type { TypeScriptResolverConfig } from "../ts-resolver.js";
3
+ export type { ParsedWorkspaceSemantics } from "./types.js";
4
+ export declare function parseWorkspaceFileSemantics(input: {
5
+ file: WorkspaceFileCandidate;
6
+ filePathSet: Set<string>;
7
+ projectImportId: string;
8
+ workspacePath: string;
9
+ resolverConfigs?: TypeScriptResolverConfig[];
10
+ }): Promise<import("./types.js").ParsedWorkspaceSemantics>;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AASlE,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE3D,wBAAsB,2BAA2B,CAAC,KAAK,EAAE;IACvD,IAAI,EAAE,sBAAsB,CAAC;IAC7B,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAC9C,0DA4BA"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseWorkspaceFileSemantics = parseWorkspaceFileSemantics;
4
+ const dart_js_1 = require("./dart.js");
5
+ const java_js_1 = require("./java.js");
6
+ const kotlin_js_1 = require("./kotlin.js");
7
+ const php_js_1 = require("./php.js");
8
+ const python_js_1 = require("./python.js");
9
+ const typescript_js_1 = require("./typescript.js");
10
+ const types_js_1 = require("./types.js");
11
+ async function parseWorkspaceFileSemantics(input) {
12
+ if (!input.file.language || !input.file.content) {
13
+ return { ...types_js_1.EMPTY_SEMANTICS };
14
+ }
15
+ switch (input.file.language) {
16
+ case "TypeScript":
17
+ case "JavaScript":
18
+ return (0, typescript_js_1.parseTypeScriptOrJavaScriptFile)(input.file, input.filePathSet, input.projectImportId, input.workspacePath, input.resolverConfigs ?? []);
19
+ case "Dart":
20
+ return (0, dart_js_1.parseDartFile)(input.file, input.filePathSet, input.projectImportId);
21
+ case "Java":
22
+ return (0, java_js_1.parseJavaFile)(input.file, input.projectImportId);
23
+ case "Kotlin":
24
+ return (0, kotlin_js_1.parseKotlinFile)(input.file, input.projectImportId);
25
+ case "PHP":
26
+ return (0, php_js_1.parsePhpFile)(input.file, input.projectImportId);
27
+ case "Python":
28
+ return (0, python_js_1.parsePythonFile)(input.file, input.filePathSet, input.projectImportId);
29
+ default:
30
+ return { ...types_js_1.EMPTY_SEMANTICS };
31
+ }
32
+ }
@@ -0,0 +1,4 @@
1
+ import type { WorkspaceFileCandidate } from "../file-discovery.js";
2
+ import { type ParsedWorkspaceSemantics } from "./types.js";
3
+ export declare function parseJavaFile(file: WorkspaceFileCandidate, projectImportId: string): Promise<ParsedWorkspaceSemantics>;
4
+ //# sourceMappingURL=java.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"java.d.ts","sourceRoot":"","sources":["../../src/parsers/java.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,EAA2C,KAAK,wBAAwB,EAAuB,MAAM,YAAY,CAAC;AAsBzH,wBAAsB,aAAa,CACjC,IAAI,EAAE,sBAAsB,EAC5B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,wBAAwB,CAAC,CAoDnC"}
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseJavaFile = parseJavaFile;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const web_tree_sitter_1 = require("web-tree-sitter");
9
+ const shared_js_1 = require("./shared.js");
10
+ const types_js_1 = require("./types.js");
11
+ let parserReady = null;
12
+ function getJavaParser() {
13
+ if (!parserReady) {
14
+ parserReady = (async () => {
15
+ await web_tree_sitter_1.Parser.init();
16
+ const wasmPath = node_path_1.default.resolve(node_path_1.default.dirname(require.resolve("tree-sitter-wasms/package.json")), "out", "tree-sitter-java.wasm");
17
+ const language = await web_tree_sitter_1.Language.load(wasmPath);
18
+ const parser = new web_tree_sitter_1.Parser();
19
+ parser.setLanguage(language);
20
+ return { parser, language };
21
+ })();
22
+ }
23
+ return parserReady;
24
+ }
25
+ async function parseJavaFile(file, projectImportId) {
26
+ const content = file.content ?? "";
27
+ if (!content.trim())
28
+ return { ...types_js_1.EMPTY_SEMANTICS };
29
+ let parser;
30
+ try {
31
+ ({ parser } = await getJavaParser());
32
+ }
33
+ catch {
34
+ return parseJavaFileWithRegexFallback(file, projectImportId);
35
+ }
36
+ const tree = parser.parse(content);
37
+ if (!tree)
38
+ return parseJavaFileWithRegexFallback(file, projectImportId);
39
+ const semantics = createEmptySemantics();
40
+ const lines = content.split(/\r?\n/);
41
+ const seenSymbols = new Set();
42
+ const seenImports = new Set();
43
+ walkJavaAst(tree.rootNode, (node) => {
44
+ const line = node.startPosition.row + 1;
45
+ const col = node.startPosition.column;
46
+ const packageName = parseJavaPackage(node.text);
47
+ if (packageName) {
48
+ addJavaSymbol(semantics, seenSymbols, file, "namespace", packageName, lines[node.startPosition.row] ?? node.text, line, col, node.endPosition.row + 1, node.endPosition.column);
49
+ return;
50
+ }
51
+ const importName = parseJavaImport(node.text);
52
+ if (importName) {
53
+ addJavaImport(semantics, seenImports, file, projectImportId, importName, line, col, node.endPosition.row + 1, node.endPosition.column);
54
+ return;
55
+ }
56
+ const symbol = parseJavaSymbol(node.text, node.type, isJavaMemberNode(node));
57
+ if (!symbol)
58
+ return;
59
+ addJavaSymbol(semantics, seenSymbols, file, symbol.kind, symbol.displayName, lines[node.startPosition.row] ?? node.text, line, col, node.endPosition.row + 1, node.endPosition.column, findParentJavaSymbolLocalKey(node, file.path));
60
+ });
61
+ return semantics;
62
+ }
63
+ function createEmptySemantics() {
64
+ return {
65
+ symbols: [],
66
+ imports: [],
67
+ exports: [],
68
+ relationships: [],
69
+ calls: [],
70
+ issues: [],
71
+ externalSymbols: [],
72
+ };
73
+ }
74
+ function walkJavaAst(node, visitor) {
75
+ visitor(node);
76
+ for (let i = 0; i < node.childCount; i++) {
77
+ const child = node.child(i);
78
+ if (child)
79
+ walkJavaAst(child, visitor);
80
+ }
81
+ }
82
+ function parseJavaPackage(text) {
83
+ return text.trim().match(/^package\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\s*;/)?.[1] ?? null;
84
+ }
85
+ function parseJavaImport(text) {
86
+ return text.trim().match(/^import\s+(?:static\s+)?([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*(?:\.\*)?)\s*;/)?.[1] ?? null;
87
+ }
88
+ function parseJavaSymbol(text, nodeType, isMemberNode) {
89
+ const trimmed = text.trim();
90
+ const typeMatch = trimmed.match(/^(?:(?:public|protected|private|abstract|static|final|sealed|non-sealed|strictfp)\s+)*(class|interface|enum|record|@interface)\s+([A-Za-z_]\w*)/);
91
+ if (typeMatch?.[1] && typeMatch[2]) {
92
+ const kind = typeMatch[1] === "interface" || typeMatch[1] === "@interface"
93
+ ? "interface"
94
+ : typeMatch[1] === "enum"
95
+ ? "enum"
96
+ : "class";
97
+ return { displayName: typeMatch[2], kind };
98
+ }
99
+ if (!/\b(method|constructor|declaration)\b/i.test(nodeType))
100
+ return null;
101
+ const methodMatch = trimmed.match(/^(?:(?:public|protected|private|abstract|static|final|synchronized|native|strictfp)\s+)*(?:<[^>{}]+>\s*)?(?:(?:[A-Za-z_]\w*(?:<[^>{}]+>)?(?:\[\])?|\w+\.\w+)\s+)?([A-Za-z_]\w*)\s*\(/);
102
+ if (!methodMatch?.[1] || ["if", "for", "while", "switch", "catch", "try"].includes(methodMatch[1])) {
103
+ return null;
104
+ }
105
+ return { displayName: methodMatch[1], kind: isMemberNode ? "method" : "function" };
106
+ }
107
+ function isJavaMemberNode(node) {
108
+ let current = node.parent;
109
+ while (current) {
110
+ if (/^(?:(?:public|protected|private|abstract|static|final|sealed|non-sealed|strictfp)\s+)*(class|interface|enum|record|@interface)\s+/.test(current.text.trimStart())) {
111
+ return true;
112
+ }
113
+ current = current.parent;
114
+ }
115
+ return false;
116
+ }
117
+ function findParentJavaSymbolLocalKey(node, filePath) {
118
+ let current = node.parent;
119
+ while (current) {
120
+ const parentSymbol = parseJavaSymbol(current.text, current.type, false);
121
+ if (parentSymbol && ["class", "interface", "enum"].includes(parentSymbol.kind)) {
122
+ return (0, shared_js_1.buildLocalSymbolKey)(filePath, parentSymbol.kind, parentSymbol.displayName);
123
+ }
124
+ current = current.parent;
125
+ }
126
+ return undefined;
127
+ }
128
+ function addJavaImport(semantics, seenImports, file, projectImportId, moduleSpecifier, line, col, endLine, endCol) {
129
+ const localKey = (0, shared_js_1.buildImportLocalKey)(file.path, "import", moduleSpecifier, line, col);
130
+ if (seenImports.has(localKey))
131
+ return;
132
+ seenImports.add(localKey);
133
+ semantics.imports.push({
134
+ localKey,
135
+ moduleSpecifier,
136
+ importKind: "import",
137
+ isTypeOnly: false,
138
+ importedNames: [moduleSpecifier.split(".").pop() ?? moduleSpecifier],
139
+ line,
140
+ col,
141
+ endLine,
142
+ endCol,
143
+ resolutionKind: "package",
144
+ targetPathText: null,
145
+ targetExternalSymbolKey: `java:${moduleSpecifier}`,
146
+ });
147
+ semantics.externalSymbols.push((0, shared_js_1.createExternalSymbolDraft)(projectImportId, file.language, moduleSpecifier));
148
+ }
149
+ function addJavaSymbol(semantics, seenSymbols, file, kind, displayName, signature, line, col, endLine, endCol, parentSymbolLocalKey) {
150
+ const stableKey = (0, shared_js_1.buildStableSymbolKey)(file.path, kind, displayName, line);
151
+ if (seenSymbols.has(stableKey))
152
+ return;
153
+ seenSymbols.add(stableKey);
154
+ semantics.symbols.push({
155
+ localKey: (0, shared_js_1.buildLocalSymbolKey)(file.path, kind, displayName),
156
+ stableKey,
157
+ displayName,
158
+ kind,
159
+ language: file.language,
160
+ signature: signature.trim(),
161
+ returnType: null,
162
+ doc: null,
163
+ isExported: true,
164
+ isDefaultExport: false,
165
+ line,
166
+ col,
167
+ endLine,
168
+ endCol,
169
+ parentSymbolLocalKey,
170
+ });
171
+ }
172
+ function parseJavaFileWithRegexFallback(file, projectImportId) {
173
+ const semantics = createEmptySemantics();
174
+ const lines = (0, shared_js_1.maskCommentsAndTemplateLiterals)(file.content ?? "").split(/\r?\n/);
175
+ const originalLines = (file.content ?? "").split(/\r?\n/);
176
+ const seenSymbols = new Set();
177
+ const seenImports = new Set();
178
+ const containerStack = [];
179
+ let braceDepth = 0;
180
+ lines.forEach((line, index) => {
181
+ const originalLine = originalLines[index] ?? line;
182
+ const lineNumber = index + 1;
183
+ while (containerStack.length > 0 && braceDepth < containerStack[containerStack.length - 1].depth) {
184
+ containerStack.pop();
185
+ }
186
+ const parentContainer = containerStack[containerStack.length - 1];
187
+ let matchedContainer = null;
188
+ const packageName = parseJavaPackage(line);
189
+ if (packageName) {
190
+ addJavaSymbol(semantics, seenSymbols, file, "namespace", packageName, originalLine, lineNumber, line.indexOf(packageName), lineNumber, line.length);
191
+ }
192
+ const importName = parseJavaImport(line);
193
+ if (importName) {
194
+ addJavaImport(semantics, seenImports, file, projectImportId, importName, lineNumber, line.indexOf(importName), lineNumber, line.length);
195
+ }
196
+ const typeMatch = line.match(/^\s*(?:(?:public|protected|private|abstract|static|final|sealed|non-sealed|strictfp)\s+)*(class|interface|enum|record|@interface)\s+([A-Za-z_]\w*)/);
197
+ if (typeMatch?.[1] && typeMatch[2]) {
198
+ const kind = typeMatch[1] === "interface" || typeMatch[1] === "@interface"
199
+ ? "interface"
200
+ : typeMatch[1] === "enum"
201
+ ? "enum"
202
+ : "class";
203
+ addJavaSymbol(semantics, seenSymbols, file, kind, typeMatch[2], originalLine, lineNumber, line.indexOf(typeMatch[2]), lineNumber, line.length);
204
+ matchedContainer = { kind, displayName: typeMatch[2] };
205
+ }
206
+ const methodMatch = line.match(/^\s*(?:(?:public|protected|private|abstract|static|final|synchronized|native|strictfp)\s+)*(?:<[^>{}]+>\s*)?(?:(?:[A-Za-z_]\w*(?:<[^>{}]+>)?(?:\[\])?|\w+\.\w+)\s+)?([A-Za-z_]\w*)\s*\([^;{}]*\)\s*(?:throws\s+[^{]+)?(?:\{|$)/);
207
+ if (methodMatch?.[1] && !["if", "for", "while", "switch", "catch", "try"].includes(methodMatch[1])) {
208
+ const kind = parentContainer ? "method" : "function";
209
+ const parentSymbolLocalKey = parentContainer
210
+ ? (0, shared_js_1.buildLocalSymbolKey)(file.path, parentContainer.kind, parentContainer.displayName)
211
+ : undefined;
212
+ addJavaSymbol(semantics, seenSymbols, file, kind, methodMatch[1], originalLine, lineNumber, line.indexOf(methodMatch[1]), lineNumber, line.length, parentSymbolLocalKey);
213
+ }
214
+ const openBraces = (line.match(/{/g) ?? []).length;
215
+ const closeBraces = (line.match(/}/g) ?? []).length;
216
+ if (matchedContainer && openBraces > 0) {
217
+ containerStack.push({ ...matchedContainer, depth: braceDepth + 1 });
218
+ }
219
+ braceDepth += openBraces - closeBraces;
220
+ });
221
+ return semantics;
222
+ }
@@ -0,0 +1,4 @@
1
+ import type { WorkspaceFileCandidate } from "../file-discovery.js";
2
+ import { type ParsedWorkspaceSemantics } from "./types.js";
3
+ export declare function parseKotlinFile(file: WorkspaceFileCandidate, projectImportId: string): Promise<ParsedWorkspaceSemantics>;
4
+ //# sourceMappingURL=kotlin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kotlin.d.ts","sourceRoot":"","sources":["../../src/parsers/kotlin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,EAA2C,KAAK,wBAAwB,EAAuB,MAAM,YAAY,CAAC;AAsBzH,wBAAsB,eAAe,CACnC,IAAI,EAAE,sBAAsB,EAC5B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,wBAAwB,CAAC,CAoDnC"}