project-librarian 0.5.4 → 0.5.6
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/CONTRIBUTING.md +36 -0
- package/README.ko.md +57 -360
- package/README.md +56 -359
- package/dist/args.js +6 -1
- package/dist/code-index/extractors/light-languages.js +285 -0
- package/dist/code-index/extractors/registry.js +12 -0
- package/dist/code-index/extractors/shared.js +18 -1
- package/dist/code-index/extractors/typescript.js +30 -16
- package/dist/code-index/modes.js +136 -32
- package/dist/code-index/native-helper-matrix.js +99 -0
- package/dist/code-index/native-helper.js +292 -0
- package/dist/code-index/ownership.js +8 -6
- package/dist/code-index/schema.js +72 -13
- package/dist/code-index/search.js +1 -1
- package/dist/code-index-db.js +20 -12
- package/dist/code-index-file-policy.js +17 -11
- package/dist/code-index.js +365 -13
- package/dist/hooks.js +5 -5
- package/dist/init-project-wiki.js +7 -1
- package/dist/install-skill.js +99 -6
- package/dist/mcp-server.js +4 -4
- package/dist/migration.js +27 -2
- package/dist/native/darwin-arm64/project-librarian-indexer +0 -0
- package/dist/native/darwin-x64/project-librarian-indexer +0 -0
- package/dist/native/linux-arm64/project-librarian-indexer +0 -0
- package/dist/native/linux-arm64-musl/project-librarian-indexer +0 -0
- package/dist/native/linux-x64/project-librarian-indexer +0 -0
- package/dist/native/linux-x64-musl/project-librarian-indexer +0 -0
- package/dist/native/project-librarian-indexer-manifest.json +70 -0
- package/dist/native/win32-arm64/project-librarian-indexer.exe +0 -0
- package/dist/native/win32-x64/project-librarian-indexer.exe +0 -0
- package/dist/templates.js +4 -3
- package/dist/workspace.js +137 -10
- package/docs/README.md +11 -0
- package/docs/benchmarks.md +64 -0
- package/docs/cli-reference.md +60 -0
- package/docs/code-evidence.md +87 -0
- package/docs/ko/README.md +13 -0
- package/docs/ko/benchmarks.md +64 -0
- package/docs/ko/cli-reference.md +60 -0
- package/docs/ko/code-evidence.md +87 -0
- package/docs/ko/maintainer.md +76 -0
- package/docs/ko/usage.md +167 -0
- package/docs/maintainer.md +76 -0
- package/docs/usage.md +175 -0
- package/package.json +13 -2
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.genericLightProfileByLanguage = void 0;
|
|
3
4
|
exports.indexPythonLight = indexPythonLight;
|
|
4
5
|
exports.indexGoLight = indexGoLight;
|
|
6
|
+
exports.indexGenericLight = indexGenericLight;
|
|
5
7
|
const shared_1 = require("./shared");
|
|
8
|
+
exports.genericLightProfileByLanguage = {
|
|
9
|
+
c: "c-light",
|
|
10
|
+
cpp: "cpp-light",
|
|
11
|
+
csharp: "csharp-light",
|
|
12
|
+
java: "java-light",
|
|
13
|
+
kotlin: "kotlin-light",
|
|
14
|
+
php: "php-light",
|
|
15
|
+
rust: "rust-light",
|
|
16
|
+
swift: "swift-light",
|
|
17
|
+
};
|
|
6
18
|
function indexPythonLight(file, statements) {
|
|
7
19
|
const symbolPatterns = [
|
|
8
20
|
[/^\s*def\s+([A-Za-z_]\w*)\s*\(([^)]*)\)/gm, "function", (match) => `def ${match[1] ?? ""}(${match[2] ?? ""})`],
|
|
@@ -50,3 +62,276 @@ function indexGoLight(file, statements) {
|
|
|
50
62
|
}
|
|
51
63
|
});
|
|
52
64
|
}
|
|
65
|
+
function indexGenericLight(file, statements, language) {
|
|
66
|
+
let phpTypeDepth = 0;
|
|
67
|
+
for (const [index, rawLine] of file.text.split("\n").entries()) {
|
|
68
|
+
const line = rawLine.replace(/\r$/, "");
|
|
69
|
+
const lineNumberOneBased = index + 1;
|
|
70
|
+
const trimmed = normalizeGenericLightLine(line, language);
|
|
71
|
+
if (!trimmed || genericLineIsComment(trimmed, language)) {
|
|
72
|
+
phpTypeDepth += braceDelta(trimmed);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const imported = genericLightImport(trimmed, language);
|
|
76
|
+
if (imported) {
|
|
77
|
+
statements.insertImport.run(file.path, imported.toRef, imported.imported, lineNumberOneBased, imported.raw);
|
|
78
|
+
(0, shared_1.insertEdge)(statements, imported.edgeKind, "file", file.path, "module", imported.toRef, file, lineNumberOneBased, imported.raw);
|
|
79
|
+
}
|
|
80
|
+
const symbol = genericLightSymbol(trimmed, language, phpTypeDepth > 0);
|
|
81
|
+
if (symbol)
|
|
82
|
+
(0, shared_1.insertSymbol)(statements, symbol.name, symbol.kind, file, lineNumberOneBased, symbol.signature);
|
|
83
|
+
phpTypeDepth += braceDelta(trimmed);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function normalizeGenericLightLine(line, language) {
|
|
87
|
+
const trimmed = line.trim();
|
|
88
|
+
if (language === "php")
|
|
89
|
+
return trimmed.replace(/^<\?php\s*/, "");
|
|
90
|
+
if (language === "java" || language === "kotlin" || language === "swift")
|
|
91
|
+
return stripLeadingAtAnnotations(trimmed);
|
|
92
|
+
return trimmed;
|
|
93
|
+
}
|
|
94
|
+
function stripLeadingAtAnnotations(line) {
|
|
95
|
+
let rest = line;
|
|
96
|
+
while (true) {
|
|
97
|
+
const match = rest.match(/^@[A-Za-z_][\w.]*(:[A-Za-z_]\w*)?(?:\([^)]*\))?\s*/);
|
|
98
|
+
if (!match)
|
|
99
|
+
return rest;
|
|
100
|
+
rest = rest.slice(match[0].length).trimStart();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function genericLineIsComment(line, language) {
|
|
104
|
+
if (line.startsWith("//") || line.startsWith("/*") || line.startsWith("*"))
|
|
105
|
+
return true;
|
|
106
|
+
if (language === "php" && line.startsWith("#"))
|
|
107
|
+
return true;
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
function braceDelta(line) {
|
|
111
|
+
let delta = 0;
|
|
112
|
+
let quote = "";
|
|
113
|
+
let escaped = false;
|
|
114
|
+
for (const ch of line) {
|
|
115
|
+
if (quote) {
|
|
116
|
+
if (escaped)
|
|
117
|
+
escaped = false;
|
|
118
|
+
else if (ch === "\\")
|
|
119
|
+
escaped = true;
|
|
120
|
+
else if (ch === quote)
|
|
121
|
+
quote = "";
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (ch === "\"" || ch === "'" || ch === "`") {
|
|
125
|
+
quote = ch;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (ch === "{")
|
|
129
|
+
delta += 1;
|
|
130
|
+
else if (ch === "}")
|
|
131
|
+
delta -= 1;
|
|
132
|
+
}
|
|
133
|
+
return delta;
|
|
134
|
+
}
|
|
135
|
+
function genericLightImport(line, language) {
|
|
136
|
+
if (language === "c" || language === "cpp") {
|
|
137
|
+
const include = line.match(/^#\s*include\s*[<"]([^>"]+)[>"]/);
|
|
138
|
+
if (include?.[1])
|
|
139
|
+
return { edgeKind: "import", imported: "", raw: include[0], toRef: include[1] };
|
|
140
|
+
if (language === "cpp") {
|
|
141
|
+
const using = line.match(/^using\s+(?:namespace\s+)?([A-Za-z_]\w*(?:::[A-Za-z_]\w*)*)\s*;?/);
|
|
142
|
+
if (using?.[1])
|
|
143
|
+
return { edgeKind: "import", imported: "", raw: line.replace(/;$/, ""), toRef: using[1] };
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
if (language === "rust") {
|
|
148
|
+
const rustUse = line.match(/^use\s+(.+?)\s*;?$/);
|
|
149
|
+
if (rustUse?.[1])
|
|
150
|
+
return { edgeKind: "use", imported: "", raw: line.replace(/;$/, ""), toRef: rustUse[1].replace(/\s+/g, " ").trim() };
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
if (language === "php") {
|
|
154
|
+
const phpUse = line.match(/^use\s+([^;]+)\s*;?/);
|
|
155
|
+
if (phpUse?.[1])
|
|
156
|
+
return { edgeKind: "import", imported: "", raw: line.replace(/;$/, ""), toRef: phpUse[1].replace(/\s+/g, " ").trim() };
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
if (language === "csharp") {
|
|
160
|
+
const using = line.match(/^using\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\s*;?/);
|
|
161
|
+
if (using?.[1])
|
|
162
|
+
return { edgeKind: "import", imported: "", raw: line.replace(/;$/, ""), toRef: using[1] };
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
if (language === "swift") {
|
|
166
|
+
const imported = line.match(/^import\s+([A-Za-z_]\w*)/);
|
|
167
|
+
if (imported?.[1])
|
|
168
|
+
return { edgeKind: "import", imported: "", raw: imported[0], toRef: imported[1] };
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
const imported = line.match(/^import\s+([A-Za-z_]\w*(?:[.*$][A-Za-z_]\w*)*(?:\.\*)?)\s*;?/);
|
|
172
|
+
if (imported?.[1])
|
|
173
|
+
return { edgeKind: "import", imported: "", raw: line.replace(/;$/, ""), toRef: imported[1] };
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
function genericLightSymbol(line, language, phpInsideType) {
|
|
177
|
+
if (language === "rust")
|
|
178
|
+
return rustLightSymbol(line);
|
|
179
|
+
if (language === "kotlin")
|
|
180
|
+
return kotlinLightSymbol(line);
|
|
181
|
+
if (language === "swift")
|
|
182
|
+
return swiftLightSymbol(line);
|
|
183
|
+
if (language === "php")
|
|
184
|
+
return phpLightSymbol(line, phpInsideType);
|
|
185
|
+
if (language === "c" || language === "cpp")
|
|
186
|
+
return cFamilyLightSymbol(line, language);
|
|
187
|
+
if (language === "java" || language === "csharp")
|
|
188
|
+
return jvmOrCsharpLightSymbol(line, language);
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
function rustLightSymbol(line) {
|
|
192
|
+
const fn = line.match(/^(?:pub(?:\([^)]*\))?\s+)?(?:async\s+)?fn\s+([A-Za-z_]\w*)/);
|
|
193
|
+
if (fn?.[1])
|
|
194
|
+
return symbol("function", fn[1], line);
|
|
195
|
+
for (const [keyword, kind] of [["struct", "struct"], ["enum", "enum"], ["trait", "trait"]]) {
|
|
196
|
+
const found = line.match(new RegExp(`^(?:pub(?:\\([^)]*\\))?\\s+)?${keyword}\\s+([A-Za-z_]\\w*)`));
|
|
197
|
+
if (found?.[1])
|
|
198
|
+
return symbol(kind, found[1], line);
|
|
199
|
+
}
|
|
200
|
+
const implName = rustImplName(line);
|
|
201
|
+
if (implName)
|
|
202
|
+
return symbol("impl", implName, line);
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
function rustImplName(line) {
|
|
206
|
+
let rest = line.replace(/^unsafe\s+/, "");
|
|
207
|
+
if (!rest.startsWith("impl"))
|
|
208
|
+
return "";
|
|
209
|
+
rest = rest.slice("impl".length);
|
|
210
|
+
if (rest.startsWith("<")) {
|
|
211
|
+
const genericEnd = matchingAngleEnd(rest);
|
|
212
|
+
if (genericEnd <= 1)
|
|
213
|
+
return "";
|
|
214
|
+
const afterGeneric = rest.slice(genericEnd + 1);
|
|
215
|
+
if (!/^\s+/.test(afterGeneric))
|
|
216
|
+
return "";
|
|
217
|
+
rest = afterGeneric.trimStart();
|
|
218
|
+
}
|
|
219
|
+
else if (/^\s+/.test(rest)) {
|
|
220
|
+
rest = rest.trimStart();
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
return "";
|
|
224
|
+
}
|
|
225
|
+
const forIndex = rest.lastIndexOf(" for ");
|
|
226
|
+
if (forIndex !== -1) {
|
|
227
|
+
const afterForName = rest.slice(forIndex + " for ".length).trimStart().match(/^([A-Za-z_]\w*)/);
|
|
228
|
+
if (afterForName?.[1])
|
|
229
|
+
return afterForName[1];
|
|
230
|
+
rest = rest.slice(0, forIndex).trimEnd();
|
|
231
|
+
}
|
|
232
|
+
return rest.match(/^([A-Za-z_]\w*)/)?.[1] ?? "";
|
|
233
|
+
}
|
|
234
|
+
function matchingAngleEnd(text) {
|
|
235
|
+
let depth = 0;
|
|
236
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
237
|
+
const ch = text[index];
|
|
238
|
+
if (ch === "<")
|
|
239
|
+
depth += 1;
|
|
240
|
+
else if (ch === ">") {
|
|
241
|
+
depth -= 1;
|
|
242
|
+
if (depth === 0)
|
|
243
|
+
return index;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return -1;
|
|
247
|
+
}
|
|
248
|
+
function kotlinLightSymbol(line) {
|
|
249
|
+
const fn = line.match(/^(?:[\w\s]+\s+)?fun\s+(?:[A-Za-z_]\w*\.)?([A-Za-z_]\w*)/);
|
|
250
|
+
if (fn?.[1])
|
|
251
|
+
return symbol("function", fn[1], line);
|
|
252
|
+
const klass = line.match(/^(?:[\w\s]+\s+)?(?:data\s+|sealed\s+|open\s+)?(class|interface)\s+([A-Za-z_]\w*)/);
|
|
253
|
+
if (klass?.[2])
|
|
254
|
+
return symbol(klass[1] === "interface" ? "interface" : "class", klass[2], line);
|
|
255
|
+
const object = line.match(/^(?:[\w\s]+\s+)?object\s+([A-Za-z_]\w*)/);
|
|
256
|
+
if (object?.[1])
|
|
257
|
+
return symbol("object", object[1], line);
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
function swiftLightSymbol(line) {
|
|
261
|
+
const fn = line.match(/^(?:[\w\s]+\s+)?func\s+([A-Za-z_]\w*)/);
|
|
262
|
+
if (fn?.[1])
|
|
263
|
+
return symbol("function", fn[1], line);
|
|
264
|
+
for (const [keyword, kind] of [["class", "class"], ["struct", "struct"], ["protocol", "protocol"], ["enum", "enum"]]) {
|
|
265
|
+
const found = line.match(new RegExp(`^(?:[\\w\\s]+\\s+)?${keyword}\\s+([A-Za-z_]\\w*)`));
|
|
266
|
+
if (found?.[1])
|
|
267
|
+
return symbol(kind, found[1], line);
|
|
268
|
+
}
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
function phpLightSymbol(line, insideType) {
|
|
272
|
+
for (const [keyword, kind] of [["class", "class"], ["interface", "interface"], ["trait", "trait"]]) {
|
|
273
|
+
const found = line.match(new RegExp(`^(?:abstract\\s+|final\\s+)?${keyword}\\s+([A-Za-z_]\\w*)`));
|
|
274
|
+
if (found?.[1])
|
|
275
|
+
return symbol(kind, found[1], line);
|
|
276
|
+
}
|
|
277
|
+
const fn = line.match(/^(?:public\s+|private\s+|protected\s+|static\s+|final\s+|abstract\s+)*function\s+&?\s*([A-Za-z_]\w*)/);
|
|
278
|
+
if (fn?.[1])
|
|
279
|
+
return symbol(insideType ? "method" : "function", fn[1], line);
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
function cFamilyLightSymbol(line, language) {
|
|
283
|
+
if (language === "cpp") {
|
|
284
|
+
const namespace = line.match(/^namespace\s+([A-Za-z_]\w*)/);
|
|
285
|
+
if (namespace?.[1])
|
|
286
|
+
return symbol("namespace", namespace[1], line);
|
|
287
|
+
const klass = line.match(/^(?:template\s*<[^>]+>\s*)?(class|struct)\s+([A-Za-z_]\w*)/);
|
|
288
|
+
if (klass?.[2])
|
|
289
|
+
return symbol(klass[1] === "class" ? "class" : "struct", klass[2], line);
|
|
290
|
+
const enumMatch = line.match(/^enum(?:\s+class)?\s+([A-Za-z_]\w*)/);
|
|
291
|
+
if (enumMatch?.[1])
|
|
292
|
+
return symbol("enum", enumMatch[1], line);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
const struct = line.match(/^struct\s+([A-Za-z_]\w*)/);
|
|
296
|
+
if (struct?.[1])
|
|
297
|
+
return symbol("struct", struct[1], line);
|
|
298
|
+
const enumMatch = line.match(/^enum\s+([A-Za-z_]\w*)/);
|
|
299
|
+
if (enumMatch?.[1])
|
|
300
|
+
return symbol("enum", enumMatch[1], line);
|
|
301
|
+
}
|
|
302
|
+
const functionName = cLikeFunctionName(line);
|
|
303
|
+
if (functionName)
|
|
304
|
+
return symbol("function", functionName, line);
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
function jvmOrCsharpLightSymbol(line, language) {
|
|
308
|
+
for (const [keyword, kind] of [
|
|
309
|
+
["class", "class"],
|
|
310
|
+
["interface", "interface"],
|
|
311
|
+
["enum", "enum"],
|
|
312
|
+
...(language === "csharp" ? [["struct", "struct"]] : []),
|
|
313
|
+
]) {
|
|
314
|
+
const found = line.match(new RegExp(`^(?:[\\w\\s]+\\s+)?${keyword}\\s+([A-Za-z_]\\w*)`));
|
|
315
|
+
if (found?.[1])
|
|
316
|
+
return symbol(kind, found[1], line);
|
|
317
|
+
}
|
|
318
|
+
const methodName = cLikeFunctionName(line);
|
|
319
|
+
if (methodName)
|
|
320
|
+
return symbol("method", methodName, line);
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
function cLikeFunctionName(line) {
|
|
324
|
+
if (!line.includes("(") || line.endsWith(";") || line.startsWith("#"))
|
|
325
|
+
return "";
|
|
326
|
+
const firstToken = line.split(/\s+/, 1)[0] ?? "";
|
|
327
|
+
if (["if", "for", "while", "switch", "catch", "return", "new", "throw"].includes(firstToken))
|
|
328
|
+
return "";
|
|
329
|
+
const beforeParen = line.slice(0, line.indexOf("(")).trim();
|
|
330
|
+
const name = beforeParen.match(/(?:^|[\s:*&~])([A-Za-z_]\w*)$/)?.[1] ?? "";
|
|
331
|
+
if (["if", "for", "while", "switch", "catch", "return", "sizeof"].includes(name))
|
|
332
|
+
return "";
|
|
333
|
+
return name;
|
|
334
|
+
}
|
|
335
|
+
function symbol(kind, name, line) {
|
|
336
|
+
return { kind, name, signature: (0, shared_1.oneLine)(line) };
|
|
337
|
+
}
|
|
@@ -81,11 +81,16 @@ function extractionProfile(relativePath, language, parserMode) {
|
|
|
81
81
|
return "python-light";
|
|
82
82
|
if (language === "go")
|
|
83
83
|
return "go-light";
|
|
84
|
+
if (isGenericLightLanguage(language))
|
|
85
|
+
return light_languages_1.genericLightProfileByLanguage[language];
|
|
84
86
|
return "inventory-only";
|
|
85
87
|
}
|
|
86
88
|
function isJavaScriptLikeProfileInput(language) {
|
|
87
89
|
return language === "javascript" || language === "typescript";
|
|
88
90
|
}
|
|
91
|
+
function isGenericLightLanguage(language) {
|
|
92
|
+
return ["c", "cpp", "csharp", "java", "kotlin", "php", "rust", "swift"].includes(language);
|
|
93
|
+
}
|
|
89
94
|
function createExtractionBackendRegistry(fail) {
|
|
90
95
|
const extractionBackends = [
|
|
91
96
|
{
|
|
@@ -109,6 +114,13 @@ function createExtractionBackendRegistry(fail) {
|
|
|
109
114
|
profile: "go-light",
|
|
110
115
|
strength: "light",
|
|
111
116
|
},
|
|
117
|
+
...Object.entries(light_languages_1.genericLightProfileByLanguage).map(([language, profile]) => ({
|
|
118
|
+
id: "regex-light",
|
|
119
|
+
index: (file, statements) => (0, light_languages_1.indexGenericLight)(file, statements, language),
|
|
120
|
+
label: `${language} lightweight regex`,
|
|
121
|
+
profile,
|
|
122
|
+
strength: "light",
|
|
123
|
+
})),
|
|
112
124
|
...(0, tree_sitter_1.treeSitterBackends)(fail),
|
|
113
125
|
{
|
|
114
126
|
id: "config-key-value",
|
|
@@ -7,7 +7,24 @@ exports.insertEdge = insertEdge;
|
|
|
7
7
|
exports.insertMatches = insertMatches;
|
|
8
8
|
exports.insertGoImport = insertGoImport;
|
|
9
9
|
function oneLine(text) {
|
|
10
|
-
|
|
10
|
+
let output = "";
|
|
11
|
+
let pendingSpace = false;
|
|
12
|
+
for (let index = 0; index < text.length && output.length < 240; index += 1) {
|
|
13
|
+
const code = text.charCodeAt(index);
|
|
14
|
+
if (code === 9 || code === 10 || code === 11 || code === 12 || code === 13 || code === 32) {
|
|
15
|
+
if (output.length > 0)
|
|
16
|
+
pendingSpace = true;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (pendingSpace) {
|
|
20
|
+
output += " ";
|
|
21
|
+
pendingSpace = false;
|
|
22
|
+
if (output.length >= 240)
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
output += text[index];
|
|
26
|
+
}
|
|
27
|
+
return output;
|
|
11
28
|
}
|
|
12
29
|
function lineNumber(text, index) {
|
|
13
30
|
return text.slice(0, index).split(/\r?\n/).length;
|
|
@@ -138,18 +138,22 @@ function signatureFor(node, sourceFile) {
|
|
|
138
138
|
return (0, shared_1.oneLine)(node.getText(sourceFile));
|
|
139
139
|
}
|
|
140
140
|
function indexJavaScriptLike(file, statements) {
|
|
141
|
-
const sourceFile = ts.createSourceFile(file.path, file.text, ts.ScriptTarget.Latest,
|
|
141
|
+
const sourceFile = ts.createSourceFile(file.path, file.text, ts.ScriptTarget.Latest, false, scriptKindForPath(file.path));
|
|
142
142
|
function visit(node, context) {
|
|
143
143
|
let nextContext = context;
|
|
144
144
|
if (ts.isFunctionDeclaration(node)) {
|
|
145
145
|
const name = node.name?.text ?? "";
|
|
146
|
-
|
|
146
|
+
const line = tsLine(sourceFile, node);
|
|
147
|
+
const signature = signatureFor(node, sourceFile);
|
|
148
|
+
(0, shared_1.insertSymbol)(statements, name, "function", file, line, signature);
|
|
147
149
|
if (name)
|
|
148
150
|
nextContext = name;
|
|
149
151
|
}
|
|
150
152
|
else if (ts.isClassDeclaration(node)) {
|
|
151
153
|
const name = node.name?.text ?? "";
|
|
152
|
-
|
|
154
|
+
const line = tsLine(sourceFile, node);
|
|
155
|
+
const signature = signatureFor(node, sourceFile);
|
|
156
|
+
(0, shared_1.insertSymbol)(statements, name, "class", file, line, signature);
|
|
153
157
|
if (name)
|
|
154
158
|
nextContext = name;
|
|
155
159
|
}
|
|
@@ -164,45 +168,55 @@ function indexJavaScriptLike(file, statements) {
|
|
|
164
168
|
}
|
|
165
169
|
else if (ts.isMethodDeclaration(node)) {
|
|
166
170
|
const name = propertyNameText(node.name, sourceFile);
|
|
167
|
-
|
|
171
|
+
const line = tsLine(sourceFile, node);
|
|
172
|
+
const signature = signatureFor(node, sourceFile);
|
|
173
|
+
(0, shared_1.insertSymbol)(statements, name, "method", file, line, signature);
|
|
168
174
|
for (const route of routeFromDecorator(node, sourceFile)) {
|
|
169
|
-
statements.insertRoute.run(route.method, route.route, file.path,
|
|
170
|
-
(0, shared_1.insertEdge)(statements, "route_to_handler", "route", `${route.method} ${route.route}`, "symbol", name, file,
|
|
175
|
+
statements.insertRoute.run(route.method, route.route, file.path, line, name);
|
|
176
|
+
(0, shared_1.insertEdge)(statements, "route_to_handler", "route", `${route.method} ${route.route}`, "symbol", name, file, line, signature);
|
|
171
177
|
}
|
|
172
178
|
if (name)
|
|
173
179
|
nextContext = name;
|
|
174
180
|
}
|
|
175
181
|
else if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {
|
|
176
182
|
const symbolKind = node.initializer && (ts.isArrowFunction(node.initializer) || ts.isFunctionExpression(node.initializer)) ? "function" : "variable";
|
|
177
|
-
|
|
183
|
+
const line = tsLine(sourceFile, node);
|
|
184
|
+
const signature = signatureFor(node, sourceFile);
|
|
185
|
+
(0, shared_1.insertSymbol)(statements, node.name.text, symbolKind, file, line, signature);
|
|
178
186
|
if (symbolKind === "function")
|
|
179
187
|
nextContext = node.name.text;
|
|
180
188
|
}
|
|
181
189
|
else if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
182
190
|
const imported = importBindingText(node.importClause, sourceFile);
|
|
183
|
-
|
|
184
|
-
|
|
191
|
+
const line = tsLine(sourceFile, node);
|
|
192
|
+
const signature = signatureFor(node, sourceFile);
|
|
193
|
+
statements.insertImport.run(file.path, node.moduleSpecifier.text, imported, line, signature);
|
|
194
|
+
(0, shared_1.insertEdge)(statements, "import", "file", file.path, "module", node.moduleSpecifier.text, file, line, signature);
|
|
185
195
|
}
|
|
186
196
|
else if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
187
197
|
const exported = node.exportClause ? (0, shared_1.oneLine)(node.exportClause.getText(sourceFile)) : "";
|
|
188
|
-
|
|
189
|
-
|
|
198
|
+
const line = tsLine(sourceFile, node);
|
|
199
|
+
const signature = signatureFor(node, sourceFile);
|
|
200
|
+
statements.insertImport.run(file.path, node.moduleSpecifier.text, exported, line, signature);
|
|
201
|
+
(0, shared_1.insertEdge)(statements, "export", "file", file.path, "module", node.moduleSpecifier.text, file, line, signature);
|
|
190
202
|
}
|
|
191
203
|
else if (ts.isCallExpression(node)) {
|
|
204
|
+
const line = tsLine(sourceFile, node);
|
|
205
|
+
const signature = signatureFor(node, sourceFile);
|
|
192
206
|
const route = routeFromCall(node, sourceFile);
|
|
193
207
|
if (route) {
|
|
194
|
-
statements.insertRoute.run(route.method, route.route, file.path,
|
|
195
|
-
(0, shared_1.insertEdge)(statements, "route_to_handler", "route", `${route.method} ${route.route}`, "symbol", route.handler, file,
|
|
208
|
+
statements.insertRoute.run(route.method, route.route, file.path, line, route.handler);
|
|
209
|
+
(0, shared_1.insertEdge)(statements, "route_to_handler", "route", `${route.method} ${route.route}`, "symbol", route.handler, file, line, signature);
|
|
196
210
|
}
|
|
197
211
|
if (ts.isIdentifier(node.expression) && node.expression.text === "require") {
|
|
198
212
|
const moduleName = stringArg(node.arguments[0]);
|
|
199
213
|
if (moduleName) {
|
|
200
|
-
statements.insertImport.run(file.path, moduleName, "",
|
|
201
|
-
(0, shared_1.insertEdge)(statements, "import", "file", file.path, "module", moduleName, file,
|
|
214
|
+
statements.insertImport.run(file.path, moduleName, "", line, signature);
|
|
215
|
+
(0, shared_1.insertEdge)(statements, "import", "file", file.path, "module", moduleName, file, line, signature);
|
|
202
216
|
}
|
|
203
217
|
}
|
|
204
218
|
else {
|
|
205
|
-
(0, shared_1.insertEdge)(statements, "call", context ? "symbol" : "file", context || file.path, "symbol", callTarget(node.expression, sourceFile), file,
|
|
219
|
+
(0, shared_1.insertEdge)(statements, "call", context ? "symbol" : "file", context || file.path, "symbol", callTarget(node.expression, sourceFile), file, line, signature);
|
|
206
220
|
}
|
|
207
221
|
}
|
|
208
222
|
ts.forEachChild(node, (child) => visit(child, nextContext));
|