@danielblomma/cortex-mcp 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -14
- package/package.json +2 -2
- package/scaffold/mcp/package-lock.json +3 -7
- package/scaffold/mcp/package.json +1 -1
- package/scaffold/scripts/dashboard.mjs +15 -1
- package/scaffold/scripts/doctor.sh +64 -10
- package/scaffold/scripts/ingest.mjs +323 -50
- package/scaffold/scripts/parsers/bash-treesitter.mjs +229 -0
- package/scaffold/scripts/parsers/cpp-dispatch.mjs +56 -0
- package/scaffold/scripts/parsers/cpp-treesitter.mjs +333 -0
- package/scaffold/scripts/parsers/csharp.mjs +197 -10
- package/scaffold/scripts/parsers/dotnet/CSharpParser/CSharpParser.csproj +1 -0
- package/scaffold/scripts/parsers/dotnet/CSharpParser/Program.cs +126 -21
- package/scaffold/scripts/parsers/go-treesitter.mjs +283 -0
- package/scaffold/scripts/parsers/java-treesitter.mjs +250 -0
- package/scaffold/scripts/parsers/javascript/ast.mjs +118 -12
- package/scaffold/scripts/parsers/javascript/chunks.mjs +4 -0
- package/scaffold/scripts/parsers/javascript/patterns.mjs +6 -0
- package/scaffold/scripts/parsers/javascript.mjs +4 -19
- package/scaffold/scripts/parsers/node_modules/.package-lock.json +57 -0
- package/scaffold/scripts/parsers/node_modules/acorn/CHANGELOG.md +972 -0
- package/scaffold/scripts/parsers/node_modules/acorn/LICENSE +21 -0
- package/scaffold/scripts/parsers/node_modules/acorn/README.md +301 -0
- package/scaffold/scripts/parsers/node_modules/acorn/bin/acorn +4 -0
- package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.d.mts +883 -0
- package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.d.ts +883 -0
- package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.js +6295 -0
- package/scaffold/scripts/parsers/node_modules/acorn/dist/acorn.mjs +6266 -0
- package/scaffold/scripts/parsers/node_modules/acorn/dist/bin.js +90 -0
- package/scaffold/scripts/parsers/node_modules/acorn/package.json +50 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/CHANGELOG.md +421 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/LICENSE +21 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/README.md +81 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/error.d.ts +103 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/error.js +78 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/error.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/decorators.d.ts +167 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/decorators.js +75 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/decorators.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/import-assertions.d.ts +177 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/import-assertions.js +56 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/import-assertions.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/index.d.ts +198 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/index.js +327 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/index.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/xhtml.d.ts +256 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/xhtml.js +256 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/extentions/jsx/xhtml.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.d.ts +472 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.js +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/index.mjs +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/middleware.d.ts +159 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/middleware.js +2 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/middleware.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/parseutil.d.ts +10 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/parseutil.js +38 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/parseutil.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/scopeflags.d.ts +12 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/scopeflags.js +29 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/scopeflags.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/tokenType.d.ts +2 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/tokenType.js +118 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/tokenType.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/types.d.ts +60 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/types.js +2 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/types.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/whitespace.d.ts +2 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/whitespace.js +19 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/lib/whitespace.js.map +1 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/package.json +53 -0
- package/scaffold/scripts/parsers/node_modules/acorn-typescript/tsconfig.json +19 -0
- package/scaffold/scripts/parsers/node_modules/acorn-walk/CHANGELOG.md +209 -0
- package/scaffold/scripts/parsers/node_modules/acorn-walk/LICENSE +21 -0
- package/scaffold/scripts/parsers/node_modules/acorn-walk/README.md +124 -0
- package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.d.mts +152 -0
- package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.d.ts +152 -0
- package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.js +485 -0
- package/scaffold/scripts/parsers/node_modules/acorn-walk/dist/walk.mjs +467 -0
- package/scaffold/scripts/parsers/node_modules/acorn-walk/package.json +50 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/LICENSE +24 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/README.md +23 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-bash.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-c.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-c_sharp.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-cpp.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-css.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-dart.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-elisp.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-elixir.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-elm.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-embedded_template.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-go.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-html.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-java.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-javascript.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-json.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-kotlin.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-lua.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-objc.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-ocaml.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-php.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-python.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-ql.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-rescript.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-ruby.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-rust.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-scala.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-solidity.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-swift.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-systemrdl.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-tlaplus.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-toml.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-tsx.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-typescript.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-vue.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-yaml.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/out/tree-sitter-zig.wasm +0 -0
- package/scaffold/scripts/parsers/node_modules/tree-sitter-wasms/package.json +64 -0
- package/scaffold/scripts/parsers/node_modules/web-tree-sitter/LICENSE +21 -0
- package/scaffold/scripts/parsers/node_modules/web-tree-sitter/README.md +198 -0
- package/scaffold/scripts/parsers/node_modules/web-tree-sitter/package.json +37 -0
- package/scaffold/scripts/parsers/node_modules/web-tree-sitter/tree-sitter-web.d.ts +242 -0
- package/scaffold/scripts/parsers/node_modules/web-tree-sitter/tree-sitter.js +1 -0
- package/scaffold/scripts/parsers/node_modules/web-tree-sitter/tree-sitter.wasm +0 -0
- package/scaffold/scripts/parsers/package-lock.json +19 -1
- package/scaffold/scripts/parsers/package.json +3 -1
- package/scaffold/scripts/parsers/python-treesitter.mjs +271 -0
- package/scaffold/scripts/parsers/ruby-treesitter.mjs +271 -0
- package/scaffold/scripts/parsers/rust-dispatch.mjs +43 -0
- package/scaffold/scripts/parsers/rust-treesitter.mjs +291 -0
- package/scaffold/scripts/parsers/tree-sitter/base.mjs +163 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/bash.calls.scm +7 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/bash.chunks.scm +6 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/bash.imports.scm +5 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/cpp.calls.scm +17 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/cpp.chunks.scm +30 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/cpp.imports.scm +6 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/go.calls.scm +11 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/go.chunks.scm +19 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/go.imports.scm +6 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/java.calls.scm +6 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/java.chunks.scm +23 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/java.imports.scm +6 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/python.calls.scm +11 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/python.chunks.scm +11 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/python.imports.scm +13 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/ruby.calls.scm +6 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/ruby.chunks.scm +16 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/ruby.imports.scm +8 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/rust.calls.scm +31 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/rust.chunks.scm +29 -0
- package/scaffold/scripts/parsers/tree-sitter/queries/rust.imports.scm +5 -0
- package/scaffold/scripts/parsers/vb6.mjs +395 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tree-sitter Go parser for Cortex.
|
|
3
|
+
*
|
|
4
|
+
* Extracts function_declaration, method_declaration (with receiver),
|
|
5
|
+
* and type_declaration (struct/interface/type alias) as chunks.
|
|
6
|
+
*
|
|
7
|
+
* Naming:
|
|
8
|
+
* top-level function: name = "Parse"
|
|
9
|
+
* method on T: name = "T.Method"
|
|
10
|
+
* method on *T: name = "T.Method" (pointer vs value unified)
|
|
11
|
+
* struct type: name = "Config" (kind = "struct")
|
|
12
|
+
* interface type: name = "Handler" (kind = "interface")
|
|
13
|
+
* other type: name = "UserID" (kind = "type")
|
|
14
|
+
*
|
|
15
|
+
* Exported: true when the name starts with an upper-case letter (Go convention).
|
|
16
|
+
*
|
|
17
|
+
* parseCode is async; the WASM grammar is lazily loaded on first call
|
|
18
|
+
* and cached for subsequent calls.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import path from "node:path";
|
|
22
|
+
import fs from "node:fs";
|
|
23
|
+
import { fileURLToPath } from "node:url";
|
|
24
|
+
import {
|
|
25
|
+
dedupe,
|
|
26
|
+
initTreeSitter,
|
|
27
|
+
lineRangeOf,
|
|
28
|
+
loadGrammar,
|
|
29
|
+
parseSource,
|
|
30
|
+
runQuery
|
|
31
|
+
} from "./tree-sitter/base.mjs";
|
|
32
|
+
|
|
33
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
34
|
+
const __dirname = path.dirname(__filename);
|
|
35
|
+
const QUERY_DIR = path.join(__dirname, "tree-sitter", "queries");
|
|
36
|
+
|
|
37
|
+
let GO_LANG = null;
|
|
38
|
+
let langPromise = null;
|
|
39
|
+
|
|
40
|
+
async function ensureLanguage() {
|
|
41
|
+
if (GO_LANG) return GO_LANG;
|
|
42
|
+
if (!langPromise) {
|
|
43
|
+
langPromise = (async () => {
|
|
44
|
+
await initTreeSitter();
|
|
45
|
+
GO_LANG = await loadGrammar("go");
|
|
46
|
+
return GO_LANG;
|
|
47
|
+
})();
|
|
48
|
+
}
|
|
49
|
+
await langPromise;
|
|
50
|
+
return GO_LANG;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function isAvailable() {
|
|
54
|
+
try {
|
|
55
|
+
await ensureLanguage();
|
|
56
|
+
return true;
|
|
57
|
+
} catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const CHUNK_QUERY = fs.readFileSync(path.join(QUERY_DIR, "go.chunks.scm"), "utf8");
|
|
63
|
+
const CALL_QUERY = fs.readFileSync(path.join(QUERY_DIR, "go.calls.scm"), "utf8");
|
|
64
|
+
const IMPORT_QUERY = fs.readFileSync(path.join(QUERY_DIR, "go.imports.scm"), "utf8");
|
|
65
|
+
|
|
66
|
+
const CALL_FILTER = new Set([
|
|
67
|
+
"make", "new", "len", "cap", "append", "copy", "delete",
|
|
68
|
+
"panic", "recover", "print", "println", "close",
|
|
69
|
+
"int", "int32", "int64", "float32", "float64", "string",
|
|
70
|
+
"byte", "rune", "bool", "complex", "real", "imag"
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
function normalizeWhitespace(value) {
|
|
74
|
+
return String(value).replace(/\s+/g, " ").trim();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function signatureOfDecl(node) {
|
|
78
|
+
const braceIndex = node.text.indexOf("{");
|
|
79
|
+
if (braceIndex === -1) return normalizeWhitespace(node.text);
|
|
80
|
+
return normalizeWhitespace(node.text.slice(0, braceIndex));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function unquoteStringLiteral(text) {
|
|
84
|
+
if (text.length >= 2 && (text.startsWith('"') || text.startsWith("`"))) {
|
|
85
|
+
return text.slice(1, -1);
|
|
86
|
+
}
|
|
87
|
+
return text;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function isExported(name) {
|
|
91
|
+
if (!name || name.length === 0) return false;
|
|
92
|
+
const first = name[0];
|
|
93
|
+
return first >= "A" && first <= "Z";
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function collectImports(rootNode) {
|
|
97
|
+
const captures = runQuery(GO_LANG, IMPORT_QUERY, rootNode);
|
|
98
|
+
const imports = captures
|
|
99
|
+
.filter((c) => c.name === "import.path")
|
|
100
|
+
.map((c) => unquoteStringLiteral(c.node.text));
|
|
101
|
+
return dedupe(imports);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function collectCallsInNode(node) {
|
|
105
|
+
const captures = runQuery(GO_LANG, CALL_QUERY, node);
|
|
106
|
+
const names = captures
|
|
107
|
+
.filter((c) => c.name === "call.name")
|
|
108
|
+
.map((c) => c.node.text)
|
|
109
|
+
.filter((name) => name && !CALL_FILTER.has(name));
|
|
110
|
+
return dedupe(names);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Return the receiver type name for a method_declaration, ignoring
|
|
115
|
+
* pointer-vs-value distinction. `func (r *Foo) M()` and `func (r Foo) M()`
|
|
116
|
+
* both return "Foo".
|
|
117
|
+
*/
|
|
118
|
+
function receiverTypeOf(methodNode) {
|
|
119
|
+
// First parameter_list is the receiver — walk for pointer_type or type_identifier.
|
|
120
|
+
for (let i = 0; i < methodNode.namedChildCount; i += 1) {
|
|
121
|
+
const child = methodNode.namedChild(i);
|
|
122
|
+
if (child.type !== "parameter_list") continue;
|
|
123
|
+
for (let j = 0; j < child.namedChildCount; j += 1) {
|
|
124
|
+
const param = child.namedChild(j);
|
|
125
|
+
if (param.type !== "parameter_declaration") continue;
|
|
126
|
+
for (let k = 0; k < param.namedChildCount; k += 1) {
|
|
127
|
+
const typeNode = param.namedChild(k);
|
|
128
|
+
if (typeNode.type === "pointer_type") {
|
|
129
|
+
for (let m = 0; m < typeNode.namedChildCount; m += 1) {
|
|
130
|
+
const inner = typeNode.namedChild(m);
|
|
131
|
+
if (inner.type === "type_identifier") return inner.text;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (typeNode.type === "type_identifier") return typeNode.text;
|
|
135
|
+
// generic receivers look like generic_type with inner type_identifier
|
|
136
|
+
if (typeNode.type === "generic_type") {
|
|
137
|
+
for (let m = 0; m < typeNode.namedChildCount; m += 1) {
|
|
138
|
+
const inner = typeNode.namedChild(m);
|
|
139
|
+
if (inner.type === "type_identifier") return inner.text;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
return "";
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Classify a type_declaration's kind. Inspects the body of the type_spec
|
|
151
|
+
* (or type_alias) child to decide: struct, interface, or generic "type".
|
|
152
|
+
*/
|
|
153
|
+
function typeKindOf(declNode) {
|
|
154
|
+
for (let i = 0; i < declNode.namedChildCount; i += 1) {
|
|
155
|
+
const spec = declNode.namedChild(i);
|
|
156
|
+
if (spec.type !== "type_spec" && spec.type !== "type_alias") continue;
|
|
157
|
+
for (let j = 0; j < spec.namedChildCount; j += 1) {
|
|
158
|
+
const child = spec.namedChild(j);
|
|
159
|
+
if (child.type === "struct_type") return "struct";
|
|
160
|
+
if (child.type === "interface_type") return "interface";
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return "type";
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function buildFunctionChunk(node, imports, language) {
|
|
167
|
+
const nameNode = node.childForFieldName("name");
|
|
168
|
+
if (!nameNode) return null;
|
|
169
|
+
const name = nameNode.text;
|
|
170
|
+
const { startLine, endLine } = lineRangeOf(node);
|
|
171
|
+
return {
|
|
172
|
+
name,
|
|
173
|
+
kind: "function",
|
|
174
|
+
signature: signatureOfDecl(node),
|
|
175
|
+
body: node.text,
|
|
176
|
+
startLine,
|
|
177
|
+
endLine,
|
|
178
|
+
language,
|
|
179
|
+
exported: isExported(name),
|
|
180
|
+
calls: collectCallsInNode(node),
|
|
181
|
+
imports
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function buildMethodChunk(node, imports, language) {
|
|
186
|
+
const nameNode = node.childForFieldName("name");
|
|
187
|
+
if (!nameNode) return null;
|
|
188
|
+
const methodName = nameNode.text;
|
|
189
|
+
const receiver = receiverTypeOf(node);
|
|
190
|
+
const qualifiedName = receiver ? `${receiver}.${methodName}` : methodName;
|
|
191
|
+
const { startLine, endLine } = lineRangeOf(node);
|
|
192
|
+
return {
|
|
193
|
+
name: qualifiedName,
|
|
194
|
+
kind: "method",
|
|
195
|
+
signature: signatureOfDecl(node),
|
|
196
|
+
body: node.text,
|
|
197
|
+
startLine,
|
|
198
|
+
endLine,
|
|
199
|
+
language,
|
|
200
|
+
exported: isExported(methodName),
|
|
201
|
+
calls: collectCallsInNode(node),
|
|
202
|
+
imports
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function buildTypeChunk(node, nameNode, language) {
|
|
207
|
+
const name = nameNode.text;
|
|
208
|
+
const kind = typeKindOf(node);
|
|
209
|
+
const { startLine, endLine } = lineRangeOf(node);
|
|
210
|
+
return {
|
|
211
|
+
name,
|
|
212
|
+
kind,
|
|
213
|
+
signature: signatureOfDecl(node),
|
|
214
|
+
body: node.text,
|
|
215
|
+
startLine,
|
|
216
|
+
endLine,
|
|
217
|
+
language,
|
|
218
|
+
exported: isExported(name),
|
|
219
|
+
calls: [],
|
|
220
|
+
imports: []
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export async function parseCode(code, filePath, language = "go") {
|
|
225
|
+
await ensureLanguage();
|
|
226
|
+
const { tree } = parseSource(GO_LANG, code);
|
|
227
|
+
const root = tree.rootNode;
|
|
228
|
+
const imports = collectImports(root);
|
|
229
|
+
|
|
230
|
+
const captures = runQuery(GO_LANG, CHUNK_QUERY, root);
|
|
231
|
+
const declCaptures = captures.filter((c) => c.name.endsWith(".decl"));
|
|
232
|
+
|
|
233
|
+
const nameCaptures = captures.filter((c) => c.name.endsWith(".name"));
|
|
234
|
+
|
|
235
|
+
const chunks = [];
|
|
236
|
+
for (const cap of declCaptures) {
|
|
237
|
+
const kind = cap.name.split(".")[0];
|
|
238
|
+
if (kind === "fn") {
|
|
239
|
+
const chunk = buildFunctionChunk(cap.node, imports, language);
|
|
240
|
+
if (chunk) chunks.push(chunk);
|
|
241
|
+
} else if (kind === "method") {
|
|
242
|
+
const chunk = buildMethodChunk(cap.node, imports, language);
|
|
243
|
+
if (chunk) chunks.push(chunk);
|
|
244
|
+
} else if (kind === "type") {
|
|
245
|
+
let nameNode = null;
|
|
246
|
+
let smallest = Infinity;
|
|
247
|
+
for (const nc of nameCaptures) {
|
|
248
|
+
if (nc.name !== "type.name") continue;
|
|
249
|
+
if (nc.node.startIndex < cap.node.startIndex) continue;
|
|
250
|
+
if (nc.node.endIndex > cap.node.endIndex) continue;
|
|
251
|
+
const size = nc.node.endIndex - nc.node.startIndex;
|
|
252
|
+
if (size < smallest) {
|
|
253
|
+
smallest = size;
|
|
254
|
+
nameNode = nc.node;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (!nameNode) continue;
|
|
258
|
+
const chunk = buildTypeChunk(cap.node, nameNode, language);
|
|
259
|
+
if (chunk) chunks.push(chunk);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const seen = new Set();
|
|
264
|
+
const deduped = chunks.filter((chunk) => {
|
|
265
|
+
const key = `${chunk.kind}|${chunk.name}|${chunk.startLine}|${chunk.endLine}`;
|
|
266
|
+
if (seen.has(key)) return false;
|
|
267
|
+
seen.add(key);
|
|
268
|
+
return true;
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
return { chunks: deduped, errors: [] };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
275
|
+
const target = process.argv[2];
|
|
276
|
+
if (!target) {
|
|
277
|
+
console.error("Usage: go-treesitter.mjs <file.go>");
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
const code = fs.readFileSync(target, "utf8");
|
|
281
|
+
const result = await parseCode(code, target, "go");
|
|
282
|
+
console.log(JSON.stringify(result, null, 2));
|
|
283
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tree-sitter Java parser for Cortex.
|
|
3
|
+
*
|
|
4
|
+
* Extracts class/interface/enum/record declarations, methods, and
|
|
5
|
+
* constructors as chunks. Methods and constructors are qualified by
|
|
6
|
+
* the enclosing type path, so `Outer.Inner.deep()` becomes
|
|
7
|
+
* "Outer.Inner.deep" and `Svc(int n)` becomes "Svc.ctor".
|
|
8
|
+
*
|
|
9
|
+
* Naming conventions (match other Cortex parsers):
|
|
10
|
+
* class/interface/enum/record: name = "Foo"
|
|
11
|
+
* nested type: name = "Outer.Inner"
|
|
12
|
+
* method: name = "Class.method"
|
|
13
|
+
* method in nested: name = "Outer.Inner.method"
|
|
14
|
+
* constructor: name = "Class.ctor" (matches C# style)
|
|
15
|
+
*
|
|
16
|
+
* exported: true when modifiers include `public`. Package-private and
|
|
17
|
+
* protected count as not-exported for Cortex's find-callers purposes.
|
|
18
|
+
*
|
|
19
|
+
* parseCode is async; the WASM grammar is lazily loaded on first call
|
|
20
|
+
* and cached for subsequent calls.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import path from "node:path";
|
|
24
|
+
import fs from "node:fs";
|
|
25
|
+
import { fileURLToPath } from "node:url";
|
|
26
|
+
import {
|
|
27
|
+
dedupe,
|
|
28
|
+
initTreeSitter,
|
|
29
|
+
lineRangeOf,
|
|
30
|
+
loadGrammar,
|
|
31
|
+
parseSource,
|
|
32
|
+
runQuery
|
|
33
|
+
} from "./tree-sitter/base.mjs";
|
|
34
|
+
|
|
35
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
36
|
+
const __dirname = path.dirname(__filename);
|
|
37
|
+
const QUERY_DIR = path.join(__dirname, "tree-sitter", "queries");
|
|
38
|
+
|
|
39
|
+
let JAVA_LANG = null;
|
|
40
|
+
let langPromise = null;
|
|
41
|
+
|
|
42
|
+
async function ensureLanguage() {
|
|
43
|
+
if (JAVA_LANG) return JAVA_LANG;
|
|
44
|
+
if (!langPromise) {
|
|
45
|
+
langPromise = (async () => {
|
|
46
|
+
await initTreeSitter();
|
|
47
|
+
JAVA_LANG = await loadGrammar("java");
|
|
48
|
+
return JAVA_LANG;
|
|
49
|
+
})();
|
|
50
|
+
}
|
|
51
|
+
await langPromise;
|
|
52
|
+
return JAVA_LANG;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function isAvailable() {
|
|
56
|
+
try {
|
|
57
|
+
await ensureLanguage();
|
|
58
|
+
return true;
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const CHUNK_QUERY = fs.readFileSync(path.join(QUERY_DIR, "java.chunks.scm"), "utf8");
|
|
65
|
+
const CALL_QUERY = fs.readFileSync(path.join(QUERY_DIR, "java.calls.scm"), "utf8");
|
|
66
|
+
const IMPORT_QUERY = fs.readFileSync(path.join(QUERY_DIR, "java.imports.scm"), "utf8");
|
|
67
|
+
|
|
68
|
+
// Keywords that parse as method_invocation in some grammars but
|
|
69
|
+
// aren't real call edges for our purposes.
|
|
70
|
+
const CALL_FILTER = new Set([
|
|
71
|
+
"super", "this"
|
|
72
|
+
]);
|
|
73
|
+
|
|
74
|
+
function normalizeWhitespace(value) {
|
|
75
|
+
return String(value).replace(/\s+/g, " ").trim();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function signatureOfDecl(node) {
|
|
79
|
+
const braceIndex = node.text.indexOf("{");
|
|
80
|
+
const semiIndex = node.text.indexOf(";");
|
|
81
|
+
const end = braceIndex === -1 ? semiIndex : (semiIndex === -1 ? braceIndex : Math.min(braceIndex, semiIndex));
|
|
82
|
+
if (end === -1) return normalizeWhitespace(node.text);
|
|
83
|
+
return normalizeWhitespace(node.text.slice(0, end));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function hasPublicModifier(node) {
|
|
87
|
+
for (let i = 0; i < node.namedChildCount; i += 1) {
|
|
88
|
+
const child = node.namedChild(i);
|
|
89
|
+
if (child.type !== "modifiers") continue;
|
|
90
|
+
if (child.text.includes("public")) return true;
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function enclosingTypePath(node) {
|
|
97
|
+
const path = [];
|
|
98
|
+
let cur = node.parent;
|
|
99
|
+
while (cur && cur.type !== "program") {
|
|
100
|
+
if (
|
|
101
|
+
cur.type === "class_declaration" ||
|
|
102
|
+
cur.type === "interface_declaration" ||
|
|
103
|
+
cur.type === "enum_declaration" ||
|
|
104
|
+
cur.type === "record_declaration"
|
|
105
|
+
) {
|
|
106
|
+
const nameNode = cur.childForFieldName("name");
|
|
107
|
+
if (nameNode) path.unshift(nameNode.text);
|
|
108
|
+
}
|
|
109
|
+
cur = cur.parent;
|
|
110
|
+
}
|
|
111
|
+
return path;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function collectCallsInNode(node) {
|
|
115
|
+
const captures = runQuery(JAVA_LANG, CALL_QUERY, node);
|
|
116
|
+
const names = captures
|
|
117
|
+
.filter((c) => c.name === "call.name")
|
|
118
|
+
.map((c) => c.node.text)
|
|
119
|
+
.filter((name) => name && !CALL_FILTER.has(name));
|
|
120
|
+
return dedupe(names);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function collectImports(rootNode) {
|
|
124
|
+
const captures = runQuery(JAVA_LANG, IMPORT_QUERY, rootNode);
|
|
125
|
+
const imports = [];
|
|
126
|
+
for (const cap of captures) {
|
|
127
|
+
if (cap.name !== "import.decl") continue;
|
|
128
|
+
const decl = cap.node;
|
|
129
|
+
// decl.text looks like `import java.util.List;` or
|
|
130
|
+
// `import static java.lang.Math.PI;` or `import java.util.*;`.
|
|
131
|
+
// Strip `import`, optional `static`, and trailing semicolon.
|
|
132
|
+
let text = decl.text.trim();
|
|
133
|
+
if (text.endsWith(";")) text = text.slice(0, -1).trim();
|
|
134
|
+
if (text.startsWith("import")) text = text.slice("import".length).trim();
|
|
135
|
+
if (text.startsWith("static ")) text = text.slice("static".length).trim();
|
|
136
|
+
imports.push(text);
|
|
137
|
+
}
|
|
138
|
+
return dedupe(imports);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function buildTypeChunk(node, kind, imports, language) {
|
|
142
|
+
const nameNode = node.childForFieldName("name");
|
|
143
|
+
if (!nameNode) return null;
|
|
144
|
+
const baseName = nameNode.text;
|
|
145
|
+
const parentPath = enclosingTypePath(node);
|
|
146
|
+
const qualifiedName = parentPath.length > 0
|
|
147
|
+
? `${parentPath.join(".")}.${baseName}`
|
|
148
|
+
: baseName;
|
|
149
|
+
const { startLine, endLine } = lineRangeOf(node);
|
|
150
|
+
return {
|
|
151
|
+
name: qualifiedName,
|
|
152
|
+
kind,
|
|
153
|
+
signature: signatureOfDecl(node),
|
|
154
|
+
body: node.text,
|
|
155
|
+
startLine,
|
|
156
|
+
endLine,
|
|
157
|
+
language,
|
|
158
|
+
exported: hasPublicModifier(node),
|
|
159
|
+
calls: [],
|
|
160
|
+
imports: []
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function buildMethodChunk(node, imports, language) {
|
|
165
|
+
const nameNode = node.childForFieldName("name");
|
|
166
|
+
if (!nameNode) return null;
|
|
167
|
+
const methodName = nameNode.text;
|
|
168
|
+
const parentPath = enclosingTypePath(node);
|
|
169
|
+
const qualifiedName = parentPath.length > 0
|
|
170
|
+
? `${parentPath.join(".")}.${methodName}`
|
|
171
|
+
: methodName;
|
|
172
|
+
const { startLine, endLine } = lineRangeOf(node);
|
|
173
|
+
return {
|
|
174
|
+
name: qualifiedName,
|
|
175
|
+
kind: "method",
|
|
176
|
+
signature: signatureOfDecl(node),
|
|
177
|
+
body: node.text,
|
|
178
|
+
startLine,
|
|
179
|
+
endLine,
|
|
180
|
+
language,
|
|
181
|
+
exported: hasPublicModifier(node),
|
|
182
|
+
calls: collectCallsInNode(node),
|
|
183
|
+
imports
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function buildConstructorChunk(node, imports, language) {
|
|
188
|
+
const nameNode = node.childForFieldName("name");
|
|
189
|
+
if (!nameNode) return null;
|
|
190
|
+
const parentPath = enclosingTypePath(node);
|
|
191
|
+
const classPath = parentPath.length > 0 ? parentPath.join(".") : nameNode.text;
|
|
192
|
+
const qualifiedName = `${classPath}.ctor`;
|
|
193
|
+
const { startLine, endLine } = lineRangeOf(node);
|
|
194
|
+
return {
|
|
195
|
+
name: qualifiedName,
|
|
196
|
+
kind: "constructor",
|
|
197
|
+
signature: signatureOfDecl(node),
|
|
198
|
+
body: node.text,
|
|
199
|
+
startLine,
|
|
200
|
+
endLine,
|
|
201
|
+
language,
|
|
202
|
+
exported: hasPublicModifier(node),
|
|
203
|
+
calls: collectCallsInNode(node),
|
|
204
|
+
imports
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export async function parseCode(code, filePath, language = "java") {
|
|
209
|
+
await ensureLanguage();
|
|
210
|
+
const { tree } = parseSource(JAVA_LANG, code);
|
|
211
|
+
const root = tree.rootNode;
|
|
212
|
+
const imports = collectImports(root);
|
|
213
|
+
|
|
214
|
+
const captures = runQuery(JAVA_LANG, CHUNK_QUERY, root);
|
|
215
|
+
const declCaptures = captures.filter((c) => c.name.endsWith(".decl"));
|
|
216
|
+
|
|
217
|
+
const chunks = [];
|
|
218
|
+
for (const cap of declCaptures) {
|
|
219
|
+
const kind = cap.name.split(".")[0];
|
|
220
|
+
let chunk = null;
|
|
221
|
+
if (kind === "class") chunk = buildTypeChunk(cap.node, "class", imports, language);
|
|
222
|
+
else if (kind === "interface") chunk = buildTypeChunk(cap.node, "interface", imports, language);
|
|
223
|
+
else if (kind === "enum") chunk = buildTypeChunk(cap.node, "enum", imports, language);
|
|
224
|
+
else if (kind === "record") chunk = buildTypeChunk(cap.node, "record", imports, language);
|
|
225
|
+
else if (kind === "method") chunk = buildMethodChunk(cap.node, imports, language);
|
|
226
|
+
else if (kind === "ctor") chunk = buildConstructorChunk(cap.node, imports, language);
|
|
227
|
+
if (chunk) chunks.push(chunk);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const seen = new Set();
|
|
231
|
+
const deduped = chunks.filter((chunk) => {
|
|
232
|
+
const key = `${chunk.kind}|${chunk.name}|${chunk.startLine}|${chunk.endLine}`;
|
|
233
|
+
if (seen.has(key)) return false;
|
|
234
|
+
seen.add(key);
|
|
235
|
+
return true;
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
return { chunks: deduped, errors: [] };
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
242
|
+
const target = process.argv[2];
|
|
243
|
+
if (!target) {
|
|
244
|
+
console.error("Usage: java-treesitter.mjs <file.java>");
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
const code = fs.readFileSync(target, "utf8");
|
|
248
|
+
const result = await parseCode(code, target, "java");
|
|
249
|
+
console.log(JSON.stringify(result, null, 2));
|
|
250
|
+
}
|
|
@@ -2,12 +2,67 @@ import { Parser } from "acorn";
|
|
|
2
2
|
import tsPlugin from "acorn-typescript";
|
|
3
3
|
import { base } from "acorn-walk";
|
|
4
4
|
|
|
5
|
+
const baseIdentifier = base.Identifier;
|
|
6
|
+
const baseFunction = base.Function;
|
|
7
|
+
const baseClass = base.Class;
|
|
8
|
+
|
|
9
|
+
base.Identifier = (node, st, visit) => {
|
|
10
|
+
baseIdentifier(node, st, visit);
|
|
11
|
+
if (node.typeAnnotation) {
|
|
12
|
+
visit(node.typeAnnotation, st);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
base.Function = (node, st, visit) => {
|
|
17
|
+
baseFunction(node, st, visit);
|
|
18
|
+
if (node.returnType) {
|
|
19
|
+
visit(node.returnType, st);
|
|
20
|
+
}
|
|
21
|
+
if (node.typeParameters) {
|
|
22
|
+
visit(node.typeParameters, st);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
base.Class = (node, st, visit) => {
|
|
27
|
+
baseClass(node, st, visit);
|
|
28
|
+
for (const implementedType of node.implements || []) {
|
|
29
|
+
visit(implementedType, st);
|
|
30
|
+
}
|
|
31
|
+
if (node.typeParameters) {
|
|
32
|
+
visit(node.typeParameters, st);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
5
36
|
const tsNodeHandlers = {
|
|
6
37
|
TSAsExpression(node, st, visit) { visit(node.expression, st); },
|
|
7
|
-
TSTypeAnnotation() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
38
|
+
TSTypeAnnotation(node, st, visit) {
|
|
39
|
+
if (node.typeAnnotation) {
|
|
40
|
+
visit(node.typeAnnotation, st);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
TSTypeParameterInstantiation(node, st, visit) {
|
|
44
|
+
for (const param of node.params || []) {
|
|
45
|
+
visit(param, st);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
TSTypeParameterDeclaration(node, st, visit) {
|
|
49
|
+
for (const param of node.params || []) {
|
|
50
|
+
if (param.constraint) {
|
|
51
|
+
visit(param.constraint, st);
|
|
52
|
+
}
|
|
53
|
+
if (param.default) {
|
|
54
|
+
visit(param.default, st);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
TSTypeReference(node, st, visit) {
|
|
59
|
+
if (node.typeName) {
|
|
60
|
+
visit(node.typeName, st);
|
|
61
|
+
}
|
|
62
|
+
if (node.typeParameters) {
|
|
63
|
+
visit(node.typeParameters, st);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
11
66
|
TSInterfaceDeclaration() {},
|
|
12
67
|
TSTypeAliasDeclaration() {},
|
|
13
68
|
TSEnumDeclaration() {},
|
|
@@ -17,14 +72,65 @@ const tsNodeHandlers = {
|
|
|
17
72
|
TSMethodSignature() {},
|
|
18
73
|
TSIndexSignature() {},
|
|
19
74
|
TSTypeLiteral() {},
|
|
20
|
-
TSUnionType() {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
75
|
+
TSUnionType(node, st, visit) {
|
|
76
|
+
for (const typeNode of node.types || []) {
|
|
77
|
+
visit(typeNode, st);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
TSIntersectionType(node, st, visit) {
|
|
81
|
+
for (const typeNode of node.types || []) {
|
|
82
|
+
visit(typeNode, st);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
TSArrayType(node, st, visit) {
|
|
86
|
+
if (node.elementType) {
|
|
87
|
+
visit(node.elementType, st);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
TSTupleType(node, st, visit) {
|
|
91
|
+
for (const elementType of node.elementTypes || []) {
|
|
92
|
+
visit(elementType, st);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
TSOptionalType(node, st, visit) {
|
|
96
|
+
if (node.typeAnnotation) {
|
|
97
|
+
visit(node.typeAnnotation, st);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
TSRestType(node, st, visit) {
|
|
101
|
+
if (node.typeAnnotation) {
|
|
102
|
+
visit(node.typeAnnotation, st);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
TSFunctionType(node, st, visit) {
|
|
106
|
+
for (const param of node.params || []) {
|
|
107
|
+
visit(param, st);
|
|
108
|
+
}
|
|
109
|
+
if (node.returnType) {
|
|
110
|
+
visit(node.returnType, st);
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
TSConstructorType(node, st, visit) {
|
|
114
|
+
for (const param of node.params || []) {
|
|
115
|
+
visit(param, st);
|
|
116
|
+
}
|
|
117
|
+
if (node.returnType) {
|
|
118
|
+
visit(node.returnType, st);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
TSExpressionWithTypeArguments(node, st, visit) {
|
|
122
|
+
if (node.expression) {
|
|
123
|
+
visit(node.expression, st);
|
|
124
|
+
}
|
|
125
|
+
if (node.typeParameters) {
|
|
126
|
+
visit(node.typeParameters, st);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
TSParameterProperty(node, st, visit) {
|
|
130
|
+
if (node.parameter) {
|
|
131
|
+
visit(node.parameter, st);
|
|
132
|
+
}
|
|
133
|
+
},
|
|
28
134
|
TSNonNullExpression(node, st, visit) { visit(node.expression, st); },
|
|
29
135
|
TSInstantiationExpression(node, st, visit) { visit(node.expression, st); }
|
|
30
136
|
};
|
|
@@ -376,6 +376,10 @@ function findLeadingCommentStart(code, node) {
|
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
function formatParameterName(param) {
|
|
379
|
+
if (param.type === "TSParameterProperty") {
|
|
380
|
+
return formatParameterName(param.parameter);
|
|
381
|
+
}
|
|
382
|
+
|
|
379
383
|
if (param.type === "Identifier") {
|
|
380
384
|
return param.name;
|
|
381
385
|
}
|
|
@@ -4,6 +4,9 @@ export function collectPatternIdentifiers(pattern, visit) {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
switch (pattern.type) {
|
|
7
|
+
case "TSParameterProperty":
|
|
8
|
+
collectPatternIdentifiers(pattern.parameter, visit);
|
|
9
|
+
break;
|
|
7
10
|
case "Identifier":
|
|
8
11
|
visit(pattern.name);
|
|
9
12
|
break;
|
|
@@ -44,6 +47,9 @@ export function walkPatternExpressions(pattern, visit) {
|
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
switch (pattern.type) {
|
|
50
|
+
case "TSParameterProperty":
|
|
51
|
+
walkPatternExpressions(pattern.parameter, visit);
|
|
52
|
+
break;
|
|
47
53
|
case "AssignmentPattern":
|
|
48
54
|
walkPatternExpressions(pattern.left, visit);
|
|
49
55
|
if (pattern.right) {
|