@jpoly1219/context-extractor 0.2.10 → 0.2.11
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/src/tree-sitter.js +21 -3
- package/dist/src/typescript-driver.d.ts +2 -2
- package/dist/src/typescript-driver.js +227 -148
- package/package.json +1 -1
package/dist/src/tree-sitter.js
CHANGED
@@ -37,6 +37,24 @@ async function getParserForFile(filepath) {
|
|
37
37
|
try {
|
38
38
|
await web_tree_sitter_1.default.init();
|
39
39
|
const parser = new web_tree_sitter_1.default();
|
40
|
+
// const packageRoot = path.dirname(
|
41
|
+
// require.resolve("./package.json", { paths: [__dirname] })
|
42
|
+
// );
|
43
|
+
// console.log(packageRoot);
|
44
|
+
// const wasmPath2 = require.resolve(
|
45
|
+
// path.join(
|
46
|
+
// __dirname,
|
47
|
+
// `tree-sitter-files/wasms/tree-sitter-${supportedLanguages["ts"]}.wasm`
|
48
|
+
// )
|
49
|
+
// );
|
50
|
+
// console.log(wasmPath2);
|
51
|
+
// const wasmPath3 = require.resolve(
|
52
|
+
// path.resolve(
|
53
|
+
// __dirname,
|
54
|
+
// `tree-sitter-files/wasms/tree-sitter-${supportedLanguages["ts"]}.wasm`
|
55
|
+
// )
|
56
|
+
// );
|
57
|
+
// console.log(wasmPath3);
|
40
58
|
const language = await getLanguageForFile(filepath);
|
41
59
|
if (!language) {
|
42
60
|
return undefined;
|
@@ -91,7 +109,7 @@ async function getQueryForFile(filepath, queryPath) {
|
|
91
109
|
return query;
|
92
110
|
}
|
93
111
|
async function loadLanguageForFileExt(fileExtension) {
|
94
|
-
const wasmPath = require.resolve(
|
112
|
+
const wasmPath = require.resolve(`@jpoly1219/context-extractor/src/tree-sitter-files/wasms/tree-sitter-${exports.supportedLanguages[fileExtension]}.wasm`);
|
95
113
|
// const wasmPath = path.join(
|
96
114
|
// __dirname,
|
97
115
|
// "tree-sitter-files",
|
@@ -223,7 +241,7 @@ async function extractTopLevelDecls(currentFile) {
|
|
223
241
|
throw new Error(`failed to get ast for file ${currentFile}`);
|
224
242
|
}
|
225
243
|
const language = (0, exports.getFullLanguageName)(currentFile);
|
226
|
-
const queryPath = require.resolve(
|
244
|
+
const queryPath = require.resolve(`@jpoly1219/context-extractor/src/tree-sitter-files/queries/relevant-headers-queries/${language}-get-toplevel-headers.scm`);
|
227
245
|
const query = await getQueryForFile(currentFile, queryPath
|
228
246
|
// path.join(
|
229
247
|
// __dirname,
|
@@ -245,7 +263,7 @@ async function extractTopLevelDeclsWithFormatting(currentFile) {
|
|
245
263
|
throw new Error(`failed to get ast for file ${currentFile}`);
|
246
264
|
}
|
247
265
|
const language = (0, exports.getFullLanguageName)(currentFile);
|
248
|
-
const queryPath = require.resolve(
|
266
|
+
const queryPath = require.resolve(`@jpoly1219/context-extractor/src/tree-sitter-files/queries/relevant-headers-queries/${language}-get-toplevel-headers.scm`);
|
249
267
|
const query = await getQueryForFile(currentFile, queryPath
|
250
268
|
// path.join(
|
251
269
|
// __dirname,
|
@@ -1,9 +1,9 @@
|
|
1
|
-
import * as ts from
|
1
|
+
import * as ts from "typescript";
|
2
2
|
import * as fs from "fs";
|
3
3
|
import { LspClient, Location, Range, SymbolInformation } from "../ts-lsp-client-dist/src/main";
|
4
4
|
import { LanguageDriver, TypeSpanAndSourceFile, TypeAnalysis, IDE, TypeSpanAndSourceFileAndAst } from "./types";
|
5
5
|
import { TypeScriptTypeChecker } from "./typescript-type-checker";
|
6
|
-
import Parser from
|
6
|
+
import Parser from "web-tree-sitter";
|
7
7
|
export declare class TypeScriptDriver implements LanguageDriver {
|
8
8
|
ide: IDE;
|
9
9
|
typeChecker: TypeScriptTypeChecker;
|
@@ -47,7 +47,7 @@ class TypeScriptDriver {
|
|
47
47
|
this.typeChecker = new typescript_type_checker_1.TypeScriptTypeChecker();
|
48
48
|
this.ide = ide;
|
49
49
|
if (ide == "vscode") {
|
50
|
-
Promise.resolve().then(() => __importStar(require("./vscode-ide"))).then(module => this.vscodeImport = module);
|
50
|
+
Promise.resolve().then(() => __importStar(require("./vscode-ide"))).then((module) => (this.vscodeImport = module));
|
51
51
|
}
|
52
52
|
// Initialize TypeScript compiler API.
|
53
53
|
this.tsCompilerProgram = this.typeChecker.createTsCompilerProgram(sources, projectRoot);
|
@@ -56,89 +56,101 @@ class TypeScriptDriver {
|
|
56
56
|
async init(lspClient, sketchPath) {
|
57
57
|
if (lspClient) {
|
58
58
|
const capabilities = {
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
59
|
+
textDocument: {
|
60
|
+
codeAction: { dynamicRegistration: true },
|
61
|
+
codeLens: { dynamicRegistration: true },
|
62
|
+
colorProvider: { dynamicRegistration: true },
|
63
|
+
completion: {
|
64
|
+
completionItem: {
|
65
|
+
commitCharactersSupport: true,
|
66
|
+
documentationFormat: ["markdown", "plaintext"],
|
67
|
+
snippetSupport: true,
|
68
68
|
},
|
69
|
-
|
70
|
-
|
69
|
+
completionItemKind: {
|
70
|
+
valueSet: [
|
71
|
+
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
72
|
+
19, 20, 21, 22, 23, 24, 25,
|
73
|
+
],
|
71
74
|
},
|
72
|
-
|
73
|
-
|
75
|
+
contextSupport: true,
|
76
|
+
dynamicRegistration: true,
|
74
77
|
},
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
78
|
+
definition: { dynamicRegistration: true },
|
79
|
+
documentHighlight: { dynamicRegistration: true },
|
80
|
+
documentLink: { dynamicRegistration: true },
|
81
|
+
documentSymbol: {
|
82
|
+
dynamicRegistration: true,
|
83
|
+
symbolKind: {
|
84
|
+
valueSet: [
|
85
|
+
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
86
|
+
19, 20, 21, 22, 23, 24, 25, 26,
|
87
|
+
],
|
88
|
+
},
|
83
89
|
},
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
90
|
+
formatting: { dynamicRegistration: true },
|
91
|
+
hover: {
|
92
|
+
contentFormat: ["markdown", "plaintext"],
|
93
|
+
dynamicRegistration: true,
|
88
94
|
},
|
89
|
-
|
95
|
+
implementation: { dynamicRegistration: true },
|
90
96
|
// 'inlayhint': { 'dynamicRegistration': true },
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
97
|
+
onTypeFormatting: { dynamicRegistration: true },
|
98
|
+
publishDiagnostics: { relatedInformation: true },
|
99
|
+
rangeFormatting: { dynamicRegistration: true },
|
100
|
+
references: { dynamicRegistration: true },
|
101
|
+
rename: { dynamicRegistration: true },
|
102
|
+
signatureHelp: {
|
103
|
+
dynamicRegistration: true,
|
104
|
+
signatureInformation: {
|
105
|
+
documentationFormat: ["markdown", "plaintext"],
|
106
|
+
},
|
99
107
|
},
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
108
|
+
synchronization: {
|
109
|
+
didSave: true,
|
110
|
+
dynamicRegistration: true,
|
111
|
+
willSave: true,
|
112
|
+
willSaveWaitUntil: true,
|
105
113
|
},
|
106
|
-
|
114
|
+
typeDefinition: { dynamicRegistration: true, linkSupport: true },
|
107
115
|
// 'typeHierarchy': { 'dynamicRegistration': true }
|
108
116
|
},
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
117
|
+
workspace: {
|
118
|
+
applyEdit: true,
|
119
|
+
configuration: true,
|
120
|
+
didChangeConfiguration: { dynamicRegistration: true },
|
121
|
+
didChangeWatchedFiles: { dynamicRegistration: true },
|
122
|
+
executeCommand: { dynamicRegistration: true },
|
123
|
+
symbol: {
|
124
|
+
dynamicRegistration: true,
|
125
|
+
symbolKind: {
|
126
|
+
valueSet: [
|
127
|
+
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
128
|
+
19, 20, 21, 22, 23, 24, 25, 26,
|
129
|
+
],
|
130
|
+
},
|
131
|
+
},
|
132
|
+
workspaceEdit: { documentChanges: true },
|
133
|
+
workspaceFolders: true,
|
122
134
|
},
|
123
|
-
|
124
|
-
|
135
|
+
general: {
|
136
|
+
positionEncodings: ["utf-8"],
|
125
137
|
},
|
126
138
|
};
|
127
139
|
const rootPath = path.dirname(sketchPath);
|
128
140
|
const rootUri = `file://${rootPath}`;
|
129
|
-
const workspaceFolders = [{
|
141
|
+
const workspaceFolders = [{ name: "context-extractor", uri: rootUri }];
|
130
142
|
await lspClient.initialize({
|
131
143
|
processId: process.pid,
|
132
144
|
capabilities: capabilities,
|
133
|
-
trace:
|
145
|
+
trace: "off",
|
134
146
|
rootUri: null,
|
135
147
|
workspaceFolders: workspaceFolders,
|
136
148
|
initializationOptions: {
|
137
149
|
disableAutomaticTypingAcquisition: true,
|
138
150
|
preferences: {
|
139
151
|
includeInlayVariableTypeHints: true,
|
140
|
-
}
|
141
|
-
}
|
152
|
+
},
|
153
|
+
},
|
142
154
|
});
|
143
155
|
}
|
144
156
|
}
|
@@ -163,13 +175,12 @@ class TypeScriptDriver {
|
|
163
175
|
// Get the hole's position.
|
164
176
|
const holePattern = /_\(\)/;
|
165
177
|
const firstPatternIndex = injectedSketchFileContent.search(holePattern);
|
166
|
-
const linePosition =
|
178
|
+
const linePosition = injectedSketchFileContent
|
167
179
|
.substring(0, firstPatternIndex)
|
168
|
-
.match(/\n/g)
|
169
|
-
const characterPosition = firstPatternIndex -
|
170
|
-
.split("\n", linePosition)
|
171
|
-
|
172
|
-
.length) - 1;
|
180
|
+
.match(/\n/g).length;
|
181
|
+
const characterPosition = firstPatternIndex -
|
182
|
+
injectedSketchFileContent.split("\n", linePosition).join("\n").length -
|
183
|
+
1;
|
173
184
|
if (lspClient) {
|
174
185
|
// Sync client and server by notifying that
|
175
186
|
// the client has opened all the files
|
@@ -207,15 +218,17 @@ class TypeScriptDriver {
|
|
207
218
|
console.time("hover");
|
208
219
|
const holeHoverResult = await lspClient.hover({
|
209
220
|
textDocument: {
|
210
|
-
uri: injectedSketchFilePath
|
221
|
+
uri: injectedSketchFilePath,
|
211
222
|
},
|
212
223
|
position: {
|
213
224
|
character: characterPosition,
|
214
|
-
line: linePosition
|
215
|
-
}
|
225
|
+
line: linePosition,
|
226
|
+
},
|
216
227
|
});
|
217
228
|
console.timeEnd("hover");
|
218
|
-
const formattedHoverResult = holeHoverResult.contents.value
|
229
|
+
const formattedHoverResult = holeHoverResult.contents.value
|
230
|
+
.split("\n")
|
231
|
+
.reduce((acc, curr) => {
|
219
232
|
if (curr != "" && curr != "```typescript" && curr != "```") {
|
220
233
|
return acc + curr;
|
221
234
|
}
|
@@ -240,18 +253,20 @@ class TypeScriptDriver {
|
|
240
253
|
lspClient.didChange({
|
241
254
|
textDocument: {
|
242
255
|
uri: `file://${injectedSketchFilePath}`,
|
243
|
-
version: 2
|
256
|
+
version: 2,
|
244
257
|
},
|
245
|
-
contentChanges: [
|
246
|
-
|
247
|
-
|
258
|
+
contentChanges: [
|
259
|
+
{
|
260
|
+
text: trueInjectedSketchFileContent,
|
261
|
+
},
|
262
|
+
],
|
248
263
|
});
|
249
264
|
console.timeEnd("didChange");
|
250
265
|
console.time("documentSymbol");
|
251
266
|
const sketchSymbol = await lspClient.documentSymbol({
|
252
267
|
textDocument: {
|
253
268
|
uri: `file://${injectedSketchFilePath}`,
|
254
|
-
}
|
269
|
+
},
|
255
270
|
});
|
256
271
|
console.timeEnd("documentSymbol");
|
257
272
|
return {
|
@@ -265,7 +280,7 @@ class TypeScriptDriver {
|
|
265
280
|
// range: { start: { line: 0, character: 0 }, end: { line: 0, character: 52 } }
|
266
281
|
range: sketchSymbol[0].location.range,
|
267
282
|
source: `file://${injectedSketchFilePath}`,
|
268
|
-
trueHoleFunction: trueHoleFunction
|
283
|
+
trueHoleFunction: trueHoleFunction,
|
269
284
|
};
|
270
285
|
}
|
271
286
|
else {
|
@@ -273,10 +288,12 @@ class TypeScriptDriver {
|
|
273
288
|
filepath: injectedSketchFilePath,
|
274
289
|
position: {
|
275
290
|
line: linePosition,
|
276
|
-
character: characterPosition
|
277
|
-
}
|
291
|
+
character: characterPosition,
|
292
|
+
},
|
278
293
|
});
|
279
|
-
const formattedHoverResult = holeHoverResult.text
|
294
|
+
const formattedHoverResult = holeHoverResult.text
|
295
|
+
.split("\n")
|
296
|
+
.reduce((acc, curr) => {
|
280
297
|
if (curr != "" && curr != "```typescript" && curr != "```") {
|
281
298
|
return acc + curr;
|
282
299
|
}
|
@@ -294,7 +311,7 @@ class TypeScriptDriver {
|
|
294
311
|
const trueInjectedSketchFileContent = `${trueHoleFunction}\n${sketchFileContent}`;
|
295
312
|
fs.writeFileSync(injectedSketchFilePath, trueInjectedSketchFileContent);
|
296
313
|
const sketchSymbol = await this.vscodeImport.VsCode.getDocumentSymbols({
|
297
|
-
filepath: injectedSketchFilePath
|
314
|
+
filepath: injectedSketchFilePath,
|
298
315
|
});
|
299
316
|
return {
|
300
317
|
fullHoverResult: formattedHoverResult,
|
@@ -306,7 +323,7 @@ class TypeScriptDriver {
|
|
306
323
|
holeTypeDefCharPos: "declare function _(): ".length,
|
307
324
|
range: sketchSymbol[0].range,
|
308
325
|
source: `file://${injectedSketchFilePath}`,
|
309
|
-
trueHoleFunction: trueHoleFunction
|
326
|
+
trueHoleFunction: trueHoleFunction,
|
310
327
|
};
|
311
328
|
}
|
312
329
|
}
|
@@ -322,13 +339,12 @@ class TypeScriptDriver {
|
|
322
339
|
// Get the hole's position.
|
323
340
|
const holePattern = /_\(\)/;
|
324
341
|
const firstPatternIndex = injectedSketchFileContent.search(holePattern);
|
325
|
-
const linePosition =
|
342
|
+
const linePosition = injectedSketchFileContent
|
326
343
|
.substring(0, firstPatternIndex)
|
327
|
-
.match(/\n/g)
|
328
|
-
const characterPosition = firstPatternIndex -
|
329
|
-
.split("\n", linePosition)
|
330
|
-
|
331
|
-
.length) - 1;
|
344
|
+
.match(/\n/g).length;
|
345
|
+
const characterPosition = firstPatternIndex -
|
346
|
+
injectedSketchFileContent.split("\n", linePosition).join("\n").length -
|
347
|
+
1;
|
332
348
|
// const sourceFile = ts.createSourceFile("sample.ts", injectedSketchFileContent, ts.ScriptTarget.Latest, true);
|
333
349
|
const sourceFile = this.tsCompilerProgram.getSourceFile(injectedSketchFilePath);
|
334
350
|
const position = ts.getPositionOfLineAndCharacter(sourceFile, linePosition, characterPosition);
|
@@ -368,10 +384,13 @@ class TypeScriptDriver {
|
|
368
384
|
characterPosition: characterPosition,
|
369
385
|
holeTypeDefLinePos: 0,
|
370
386
|
holeTypeDefCharPos: "declare function _(): ".length,
|
371
|
-
range: {
|
387
|
+
range: {
|
388
|
+
start: { line: 0, character: 0 },
|
389
|
+
end: { line: 0, character: 52 },
|
390
|
+
},
|
372
391
|
// range: (sketchSymbol![0] as SymbolInformation).location.range,
|
373
392
|
source: `file://${injectedSketchFilePath}`,
|
374
|
-
trueHoleFunction: trueHoleFunction
|
393
|
+
trueHoleFunction: trueHoleFunction,
|
375
394
|
};
|
376
395
|
}
|
377
396
|
async getHoleContextWithTreesitter(sketchFilePath, cursorPosition, logStream) {
|
@@ -382,7 +401,10 @@ class TypeScriptDriver {
|
|
382
401
|
const sketchFileContent = fs.readFileSync(sketchFilePath, "utf8");
|
383
402
|
const injectedContent = (0, utils_1.insertAtPosition)(sketchFileContent, cursorPosition, "@;");
|
384
403
|
// The hole's position is cursorPosition.
|
385
|
-
const snip = (0, utils_1.extractSnippet)(injectedContent, cursorPosition, {
|
404
|
+
const snip = (0, utils_1.extractSnippet)(injectedContent, cursorPosition, {
|
405
|
+
line: cursorPosition.line,
|
406
|
+
character: cursorPosition.character + 2,
|
407
|
+
});
|
386
408
|
// console.log(snip)
|
387
409
|
// Use treesitter to parse.
|
388
410
|
const ast = await (0, ast_1.getAst)(sketchFilePath, injectedContent);
|
@@ -390,7 +412,7 @@ class TypeScriptDriver {
|
|
390
412
|
throw new Error("failed to get ast");
|
391
413
|
}
|
392
414
|
const language = (0, tree_sitter_1.getFullLanguageName)(sketchFilePath);
|
393
|
-
const queryPath = require.resolve(
|
415
|
+
const queryPath = require.resolve(`@jpoly1219/context-extractor/src/tree-sitter-files/queries/hole-queries/${language}.scm`);
|
394
416
|
const query = await (0, tree_sitter_1.getQueryForFile)(sketchFilePath, queryPath
|
395
417
|
// path.join(
|
396
418
|
// __dirname,
|
@@ -423,10 +445,13 @@ class TypeScriptDriver {
|
|
423
445
|
characterPosition: 0,
|
424
446
|
holeTypeDefLinePos: 0,
|
425
447
|
holeTypeDefCharPos: "declare function _(): ".length,
|
426
|
-
range: {
|
448
|
+
range: {
|
449
|
+
start: { line: 0, character: 0 },
|
450
|
+
end: { line: 0, character: 52 },
|
451
|
+
},
|
427
452
|
// range: (sketchSymbol![0] as SymbolInformation).location.range,
|
428
453
|
source: `file://${sketchFilePath}`,
|
429
|
-
trueHoleFunction: ""
|
454
|
+
trueHoleFunction: "",
|
430
455
|
};
|
431
456
|
for (const c of captures) {
|
432
457
|
const { name, node } = c;
|
@@ -448,7 +473,7 @@ class TypeScriptDriver {
|
|
448
473
|
end: {
|
449
474
|
line: node.endPosition.row,
|
450
475
|
character: node.endPosition.column,
|
451
|
-
}
|
476
|
+
},
|
452
477
|
};
|
453
478
|
}
|
454
479
|
}
|
@@ -461,32 +486,39 @@ class TypeScriptDriver {
|
|
461
486
|
// outputFile: fs.WriteStream,
|
462
487
|
) {
|
463
488
|
if (!foundSoFar.has(typeName)) {
|
464
|
-
foundSoFar.set(typeName, {
|
489
|
+
foundSoFar.set(typeName, {
|
490
|
+
typeSpan: fullHoverResult,
|
491
|
+
sourceFile: currentFile.slice(7),
|
492
|
+
});
|
465
493
|
// outputFile.write(`${fullHoverResult};\n`);
|
466
494
|
const content = fs.readFileSync(currentFile.slice(7), "utf8");
|
467
495
|
for (let linePos = startLine; linePos <= endLine; ++linePos) {
|
468
496
|
// TODO: use a platform-agnostic command here
|
469
|
-
const numOfCharsInLine = parseInt((0, child_process_1.execSync)(`wc -m <<< "${content.split("\n")[linePos]}"`, {
|
497
|
+
const numOfCharsInLine = parseInt((0, child_process_1.execSync)(`wc -m <<< "${content.split("\n")[linePos]}"`, {
|
498
|
+
shell: "/bin/bash",
|
499
|
+
}).toString());
|
470
500
|
const numOfCharsInLine2 = content.split("\n")[linePos].length;
|
471
|
-
const numOfCharsInLine3 = [...content.split("\n")[linePos]].map(c => c.codePointAt(0)).length;
|
501
|
+
const numOfCharsInLine3 = [...content.split("\n")[linePos]].map((c) => c.codePointAt(0)).length;
|
472
502
|
// console.log(numOfCharsInLine === numOfCharsInLine2, content.split("\n")[linePos], numOfCharsInLine, numOfCharsInLine2, numOfCharsInLine3)
|
473
503
|
// console.time(`===loop ${content.split("\n")[linePos]}===`);
|
474
504
|
for (let charPos = 0; charPos < numOfCharsInLine2; ++charPos) {
|
475
505
|
try {
|
476
506
|
const typeDefinitionResult = await lspClient.typeDefinition({
|
477
507
|
textDocument: {
|
478
|
-
uri: currentFile
|
508
|
+
uri: currentFile,
|
479
509
|
},
|
480
510
|
position: {
|
481
511
|
character: charPos,
|
482
|
-
line: linePos
|
483
|
-
}
|
512
|
+
line: linePos,
|
513
|
+
},
|
484
514
|
});
|
485
515
|
// if (content.split("\n")[linePos] === `type Action = AddBooking | CancelBooking | ClearBookings;`) {
|
486
516
|
// console.dir(typeDefinitionResult, { depth: null })
|
487
517
|
// console.log(charPos)
|
488
518
|
// }
|
489
|
-
if (typeDefinitionResult &&
|
519
|
+
if (typeDefinitionResult &&
|
520
|
+
typeDefinitionResult instanceof Array &&
|
521
|
+
typeDefinitionResult.length != 0) {
|
490
522
|
const tdResultStr = JSON.stringify(typeDefinitionResult);
|
491
523
|
if (!foundTypeDefinitions.has(tdResultStr)) {
|
492
524
|
foundTypeDefinitions.set(tdResultStr, typeDefinitionResult);
|
@@ -501,17 +533,18 @@ class TypeScriptDriver {
|
|
501
533
|
documentSymbolResult = foundSymbols.get(tdUri);
|
502
534
|
}
|
503
535
|
else {
|
504
|
-
documentSymbolResult = await lspClient.documentSymbol({
|
536
|
+
documentSymbolResult = (await lspClient.documentSymbol({
|
505
537
|
textDocument: {
|
506
|
-
uri: typeDefinitionResult[0].uri
|
507
|
-
}
|
508
|
-
});
|
538
|
+
uri: typeDefinitionResult[0].uri,
|
539
|
+
},
|
540
|
+
}));
|
509
541
|
foundSymbols.set(tdUri, documentSymbolResult);
|
510
542
|
}
|
511
543
|
// console.timeEnd("docSymbol")
|
512
544
|
// console.time("dsMap")
|
513
545
|
const dsMap = documentSymbolResult.reduce((m, obj) => {
|
514
|
-
m.set(obj.location.range.start.line, obj.location
|
546
|
+
m.set(obj.location.range.start.line, obj.location
|
547
|
+
.range);
|
515
548
|
return m;
|
516
549
|
}, new Map());
|
517
550
|
// console.timeEnd("dsMap")
|
@@ -526,7 +559,9 @@ class TypeScriptDriver {
|
|
526
559
|
// }, new Map<number, Range>());
|
527
560
|
const matchingSymbolRange = dsMap.get(typeDefinitionResult[0].range.start.line);
|
528
561
|
if (matchingSymbolRange) {
|
529
|
-
const snippetInRange = (0, utils_1.extractSnippet)(fs
|
562
|
+
const snippetInRange = (0, utils_1.extractSnippet)(fs
|
563
|
+
.readFileSync(typeDefinitionResult[0].uri.slice(7))
|
564
|
+
.toString("utf8"), matchingSymbolRange.start, matchingSymbolRange.end);
|
530
565
|
// TODO: this can potentially be its own method. the driver would require some way to get type context.
|
531
566
|
// potentially, this type checker can be its own class.
|
532
567
|
const identifier = this.typeChecker.getIdentifierFromDecl(snippetInRange);
|
@@ -577,7 +612,10 @@ class TypeScriptDriver {
|
|
577
612
|
// Split the type span into identifiers, where each include the text, line number, and character range.
|
578
613
|
// For each identifier, invoke go to type definition.
|
579
614
|
if (!foundSoFar.has(typeName)) {
|
580
|
-
foundSoFar.set(typeName, {
|
615
|
+
foundSoFar.set(typeName, {
|
616
|
+
typeSpan: fullHoverResult,
|
617
|
+
sourceFile: currentFile.slice(7),
|
618
|
+
});
|
581
619
|
// console.log(fullHoverResult)
|
582
620
|
const identifiers = this.typeChecker.extractIdentifiers(fullHoverResult);
|
583
621
|
// DEBUG: REMOVE
|
@@ -599,12 +637,12 @@ class TypeScriptDriver {
|
|
599
637
|
// const start = performance.now()
|
600
638
|
const typeDefinitionResult = await lspClient.typeDefinition({
|
601
639
|
textDocument: {
|
602
|
-
uri: currentFile
|
640
|
+
uri: currentFile,
|
603
641
|
},
|
604
642
|
position: {
|
605
643
|
character: identifier.start,
|
606
|
-
line: startLine + identifier.line - 1 // startLine is already 1-indexed
|
607
|
-
}
|
644
|
+
line: startLine + identifier.line - 1, // startLine is already 1-indexed
|
645
|
+
},
|
608
646
|
});
|
609
647
|
// const end = performance.now()
|
610
648
|
// console.log(end - start)
|
@@ -612,7 +650,9 @@ class TypeScriptDriver {
|
|
612
650
|
// console.log(identifier)
|
613
651
|
// console.dir(typeDefinitionResult, { depth: null })
|
614
652
|
// }
|
615
|
-
if (typeDefinitionResult &&
|
653
|
+
if (typeDefinitionResult &&
|
654
|
+
typeDefinitionResult instanceof Array &&
|
655
|
+
typeDefinitionResult.length != 0) {
|
616
656
|
const tdLocation = typeDefinitionResult[0];
|
617
657
|
let content = "";
|
618
658
|
if (foundContents.has(tdLocation.uri.slice(7))) {
|
@@ -654,7 +694,10 @@ class TypeScriptDriver {
|
|
654
694
|
else {
|
655
695
|
// TODO: Test this.
|
656
696
|
if (!foundSoFar.has(typeName)) {
|
657
|
-
foundSoFar.set(typeName, {
|
697
|
+
foundSoFar.set(typeName, {
|
698
|
+
typeSpan: fullHoverResult,
|
699
|
+
sourceFile: currentFile.slice(7),
|
700
|
+
});
|
658
701
|
const identifiers = this.typeChecker.extractIdentifiers(fullHoverResult);
|
659
702
|
for (const identifier of identifiers) {
|
660
703
|
if (!foundSoFar.has(identifier.name)) {
|
@@ -663,8 +706,8 @@ class TypeScriptDriver {
|
|
663
706
|
filepath: currentFile,
|
664
707
|
position: {
|
665
708
|
line: startLine + identifier.line - 1,
|
666
|
-
character: identifier.start
|
667
|
-
}
|
709
|
+
character: identifier.start,
|
710
|
+
},
|
668
711
|
});
|
669
712
|
if (typeDefinitionResult.length != 0) {
|
670
713
|
const tdLocation = typeDefinitionResult[0];
|
@@ -717,7 +760,10 @@ class TypeScriptDriver {
|
|
717
760
|
// Split the type span into identifiers, where each include the text, line number, and character range.
|
718
761
|
// For each identifier, invoke go to type definition.
|
719
762
|
if (!foundSoFar.has(typeName)) {
|
720
|
-
foundSoFar.set(typeName, {
|
763
|
+
foundSoFar.set(typeName, {
|
764
|
+
typeSpan: fullHoverResult,
|
765
|
+
sourceFile: currentFile.slice(7),
|
766
|
+
});
|
721
767
|
const identifiers = this.typeChecker.extractIdentifiers(fullHoverResult);
|
722
768
|
const sourceFile = this.tsCompilerProgram.getSourceFile(currentFile.slice(7));
|
723
769
|
for (const identifier of identifiers) {
|
@@ -742,7 +788,9 @@ class TypeScriptDriver {
|
|
742
788
|
}
|
743
789
|
function findIdentifierAtPosition(sourceFile, position) {
|
744
790
|
function find(node) {
|
745
|
-
if (ts.isIdentifier(node) &&
|
791
|
+
if (ts.isIdentifier(node) &&
|
792
|
+
position >= node.getStart() &&
|
793
|
+
position <= node.getEnd()) {
|
746
794
|
return node;
|
747
795
|
}
|
748
796
|
return ts.forEachChild(node, find);
|
@@ -820,9 +868,13 @@ class TypeScriptDriver {
|
|
820
868
|
if (!ast) {
|
821
869
|
throw new Error(`failed to get ast for file ${currentFile}`);
|
822
870
|
}
|
823
|
-
foundSoFar.set(typeName, {
|
871
|
+
foundSoFar.set(typeName, {
|
872
|
+
typeSpan: fullHoverResult,
|
873
|
+
sourceFile: currentFile.slice(7),
|
874
|
+
ast: ast,
|
875
|
+
});
|
824
876
|
const language = (0, tree_sitter_1.getFullLanguageName)(currentFile);
|
825
|
-
const queryPath = require.resolve(
|
877
|
+
const queryPath = require.resolve(`@jpoly1219/context-extractor/src/tree-sitter-files/queries/relevant-types-queries/${language}-extract-identifiers.scm`);
|
826
878
|
const query = await (0, tree_sitter_1.getQueryForFile)(currentFile, queryPath
|
827
879
|
// path.join(
|
828
880
|
// __dirname,
|
@@ -842,14 +894,16 @@ class TypeScriptDriver {
|
|
842
894
|
try {
|
843
895
|
const typeDefinitionResult = await lspClient.typeDefinition({
|
844
896
|
textDocument: {
|
845
|
-
uri: currentFile
|
897
|
+
uri: currentFile,
|
846
898
|
},
|
847
899
|
position: {
|
848
900
|
character: node.startPosition.column,
|
849
|
-
line: startLine + node.startPosition.row
|
850
|
-
}
|
901
|
+
line: startLine + node.startPosition.row,
|
902
|
+
},
|
851
903
|
});
|
852
|
-
if (typeDefinitionResult &&
|
904
|
+
if (typeDefinitionResult &&
|
905
|
+
typeDefinitionResult instanceof Array &&
|
906
|
+
typeDefinitionResult.length != 0) {
|
853
907
|
const tdLocation = typeDefinitionResult[0];
|
854
908
|
let content = "";
|
855
909
|
if (foundContents.has(tdLocation.uri.slice(7))) {
|
@@ -897,9 +951,13 @@ class TypeScriptDriver {
|
|
897
951
|
if (!ast) {
|
898
952
|
throw new Error(`failed to get ast for file ${currentFile}`);
|
899
953
|
}
|
900
|
-
foundSoFar.set(typeName, {
|
954
|
+
foundSoFar.set(typeName, {
|
955
|
+
typeSpan: fullHoverResult,
|
956
|
+
sourceFile: currentFile.slice(7),
|
957
|
+
ast: ast,
|
958
|
+
});
|
901
959
|
const language = (0, tree_sitter_1.getFullLanguageName)(currentFile);
|
902
|
-
const queryPath = require.resolve(
|
960
|
+
const queryPath = require.resolve(`@jpoly1219/context-extractor/src/tree-sitter-files/queries/relevant-headers-queries/${language}-extract-identifiers.scm`);
|
903
961
|
const query = await (0, tree_sitter_1.getQueryForFile)(currentFile, queryPath
|
904
962
|
// path.join(
|
905
963
|
// __dirname,
|
@@ -920,8 +978,8 @@ class TypeScriptDriver {
|
|
920
978
|
filepath: currentFile,
|
921
979
|
position: {
|
922
980
|
character: node.startPosition.column,
|
923
|
-
line: startLine + node.startPosition.row
|
924
|
-
}
|
981
|
+
line: startLine + node.startPosition.row,
|
982
|
+
},
|
925
983
|
});
|
926
984
|
if (typeDefinitionResult.length != 0) {
|
927
985
|
const tdLocation = typeDefinitionResult[0];
|
@@ -1106,14 +1164,16 @@ class TypeScriptDriver {
|
|
1106
1164
|
this.generateTargetTypesHelper(relevantTypes, rettype.text, targetTypes, program, checker);
|
1107
1165
|
}
|
1108
1166
|
else if (this.typeChecker.isTuple2(typeAnalysisResult)) {
|
1109
|
-
typeAnalysisResult.constituents.forEach(constituent => {
|
1167
|
+
typeAnalysisResult.constituents.forEach((constituent) => {
|
1110
1168
|
targetTypes.add(constituent.text);
|
1111
1169
|
this.generateTargetTypesHelper(relevantTypes, constituent.text, targetTypes, program, checker);
|
1112
1170
|
});
|
1113
1171
|
}
|
1114
1172
|
else {
|
1115
1173
|
if (relevantTypes.has(currType)) {
|
1116
|
-
const definition = relevantTypes
|
1174
|
+
const definition = relevantTypes
|
1175
|
+
.get(currType)
|
1176
|
+
.typeSpan.split(" = ")[1];
|
1117
1177
|
this.generateTargetTypesHelper(relevantTypes, definition, targetTypes, program, checker);
|
1118
1178
|
}
|
1119
1179
|
}
|
@@ -1161,7 +1221,7 @@ class TypeScriptDriver {
|
|
1161
1221
|
else {
|
1162
1222
|
typeAnalysisResult = foundTypeAnalysisResults.get(source + ":" + typeSpan);
|
1163
1223
|
}
|
1164
|
-
targetTypes.forEach(typ => {
|
1224
|
+
targetTypes.forEach((typ) => {
|
1165
1225
|
if (this.isTypeEquivalent(typeSpan, typ, relevantTypes, foundNormalForms, program, checker)) {
|
1166
1226
|
// NOTE: This checks for dupes. ctx is an object so you need to check for each field.
|
1167
1227
|
// relevantContext.add({ typeSpan: line, sourceFile: source });
|
@@ -1173,7 +1233,7 @@ class TypeScriptDriver {
|
|
1173
1233
|
this.extractRelevantHeadersHelper(rettype.text, targetTypes, relevantTypes, relevantContext, line, source, relevantContextMap, tag, trace, foundNormalForms, foundTypeAnalysisResults, program, checker);
|
1174
1234
|
}
|
1175
1235
|
else if (this.typeChecker.isTuple2(typeAnalysisResult)) {
|
1176
|
-
typeAnalysisResult.constituents.forEach(constituent => {
|
1236
|
+
typeAnalysisResult.constituents.forEach((constituent) => {
|
1177
1237
|
this.extractRelevantHeadersHelper(constituent.text, targetTypes, relevantTypes, relevantContext, line, source, relevantContextMap, tag, trace, foundNormalForms, foundTypeAnalysisResults, program, checker);
|
1178
1238
|
});
|
1179
1239
|
}
|
@@ -1239,10 +1299,12 @@ class TypeScriptDriver {
|
|
1239
1299
|
// console.log(`isObject: ${typeSpan}`)
|
1240
1300
|
const elements = typeSpan.slice(1, typeSpan.length - 2).split(";");
|
1241
1301
|
normalForm += "{";
|
1242
|
-
elements.forEach(element => {
|
1302
|
+
elements.forEach((element) => {
|
1243
1303
|
if (element !== "") {
|
1244
1304
|
const kv = element.split(": ");
|
1245
|
-
normalForm += kv[0].slice(1, kv[0].length),
|
1305
|
+
(normalForm += kv[0].slice(1, kv[0].length)),
|
1306
|
+
": ",
|
1307
|
+
this.normalize(kv[1], relevantTypes);
|
1246
1308
|
normalForm += "; ";
|
1247
1309
|
}
|
1248
1310
|
});
|
@@ -1320,10 +1382,12 @@ class TypeScriptDriver {
|
|
1320
1382
|
// console.log(`isObject: ${typeSpan}`)
|
1321
1383
|
const elements = typeSpan.slice(1, typeSpan.length - 2).split(";");
|
1322
1384
|
normalForm += "{";
|
1323
|
-
elements.forEach(element => {
|
1385
|
+
elements.forEach((element) => {
|
1324
1386
|
if (element !== "") {
|
1325
1387
|
const kv = element.split(": ");
|
1326
|
-
normalForm += kv[0].slice(1, kv[0].length),
|
1388
|
+
(normalForm += kv[0].slice(1, kv[0].length)),
|
1389
|
+
": ",
|
1390
|
+
this.normalize2(kv[1], relevantTypes, program, checker);
|
1327
1391
|
normalForm += "; ";
|
1328
1392
|
}
|
1329
1393
|
});
|
@@ -1378,7 +1442,9 @@ class TypeScriptDriver {
|
|
1378
1442
|
if (!relevantTypes.has(analysisResult.text)) {
|
1379
1443
|
return typeSpan;
|
1380
1444
|
}
|
1381
|
-
const typ = relevantTypes
|
1445
|
+
const typ = relevantTypes
|
1446
|
+
.get(analysisResult.text)
|
1447
|
+
.typeSpan.split(" = ")[1];
|
1382
1448
|
if (typ === undefined) {
|
1383
1449
|
return typeSpan;
|
1384
1450
|
}
|
@@ -1405,7 +1471,7 @@ class TypeScriptDriver {
|
|
1405
1471
|
else {
|
1406
1472
|
typeAnalysisResult = foundTypeAnalysisResults.get(source + ":" + typeSpan);
|
1407
1473
|
}
|
1408
|
-
targetTypes.forEach(typ => {
|
1474
|
+
targetTypes.forEach((typ) => {
|
1409
1475
|
// if (declText.includes("getBookings")) {
|
1410
1476
|
// if (declText.slice(0, 11) === "getBookings") {
|
1411
1477
|
// console.log("innermost", declText, "-=-=-", typeSpan)
|
@@ -1424,7 +1490,7 @@ class TypeScriptDriver {
|
|
1424
1490
|
foundTypeAnalysisResults;
|
1425
1491
|
}
|
1426
1492
|
else if (this.typeChecker.isTuple2(typeAnalysisResult)) {
|
1427
|
-
typeAnalysisResult.constituents.forEach(constituent => {
|
1493
|
+
typeAnalysisResult.constituents.forEach((constituent) => {
|
1428
1494
|
this.extractRelevantHeadersHelper2(declText, constituent.text, targetTypes, relevantTypes, relevantContext, source, relevantContextMap, trace, foundNormalForms, foundTypeAnalysisResults, program, checker);
|
1429
1495
|
});
|
1430
1496
|
}
|
@@ -1454,8 +1520,8 @@ class TypeScriptDriver {
|
|
1454
1520
|
// pattern 0 is let/const, 1 is var, 2 is fun
|
1455
1521
|
// if (!seenDecls.has(JSON.stringify()) {
|
1456
1522
|
const originalDeclText = tld.pattern === 2
|
1457
|
-
? tld.captures.find(d => d.name === "top.fn.decl").node.text
|
1458
|
-
: tld.captures.find(d => d.name === "top.var.decl").node.text;
|
1523
|
+
? tld.captures.find((d) => d.name === "top.fn.decl").node.text
|
1524
|
+
: tld.captures.find((d) => d.name === "top.var.decl").node.text;
|
1459
1525
|
if (tld.pattern === 2) {
|
1460
1526
|
// build a type span
|
1461
1527
|
const funcType = (0, tree_sitter_1.extractFunctionTypeFromDecl)(tld);
|
@@ -1475,7 +1541,7 @@ class TypeScriptDriver {
|
|
1475
1541
|
await this.extractRelevantHeadersWithTreesitterHelper(originalDeclText, baseNode, targetTypes, relevantTypes, relevantContext, relevantContextMap, foundNormalForms, source);
|
1476
1542
|
}
|
1477
1543
|
else {
|
1478
|
-
const varTypNode = tld.captures.find(d => d.name === "top.var.type").node;
|
1544
|
+
const varTypNode = tld.captures.find((d) => d.name === "top.var.type").node;
|
1479
1545
|
await this.extractRelevantHeadersWithTreesitterHelper(originalDeclText, varTypNode, targetTypes, relevantTypes, relevantContext, relevantContextMap, foundNormalForms, source);
|
1480
1546
|
}
|
1481
1547
|
}
|
@@ -1492,7 +1558,7 @@ class TypeScriptDriver {
|
|
1492
1558
|
relevantContextMap.set(JSON.stringify(ctx), ctx);
|
1493
1559
|
}
|
1494
1560
|
if (node.type === "function_type") {
|
1495
|
-
const retTypeNode = node.namedChildren.find(c => c && c.type === "return_type");
|
1561
|
+
const retTypeNode = node.namedChildren.find((c) => c && c.type === "return_type");
|
1496
1562
|
if (retTypeNode) {
|
1497
1563
|
this.extractRelevantHeadersWithTreesitterHelper(originalDeclText, retTypeNode, targetTypes, relevantTypes, relevantContext, relevantContextMap, foundNormalForms, source);
|
1498
1564
|
}
|
@@ -1526,12 +1592,23 @@ class TypeScriptDriver {
|
|
1526
1592
|
return targetTypes;
|
1527
1593
|
}
|
1528
1594
|
unwrapToBaseType(node) {
|
1529
|
-
if ([
|
1595
|
+
if ([
|
1596
|
+
"function_type",
|
1597
|
+
"tuple_type",
|
1598
|
+
"type_identifier",
|
1599
|
+
"predefined_type",
|
1600
|
+
].includes(node.type)) {
|
1530
1601
|
return node;
|
1531
1602
|
}
|
1532
1603
|
for (const child of node.namedChildren) {
|
1533
1604
|
const unwrapped = this.unwrapToBaseType(child);
|
1534
|
-
if (unwrapped !== child ||
|
1605
|
+
if (unwrapped !== child ||
|
1606
|
+
[
|
1607
|
+
"function_type",
|
1608
|
+
"tuple_type",
|
1609
|
+
"type_identifier",
|
1610
|
+
"predefined_type",
|
1611
|
+
].includes(unwrapped.type)) {
|
1535
1612
|
return unwrapped;
|
1536
1613
|
}
|
1537
1614
|
}
|
@@ -1616,16 +1693,17 @@ class TypeScriptDriver {
|
|
1616
1693
|
case "function_type": {
|
1617
1694
|
const params = node.child(0); // formal_parameters
|
1618
1695
|
const returnType = node.childForFieldName("type") || node.namedChildren[1]; // function_type → parameters, =>, return
|
1619
|
-
const paramTypes = (params === null || params === void 0 ? void 0 : params.namedChildren.map(param => this.normalizeWithTreesitter(param.childForFieldName("type") ||
|
1696
|
+
const paramTypes = (params === null || params === void 0 ? void 0 : params.namedChildren.map((param) => this.normalizeWithTreesitter(param.childForFieldName("type") ||
|
1697
|
+
param.namedChildren.at(-1), relevantTypes)).join(", ")) || "";
|
1620
1698
|
const ret = this.normalizeWithTreesitter(returnType, relevantTypes);
|
1621
1699
|
return `(${paramTypes}) => ${ret}`;
|
1622
1700
|
}
|
1623
1701
|
case "tuple_type": {
|
1624
|
-
const elements = node.namedChildren.map(c => this.normalizeWithTreesitter(c, relevantTypes));
|
1702
|
+
const elements = node.namedChildren.map((c) => this.normalizeWithTreesitter(c, relevantTypes));
|
1625
1703
|
return `[${elements.join(", ")}]`;
|
1626
1704
|
}
|
1627
1705
|
case "union_type": {
|
1628
|
-
const parts = node.namedChildren.map(c => this.normalizeWithTreesitter(c, relevantTypes));
|
1706
|
+
const parts = node.namedChildren.map((c) => this.normalizeWithTreesitter(c, relevantTypes));
|
1629
1707
|
return parts.join(" | ");
|
1630
1708
|
}
|
1631
1709
|
case "type_identifier": {
|
@@ -1635,7 +1713,8 @@ class TypeScriptDriver {
|
|
1635
1713
|
// Parse the alias's type span
|
1636
1714
|
const wrapped = `type __TMP = ${alias};`;
|
1637
1715
|
const tree = await (0, ast_1.getAst)("file.ts", wrapped);
|
1638
|
-
const valueNode = (_a = tree.rootNode
|
1716
|
+
const valueNode = (_a = tree.rootNode
|
1717
|
+
.descendantsOfType("type_alias_declaration")[0]) === null || _a === void 0 ? void 0 : _a.childForFieldName("value");
|
1639
1718
|
return this.normalizeWithTreesitter(valueNode, relevantTypes);
|
1640
1719
|
}
|
1641
1720
|
case "predefined_type":
|