@jpoly1219/context-extractor 0.2.8 → 0.2.10
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/app.d.ts +7 -3
- package/dist/src/app.js +304 -101
- package/dist/src/ast.d.ts +6 -0
- package/dist/src/ast.js +80 -0
- package/dist/src/codeql.js +17 -7
- package/dist/src/constants.js +17 -7
- package/dist/src/core.d.ts +0 -1
- package/dist/src/core.js +17 -7
- package/dist/src/main.d.ts +8 -2
- package/dist/src/main.js +51 -13
- package/dist/src/ocaml-driver.d.ts +55 -5
- package/dist/src/ocaml-driver.js +295 -190
- package/dist/src/ocaml-utils/_build/default/test_parser.bc.cjs +194658 -0
- package/dist/src/runner.js +118 -3
- package/dist/src/tree-sitter-files/queries/hole-queries/typescript.scm +36 -0
- package/dist/src/tree-sitter-files/queries/relevant-headers-queries/typescript-get-toplevel-headers.scm +22 -0
- package/dist/src/tree-sitter-files/queries/relevant-types-queries/typescript-extract-identifiers.scm +10 -0
- package/dist/src/tree-sitter-files/queries/relevant-types-queries/typescript-find-typedecl-given-typeidentifier.scm +11 -0
- package/dist/src/tree-sitter-files/wasms/tree-sitter-ocaml.wasm +0 -0
- package/dist/src/tree-sitter-files/wasms/tree-sitter-typescript.wasm +0 -0
- package/dist/src/tree-sitter-files/wasms/tree-sitter.wasm +0 -0
- package/dist/src/tree-sitter.d.ts +40 -0
- package/dist/src/tree-sitter.js +334 -0
- package/dist/src/types.d.ts +79 -9
- package/dist/src/types.js +1 -6
- package/dist/src/typescript-driver.d.ts +81 -13
- package/dist/src/typescript-driver.js +1150 -237
- package/dist/src/typescript-type-checker.d.ts +6 -2
- package/dist/src/typescript-type-checker.js +222 -10
- package/dist/src/utils.d.ts +11 -1
- package/dist/src/utils.js +87 -10
- package/dist/src/vscode-ide.d.ts +29 -0
- package/dist/src/vscode-ide.js +161 -0
- package/package.json +12 -6
package/dist/src/runner.js
CHANGED
@@ -1,15 +1,118 @@
|
|
1
1
|
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
+
}) : function(o, v) {
|
16
|
+
o["default"] = v;
|
17
|
+
});
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
19
|
+
var ownKeys = function(o) {
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
21
|
+
var ar = [];
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
23
|
+
return ar;
|
24
|
+
};
|
25
|
+
return ownKeys(o);
|
26
|
+
};
|
27
|
+
return function (mod) {
|
28
|
+
if (mod && mod.__esModule) return mod;
|
29
|
+
var result = {};
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
31
|
+
__setModuleDefault(result, mod);
|
32
|
+
return result;
|
33
|
+
};
|
34
|
+
})();
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
36
|
const main_1 = require("./main");
|
4
|
-
const
|
37
|
+
const pprof = __importStar(require("pprof"));
|
38
|
+
const fs = __importStar(require("fs"));
|
5
39
|
// extract("/home/jacob/projects/context-extractor/targets/todo/sketch.ts").then(r => console.log("todo\n", r));
|
6
40
|
// extract("/home/jacob/projects/context-extractor/targets/playlist/sketch.ts").then(r => console.log("playlist\n", r));
|
7
41
|
// extract("/home/jacob/projects/context-extractor/targets/passwords/sketch.ts").then(r => console.log("passwords\n", r));
|
8
42
|
// extract("/home/jacob/projects/context-extractor/targets/booking/sketch.ts").then(r => console.log("booking\n", r));
|
9
43
|
// extract("/home/jacob/projects/context-extractor/targets/emojipaint/sketch.ts").then(r => console.log("emojipaint\n", r));
|
10
44
|
(async () => {
|
45
|
+
const profile = await pprof.time.start(10000); // Collect for 10s
|
11
46
|
try {
|
12
47
|
let x;
|
48
|
+
x = await (0, main_1.extractContext)("typescript", "/home/jacob/projects/context-extractor/targets/booking/sketch.ts", "/home/jacob/projects/context-extractor/targets/booking/", "standalone", { line: 3, character: 56 });
|
49
|
+
console.dir(x, { depth: null });
|
50
|
+
}
|
51
|
+
catch (err) {
|
52
|
+
console.log("top level err: ", err);
|
53
|
+
}
|
54
|
+
finally {
|
55
|
+
const buf = await pprof.encode(profile());
|
56
|
+
fs.writeFile('wall.pb.gz', buf, (err) => {
|
57
|
+
if (err)
|
58
|
+
throw err;
|
59
|
+
});
|
60
|
+
}
|
61
|
+
})();
|
62
|
+
(async () => {
|
63
|
+
// try {
|
64
|
+
const app = (0, main_1.spawnApp)("typescript",
|
65
|
+
// "/home/jacob/projects/context-extractor/targets/vscode/src/main.ts",
|
66
|
+
// "/home/jacob/projects/context-extractor/targets/vscode/",
|
67
|
+
"/home/jacob/projects/context-extractor/targets/booking/sketch.ts", "/home/jacob/projects/context-extractor/targets/booking/", "standalone", { line: 3, character: 56 });
|
68
|
+
const x = await (0, main_1.extractContextWithReuse)(app, 0);
|
69
|
+
console.dir(x, { depth: null });
|
70
|
+
// for (let i = 0; i < 11; ++i) {
|
71
|
+
//
|
72
|
+
// await (async (ms: number) => new Promise((r) => setTimeout(r, ms)))(2000)
|
73
|
+
//
|
74
|
+
// try {
|
75
|
+
// console.log(`loop ${i}`)
|
76
|
+
// let start = performance.now();
|
77
|
+
// const x = await extractContextWithReuse(app, i);
|
78
|
+
// let end = performance.now();
|
79
|
+
// console.log(end - start);
|
80
|
+
// // console.dir(x, { depth: null })
|
81
|
+
// } catch (err) {
|
82
|
+
// console.log("error!")
|
83
|
+
// continue;
|
84
|
+
// }
|
85
|
+
//
|
86
|
+
// }
|
87
|
+
app.close();
|
88
|
+
// } catch (err) {
|
89
|
+
// console.error(err)
|
90
|
+
// }
|
91
|
+
});
|
92
|
+
(async () => {
|
93
|
+
// const profile = await pprof.time.start(10000); // Collect for 10s
|
94
|
+
try {
|
95
|
+
let x;
|
96
|
+
// x = await extractContext(
|
97
|
+
// Language.TypeScript,
|
98
|
+
// "/home/jacob/projects/context-extractor/targets/vscode/src/main.ts",
|
99
|
+
// "/home/jacob/projects/context-extractor/targets/vscode/",
|
100
|
+
// IDE.Standalone
|
101
|
+
// )
|
102
|
+
// console.dir(x, { depth: null })
|
103
|
+
// x = await extractContext(
|
104
|
+
// Language.TypeScript,
|
105
|
+
// "/home/jacob/projects/context-extractor/targets/angular/packages/elements/src/utils.ts",
|
106
|
+
// "/home/jacob/projects/context-extractor/targets/angular/",
|
107
|
+
// )
|
108
|
+
// console.dir(x, { depth: null })
|
109
|
+
// x = await extractContext(
|
110
|
+
// Language.TypeScript,
|
111
|
+
// "/home/jacob/projects/context-extractor/targets/ionic-framework/core/src/components/img/img.tsx",
|
112
|
+
// "/home/jacob/projects/context-extractor/targets/ionic-framework/",
|
113
|
+
// )
|
114
|
+
// console.dir(x, { depth: null })
|
115
|
+
//
|
13
116
|
// x = await extractContext(
|
14
117
|
// Language.TypeScript,
|
15
118
|
// "/home/jacob/projects/context-extractor/targets/todo/sketch.ts",
|
@@ -30,14 +133,22 @@ const types_1 = require("./types");
|
|
30
133
|
// "/home/jacob/projects/context-extractor/targets/passwords/",
|
31
134
|
// )
|
32
135
|
// console.dir(x, { depth: null })
|
33
|
-
|
136
|
+
//
|
137
|
+
x = await (0, main_1.extractContext)("typescript", "/home/jacob/projects/context-extractor/targets/booking/sketch.ts", "/home/jacob/projects/context-extractor/targets/booking/", "standalone", { line: 3, character: 56 });
|
34
138
|
console.dir(x, { depth: null });
|
139
|
+
//
|
35
140
|
// x = await extractContext(
|
36
141
|
// Language.TypeScript,
|
37
142
|
// "/home/jacob/projects/context-extractor/targets/emojipaint/sketch.ts",
|
38
143
|
// "/home/jacob/projects/context-extractor/targets/emojipaint/",
|
39
144
|
// )
|
40
145
|
// console.dir(x, { depth: null })
|
146
|
+
// x = await extractContext(
|
147
|
+
// Language.TypeScript,
|
148
|
+
// "/home/jacob/projects/continue/manual-testing-sandbox/booking/sketch.ts",
|
149
|
+
// "/home/jacob/projects/continue/manual-testing-sandbox/booking",
|
150
|
+
// )
|
151
|
+
// console.dir(x, { depth: null })
|
41
152
|
// const y = await completeWithLLM(
|
42
153
|
// x!,
|
43
154
|
// Language.TypeScript,
|
@@ -66,7 +177,11 @@ const types_1 = require("./types");
|
|
66
177
|
// }
|
67
178
|
// process.exit(0);
|
68
179
|
}
|
69
|
-
|
180
|
+
// const buf = await pprof.encode(profile());
|
181
|
+
// fs.writeFile('wall.pb.gz', buf, (err) => {
|
182
|
+
// if (err) throw err;
|
183
|
+
// });
|
184
|
+
});
|
70
185
|
// extractWithNew(Language.TypeScript, "/home/jacob/projects/context-extractor/targets/playlist/sketch.ts", "/home/jacob/projects/context-extractor/credentials.json").then(r => console.log("playlist\n", r));
|
71
186
|
// extractWithNew(Language.TypeScript, "/home/jacob/projects/context-extractor/targets/passwords/sketch.ts", "/home/jacob/projects/context-extractor/credentials.json").then(r => console.log("passwords\n", r));
|
72
187
|
// extractWithNew(Language.TypeScript, "/home/jacob/projects/context-extractor/targets/booking/sketch.ts", "/home/jacob/projects/context-extractor/credentials.json").then(r => console.log("booking\n", r));
|
@@ -0,0 +1,36 @@
|
|
1
|
+
;; Capture the variable/function name
|
2
|
+
(variable_declarator
|
3
|
+
name: (identifier) @function.name
|
4
|
+
type: (type_annotation
|
5
|
+
(function_type) @function.type))
|
6
|
+
|
7
|
+
;; Capture the full parameter list
|
8
|
+
(function_type
|
9
|
+
parameters: (formal_parameters) @function.params)
|
10
|
+
|
11
|
+
;; Capture the type identifiers used in the parameters
|
12
|
+
(formal_parameters
|
13
|
+
(required_parameter
|
14
|
+
type: (type_annotation
|
15
|
+
(type_identifier) @param.type))
|
16
|
+
(required_parameter
|
17
|
+
type: (type_annotation
|
18
|
+
(type_identifier) @param.type)))
|
19
|
+
|
20
|
+
;; Capture the return type of the function
|
21
|
+
(function_type
|
22
|
+
return_type: (type_identifier) @return.type)
|
23
|
+
|
24
|
+
;; Capture any parse errors (e.g., the `??`)
|
25
|
+
(ERROR) @error.node
|
26
|
+
|
27
|
+
;; Capture the entire function declaration line
|
28
|
+
(lexical_declaration) @function.decl
|
29
|
+
|
30
|
+
;; Matches import declarations like: import { A, B } from "module";
|
31
|
+
(import_statement
|
32
|
+
(import_clause
|
33
|
+
(named_imports
|
34
|
+
(import_specifier
|
35
|
+
name: (identifier) @import.name)))
|
36
|
+
source: (string) @import.source)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
;; Match top-level `var`, `let`, or `const` declarations
|
2
|
+
(lexical_declaration
|
3
|
+
(variable_declarator
|
4
|
+
name: (identifier) @top.var.name
|
5
|
+
type: (type_annotation
|
6
|
+
(_) @top.var.type))) @top.var.decl
|
7
|
+
|
8
|
+
(variable_declaration
|
9
|
+
(variable_declarator
|
10
|
+
name: (identifier) @top.var.name
|
11
|
+
type: (type_annotation
|
12
|
+
(_) @top.var.type))) @top.var.decl
|
13
|
+
|
14
|
+
;; Match function declarations
|
15
|
+
(function_declaration
|
16
|
+
name: (identifier) @top.fn.name
|
17
|
+
parameters: (formal_parameters
|
18
|
+
(required_parameter
|
19
|
+
pattern: (identifier) @top.fn.param.name
|
20
|
+
type: (type_annotation (_) @top.fn.param.type)))*
|
21
|
+
|
22
|
+
return_type: (type_annotation (_) @top.fn.type)?) @top.fn.decl
|
package/dist/src/tree-sitter-files/queries/relevant-types-queries/typescript-extract-identifiers.scm
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
;; Capture the type alias name (left-hand side)
|
2
|
+
; (type_alias_declaration
|
3
|
+
; name: (type_identifier) @type.name)
|
4
|
+
|
5
|
+
;; Capture all identifiers on the right-hand side (value), recursively
|
6
|
+
; (type_alias_declaration
|
7
|
+
; value: (_) @type.value)
|
8
|
+
|
9
|
+
;; Match all identifiers inside the type value — deeply nested
|
10
|
+
(type_identifier) @type.identifier
|
@@ -0,0 +1,11 @@
|
|
1
|
+
(type_alias_declaration
|
2
|
+
name: (type_identifier) @type.identifier
|
3
|
+
value: (_) @type.value)
|
4
|
+
|
5
|
+
(interface_declaration
|
6
|
+
name: (type_identifier) @type.identifier
|
7
|
+
body: (_) @type.value)
|
8
|
+
|
9
|
+
(enum_declaration
|
10
|
+
name: (type_identifier) @type.identifier
|
11
|
+
body: (_) @type.value)
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import Parser from "web-tree-sitter";
|
2
|
+
import { SymbolWithRange } from "./types";
|
3
|
+
export declare enum LanguageName {
|
4
|
+
TYPESCRIPT = "typescript",
|
5
|
+
OCAML = "ocaml"
|
6
|
+
}
|
7
|
+
export declare const supportedLanguages: {
|
8
|
+
[key: string]: LanguageName;
|
9
|
+
};
|
10
|
+
export declare const IGNORE_PATH_PATTERNS: Partial<Record<LanguageName, RegExp[]>>;
|
11
|
+
export declare function getParserForFile(filepath: string): Promise<Parser | undefined>;
|
12
|
+
export declare function getLanguageForFile(filepath: string): Promise<Parser.Language | undefined>;
|
13
|
+
export declare const getFullLanguageName: (filepath: string) => LanguageName;
|
14
|
+
export declare function getQueryForFile(filepath: string, queryPath: string): Promise<Parser.Query | undefined>;
|
15
|
+
export declare function getSymbolsForFile(filepath: string, contents: string): Promise<SymbolWithRange[] | undefined>;
|
16
|
+
export declare function findTypeDeclarationGivenIdentifier(captures: Parser.QueryCapture[], typeIdentifier: string): {
|
17
|
+
name: Parser.SyntaxNode;
|
18
|
+
value: Parser.SyntaxNode | undefined;
|
19
|
+
kind: string | undefined;
|
20
|
+
} | null;
|
21
|
+
interface TypeDeclarationResult {
|
22
|
+
name: string;
|
23
|
+
fullText: string;
|
24
|
+
startLine: number;
|
25
|
+
startColumn: number;
|
26
|
+
endLine: number;
|
27
|
+
endColumn: number;
|
28
|
+
kind: string;
|
29
|
+
}
|
30
|
+
export declare function findEnclosingTypeDeclaration(sourceCode: string, cursorLine: number, cursorColumn: number, ast: Parser.Tree): TypeDeclarationResult | null;
|
31
|
+
export declare function extractTopLevelDecls(currentFile: string): Promise<Parser.QueryMatch[]>;
|
32
|
+
export declare function extractTopLevelDeclsWithFormatting(currentFile: string): Promise<{
|
33
|
+
declaration: string;
|
34
|
+
nodeType: string;
|
35
|
+
name: string;
|
36
|
+
declaredType: string;
|
37
|
+
returnType?: string;
|
38
|
+
}[]>;
|
39
|
+
export declare function extractFunctionTypeFromDecl(match: Parser.QueryMatch): string;
|
40
|
+
export {};
|
@@ -0,0 +1,334 @@
|
|
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.getFullLanguageName = exports.IGNORE_PATH_PATTERNS = exports.supportedLanguages = exports.LanguageName = void 0;
|
7
|
+
exports.getParserForFile = getParserForFile;
|
8
|
+
exports.getLanguageForFile = getLanguageForFile;
|
9
|
+
exports.getQueryForFile = getQueryForFile;
|
10
|
+
exports.getSymbolsForFile = getSymbolsForFile;
|
11
|
+
exports.findTypeDeclarationGivenIdentifier = findTypeDeclarationGivenIdentifier;
|
12
|
+
exports.findEnclosingTypeDeclaration = findEnclosingTypeDeclaration;
|
13
|
+
exports.extractTopLevelDecls = extractTopLevelDecls;
|
14
|
+
exports.extractTopLevelDeclsWithFormatting = extractTopLevelDeclsWithFormatting;
|
15
|
+
exports.extractFunctionTypeFromDecl = extractFunctionTypeFromDecl;
|
16
|
+
const fs_1 = __importDefault(require("fs"));
|
17
|
+
const web_tree_sitter_1 = __importDefault(require("web-tree-sitter"));
|
18
|
+
const utils_1 = require("./utils");
|
19
|
+
const ast_1 = require("./ast");
|
20
|
+
var LanguageName;
|
21
|
+
(function (LanguageName) {
|
22
|
+
LanguageName["TYPESCRIPT"] = "typescript";
|
23
|
+
LanguageName["OCAML"] = "ocaml";
|
24
|
+
})(LanguageName || (exports.LanguageName = LanguageName = {}));
|
25
|
+
exports.supportedLanguages = {
|
26
|
+
ts: LanguageName.TYPESCRIPT,
|
27
|
+
mts: LanguageName.TYPESCRIPT,
|
28
|
+
cts: LanguageName.TYPESCRIPT,
|
29
|
+
ocaml: LanguageName.OCAML,
|
30
|
+
ml: LanguageName.OCAML,
|
31
|
+
mli: LanguageName.OCAML,
|
32
|
+
};
|
33
|
+
exports.IGNORE_PATH_PATTERNS = {
|
34
|
+
[LanguageName.TYPESCRIPT]: [/.*node_modules/],
|
35
|
+
};
|
36
|
+
async function getParserForFile(filepath) {
|
37
|
+
try {
|
38
|
+
await web_tree_sitter_1.default.init();
|
39
|
+
const parser = new web_tree_sitter_1.default();
|
40
|
+
const language = await getLanguageForFile(filepath);
|
41
|
+
if (!language) {
|
42
|
+
return undefined;
|
43
|
+
}
|
44
|
+
parser.setLanguage(language);
|
45
|
+
return parser;
|
46
|
+
}
|
47
|
+
catch (e) {
|
48
|
+
console.debug("Unable to load language for file", filepath, e);
|
49
|
+
return undefined;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
// Loading the wasm files to create a Language object is an expensive operation and with
|
53
|
+
// sufficient number of files can result in errors, instead keep a map of language name
|
54
|
+
// to Language object
|
55
|
+
const nameToLanguage = new Map();
|
56
|
+
async function getLanguageForFile(filepath) {
|
57
|
+
try {
|
58
|
+
await web_tree_sitter_1.default.init();
|
59
|
+
const extension = (0, utils_1.getUriFileExtension)(filepath);
|
60
|
+
const languageName = exports.supportedLanguages[extension];
|
61
|
+
if (!languageName) {
|
62
|
+
return undefined;
|
63
|
+
}
|
64
|
+
let language = nameToLanguage.get(languageName);
|
65
|
+
if (!language) {
|
66
|
+
language = await loadLanguageForFileExt(extension);
|
67
|
+
nameToLanguage.set(languageName, language);
|
68
|
+
}
|
69
|
+
return language;
|
70
|
+
}
|
71
|
+
catch (e) {
|
72
|
+
console.debug("Unable to load language for file", filepath, e);
|
73
|
+
return undefined;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
const getFullLanguageName = (filepath) => {
|
77
|
+
const extension = (0, utils_1.getUriFileExtension)(filepath);
|
78
|
+
return exports.supportedLanguages[extension];
|
79
|
+
};
|
80
|
+
exports.getFullLanguageName = getFullLanguageName;
|
81
|
+
async function getQueryForFile(filepath, queryPath) {
|
82
|
+
const language = await getLanguageForFile(filepath);
|
83
|
+
if (!language) {
|
84
|
+
return undefined;
|
85
|
+
}
|
86
|
+
if (!fs_1.default.existsSync(queryPath)) {
|
87
|
+
return undefined;
|
88
|
+
}
|
89
|
+
const querySource = fs_1.default.readFileSync(queryPath).toString();
|
90
|
+
const query = language.query(querySource);
|
91
|
+
return query;
|
92
|
+
}
|
93
|
+
async function loadLanguageForFileExt(fileExtension) {
|
94
|
+
const wasmPath = require.resolve(`./tree-sitter-files/wasms/tree-sitter-${exports.supportedLanguages[fileExtension]}.wasm`);
|
95
|
+
// const wasmPath = path.join(
|
96
|
+
// __dirname,
|
97
|
+
// "tree-sitter-files",
|
98
|
+
// "wasms",
|
99
|
+
// `tree-sitter-${supportedLanguages[fileExtension]}.wasm`
|
100
|
+
// );
|
101
|
+
return await web_tree_sitter_1.default.Language.load(wasmPath);
|
102
|
+
}
|
103
|
+
const GET_SYMBOLS_FOR_NODE_TYPES = [
|
104
|
+
"class_declaration",
|
105
|
+
"class_definition",
|
106
|
+
"function_item", // function name = first "identifier" child
|
107
|
+
"function_definition",
|
108
|
+
"method_declaration", // method name = first "identifier" child
|
109
|
+
"method_definition",
|
110
|
+
"generator_function_declaration",
|
111
|
+
// property_identifier
|
112
|
+
// field_declaration
|
113
|
+
// "arrow_function",
|
114
|
+
];
|
115
|
+
async function getSymbolsForFile(filepath, contents) {
|
116
|
+
const parser = await getParserForFile(filepath);
|
117
|
+
if (!parser) {
|
118
|
+
return;
|
119
|
+
}
|
120
|
+
let tree;
|
121
|
+
try {
|
122
|
+
tree = parser.parse(contents);
|
123
|
+
if (!tree) {
|
124
|
+
throw new Error("tree parsing failed");
|
125
|
+
}
|
126
|
+
}
|
127
|
+
catch (e) {
|
128
|
+
console.log(`Error parsing file: ${filepath}`);
|
129
|
+
return;
|
130
|
+
}
|
131
|
+
// console.log(`file: ${filepath}`);
|
132
|
+
// Function to recursively find all named nodes (classes and functions)
|
133
|
+
const symbols = [];
|
134
|
+
function findNamedNodesRecursive(node) {
|
135
|
+
if (!node) {
|
136
|
+
return;
|
137
|
+
}
|
138
|
+
// console.log(`node: ${node.type}, ${node.text}`);
|
139
|
+
if (GET_SYMBOLS_FOR_NODE_TYPES.includes(node.type)) {
|
140
|
+
// console.log(`parent: ${node.type}, ${node.text.substring(0, 200)}`);
|
141
|
+
// node.children.forEach((child) => {
|
142
|
+
// console.log(`child: ${child.type}, ${child.text}`);
|
143
|
+
// });
|
144
|
+
// Empirically, the actual name is the last identifier in the node
|
145
|
+
// Especially with languages where return type is declared before the name
|
146
|
+
// TODO use findLast in newer version of node target
|
147
|
+
let identifier = undefined;
|
148
|
+
for (let i = node.children.length - 1; i >= 0; i--) {
|
149
|
+
if (node.children[i] &&
|
150
|
+
(node.children[i].type === "identifier" ||
|
151
|
+
node.children[i].type === "property_identifier")) {
|
152
|
+
identifier = node.children[i];
|
153
|
+
break;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
if (identifier === null || identifier === void 0 ? void 0 : identifier.text) {
|
157
|
+
symbols.push({
|
158
|
+
filepath,
|
159
|
+
type: node.type,
|
160
|
+
name: identifier.text,
|
161
|
+
range: {
|
162
|
+
start: {
|
163
|
+
character: node.startPosition.column,
|
164
|
+
line: node.startPosition.row,
|
165
|
+
},
|
166
|
+
end: {
|
167
|
+
character: node.endPosition.column + 1,
|
168
|
+
line: node.endPosition.row + 1,
|
169
|
+
},
|
170
|
+
},
|
171
|
+
content: node.text,
|
172
|
+
});
|
173
|
+
}
|
174
|
+
}
|
175
|
+
node.children.forEach(findNamedNodesRecursive);
|
176
|
+
}
|
177
|
+
findNamedNodesRecursive(tree.rootNode);
|
178
|
+
return symbols;
|
179
|
+
}
|
180
|
+
function findTypeDeclarationGivenIdentifier(captures, typeIdentifier) {
|
181
|
+
for (let i = 0; i < captures.length; i++) {
|
182
|
+
const cap = captures[i];
|
183
|
+
if (cap.name === "type.identifier" && cap.node.text === typeIdentifier) {
|
184
|
+
const parent = cap.node.parent;
|
185
|
+
const value = captures.find((c) => c.name === "type.value" && c.node.parent === parent);
|
186
|
+
return { name: cap.node, value: value === null || value === void 0 ? void 0 : value.node, kind: parent === null || parent === void 0 ? void 0 : parent.type };
|
187
|
+
}
|
188
|
+
}
|
189
|
+
return null;
|
190
|
+
}
|
191
|
+
function findEnclosingTypeDeclaration(sourceCode, cursorLine, cursorColumn, ast) {
|
192
|
+
var _a;
|
193
|
+
const point = { row: cursorLine, column: cursorColumn };
|
194
|
+
let node = ast.rootNode.descendantForPosition(point);
|
195
|
+
while (node &&
|
196
|
+
![
|
197
|
+
"type_alias_declaration",
|
198
|
+
"interface_declaration",
|
199
|
+
"enum_declaration",
|
200
|
+
].includes(node.type)) {
|
201
|
+
if (!node.parent)
|
202
|
+
return null;
|
203
|
+
node = node.parent;
|
204
|
+
}
|
205
|
+
if (!node)
|
206
|
+
return null;
|
207
|
+
const nameNode = node.childForFieldName("name");
|
208
|
+
const name = (_a = nameNode === null || nameNode === void 0 ? void 0 : nameNode.text) !== null && _a !== void 0 ? _a : "<anonymous>";
|
209
|
+
const fullText = sourceCode.slice(node.startIndex, node.endIndex);
|
210
|
+
return {
|
211
|
+
name,
|
212
|
+
fullText,
|
213
|
+
startLine: node.startPosition.row,
|
214
|
+
startColumn: node.startPosition.column,
|
215
|
+
endLine: node.endPosition.row,
|
216
|
+
endColumn: node.endPosition.column,
|
217
|
+
kind: node.type,
|
218
|
+
};
|
219
|
+
}
|
220
|
+
async function extractTopLevelDecls(currentFile) {
|
221
|
+
const ast = await (0, ast_1.getAst)(currentFile, fs_1.default.readFileSync(currentFile, "utf8"));
|
222
|
+
if (!ast) {
|
223
|
+
throw new Error(`failed to get ast for file ${currentFile}`);
|
224
|
+
}
|
225
|
+
const language = (0, exports.getFullLanguageName)(currentFile);
|
226
|
+
const queryPath = require.resolve(`./tree-sitter-files/queries/relevant-headers-queries/${language}-get-toplevel-headers.scm`);
|
227
|
+
const query = await getQueryForFile(currentFile, queryPath
|
228
|
+
// path.join(
|
229
|
+
// __dirname,
|
230
|
+
// "tree-sitter-files",
|
231
|
+
// "queries",
|
232
|
+
// "relevant-headers-queries",
|
233
|
+
// `${language}-get-toplevel-headers.scm`
|
234
|
+
// )
|
235
|
+
);
|
236
|
+
if (!query) {
|
237
|
+
throw new Error(`failed to get query for file ${currentFile} and language ${language}`);
|
238
|
+
}
|
239
|
+
return query.matches(ast.rootNode);
|
240
|
+
}
|
241
|
+
async function extractTopLevelDeclsWithFormatting(currentFile) {
|
242
|
+
var _a;
|
243
|
+
const ast = await (0, ast_1.getAst)(currentFile, fs_1.default.readFileSync(currentFile, "utf8"));
|
244
|
+
if (!ast) {
|
245
|
+
throw new Error(`failed to get ast for file ${currentFile}`);
|
246
|
+
}
|
247
|
+
const language = (0, exports.getFullLanguageName)(currentFile);
|
248
|
+
const queryPath = require.resolve(`./tree-sitter-files/queries/relevant-headers-queries/${language}-get-toplevel-headers.scm`);
|
249
|
+
const query = await getQueryForFile(currentFile, queryPath
|
250
|
+
// path.join(
|
251
|
+
// __dirname,
|
252
|
+
// "tree-sitter-files",
|
253
|
+
// "queries",
|
254
|
+
// "relevant-headers-queries",
|
255
|
+
// `${language}-get-toplevel-headers.scm`
|
256
|
+
// )
|
257
|
+
);
|
258
|
+
if (!query) {
|
259
|
+
throw new Error(`failed to get query for file ${currentFile} and language ${language}`);
|
260
|
+
}
|
261
|
+
const matches = query.matches(ast.rootNode);
|
262
|
+
const results = [];
|
263
|
+
for (const match of matches) {
|
264
|
+
const item = {
|
265
|
+
declaration: "",
|
266
|
+
nodeType: "",
|
267
|
+
name: "",
|
268
|
+
declaredType: "",
|
269
|
+
};
|
270
|
+
for (const { name, node } of match.captures) {
|
271
|
+
if (name === "top.var.decl") {
|
272
|
+
item.nodeType = "variable";
|
273
|
+
item.declaration = node.text;
|
274
|
+
// Attempt to get the declared type (e.g., const x: string = ...)
|
275
|
+
const typeNode = node.descendantsOfType("type_annotation")[0];
|
276
|
+
if (typeNode) {
|
277
|
+
item.declaredType = typeNode.text.replace(/^:\s*/, "");
|
278
|
+
}
|
279
|
+
}
|
280
|
+
else if (name === "top.var.name" || name === "top.fn.name") {
|
281
|
+
item.name = node.text;
|
282
|
+
}
|
283
|
+
else if (name === "top.fn.decl") {
|
284
|
+
item.nodeType = "function";
|
285
|
+
item.declaration = node.text;
|
286
|
+
// Get the return type (e.g., function foo(): string)
|
287
|
+
const returnTypeNode = node.childForFieldName("return_type");
|
288
|
+
if (returnTypeNode) {
|
289
|
+
item.returnType = returnTypeNode.text.replace(/^:\s*/, "");
|
290
|
+
}
|
291
|
+
// Get declaredType if needed (TypeScript style)
|
292
|
+
const nameNode = node.childForFieldName("name");
|
293
|
+
if (nameNode && ((_a = nameNode.nextSibling) === null || _a === void 0 ? void 0 : _a.type) === "type_annotation") {
|
294
|
+
item.declaredType = nameNode.nextSibling.text.replace(/^:\s*/, "");
|
295
|
+
}
|
296
|
+
}
|
297
|
+
}
|
298
|
+
if (item.name && item.declaration) {
|
299
|
+
results.push(item);
|
300
|
+
}
|
301
|
+
}
|
302
|
+
return results;
|
303
|
+
}
|
304
|
+
function extractFunctionTypeFromDecl(match) {
|
305
|
+
let paramsNode;
|
306
|
+
let returnNode;
|
307
|
+
for (const capture of match.captures) {
|
308
|
+
if (capture.name === "top.fn.param.type") {
|
309
|
+
paramsNode = capture.node;
|
310
|
+
}
|
311
|
+
else if (capture.name === "top.fn.type") {
|
312
|
+
returnNode = capture.node;
|
313
|
+
}
|
314
|
+
}
|
315
|
+
return `${paramsNode.text} => ${returnNode.text}`;
|
316
|
+
}
|
317
|
+
// export async function getSymbolsForManyFiles(
|
318
|
+
// uris: string[],
|
319
|
+
// ide: IDE,
|
320
|
+
// ): Promise<FileSymbolMap> {
|
321
|
+
// const filesAndSymbols = await Promise.all(
|
322
|
+
// uris.map(async (uri): Promise<[string, SymbolWithRange[]]> => {
|
323
|
+
// const contents = await ide.readFile(uri);
|
324
|
+
// let symbols = undefined;
|
325
|
+
// try {
|
326
|
+
// symbols = await getSymbolsForFile(uri, contents);
|
327
|
+
// } catch (e) {
|
328
|
+
// console.error(`Failed to get symbols for ${uri}:`, e);
|
329
|
+
// }
|
330
|
+
// return [uri, symbols ?? []];
|
331
|
+
// }),
|
332
|
+
// );
|
333
|
+
// return Object.fromEntries(filesAndSymbols);
|
334
|
+
// }
|