universal-ast-mapper 0.7.0 → 0.8.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 +12 -9
- package/dist/extractors/c.js +204 -0
- package/dist/extractors/cpp.js +272 -0
- package/dist/extractors/kotlin.js +159 -0
- package/dist/extractors/swift.js +192 -0
- package/dist/registry.js +25 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,16 +4,18 @@ An **MCP server + CLI tool** that turns source code into structured, machine-rea
|
|
|
4
4
|
|
|
5
5
|
Built on [tree-sitter](https://tree-sitter.github.io/) WASM grammars. Zero regex guessing — real AST parsing.
|
|
6
6
|
|
|
7
|
-
**Supported languages:** TypeScript · TSX · JavaScript (ESM/CJS) · Python · Go · Rust · Java · C#
|
|
7
|
+
**Supported languages:** TypeScript · TSX · JavaScript (ESM/CJS) · Python · Go · Rust · Java · C# · C · C++ · Kotlin · Swift
|
|
8
8
|
|
|
9
|
-
| Capability | TS/JS | Python | Go | Rust | Java | C# |
|
|
10
|
-
|
|
11
|
-
| Symbol extraction | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
12
|
-
| Imports parsing | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
13
|
-
| Graph `imports` edges | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
14
|
-
| `resolve_imports` enrich | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
15
|
-
| Call graph callee origin | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
16
|
-
| Reverse `calledBy` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
9
|
+
| Capability | TS/JS | Python | Go | Rust | Java | C# | C | C++ | Kt | Swift |
|
|
10
|
+
|--------------------------|:-----:|:------:|:---:|:----:|:----:|:---:|:---:|:---:|:---:|:-----:|
|
|
11
|
+
| Symbol extraction | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
12
|
+
| Imports parsing | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
13
|
+
| Graph `imports` edges | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | — | — |
|
|
14
|
+
| `resolve_imports` enrich | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | — | — |
|
|
15
|
+
| Call graph callee origin | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | — | — |
|
|
16
|
+
| Reverse `calledBy` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | — | — |
|
|
17
|
+
|
|
18
|
+
> v0.8.0 introduces **symbol extraction + imports parsing** for C / C++ / Kotlin / Swift. Graph/resolver/callgraph dispatch for these four lands in a follow-up release. (Ruby grammar in `tree-sitter-wasms@0.1.13` is unstable and was skipped.)
|
|
17
19
|
|
|
18
20
|
Each language uses the resolution strategy that fits it:
|
|
19
21
|
- **TS/JS/Python** — relative paths (`./foo`, `..mod`) resolved against the importing file's directory, with TS-ESM `.js` → `.ts` rewriting.
|
|
@@ -478,6 +480,7 @@ src/
|
|
|
478
480
|
|
|
479
481
|
| Version | What changed |
|
|
480
482
|
|---------|--------------|
|
|
483
|
+
| **0.8.0** | **4 new languages: C · C++ · Kotlin · Swift** — symbol extraction + imports parsing. C++ tracks access_specifier through class bodies. Kotlin handles `package`/`object`/`data class`. Swift handles `class`/`struct`/`enum` (all under `class_declaration`) and `protocol_declaration`. Ruby grammar in tree-sitter-wasms@0.1.13 is unstable — skipped. |
|
|
481
484
|
| **0.7.0** | Go full resolution (reads `go.mod`, resolves package-as-directory) · C# reverse `calledBy` via call-site scanning · `csharpTypes` index lets `using` directives resolve to specific types · 4-suite test harness (smoke + graph-smoke + resolver-smoke + callgraph-smoke) |
|
|
482
485
|
| **0.6.0** | **3 new languages: Rust · Java · C#** (extractors + import parsing) · cross-language resolver in `crosslang.ts` (Java FQCN index, C# namespace index, Rust `crate::` module walk) · symbol-graph `imports` edges + `resolveFileImports` enrichment + `get_call_graph` callee resolution rewired through it · Java `package` and C# `namespace` captured as directives |
|
|
483
486
|
| **0.5.3** | Auto-install `/ast-map` Claude Code skill on `npm install` · `postinstall` writes `~/.claude/skills/ast-map/SKILL.md` + registers trigger in `CLAUDE.md` (idempotent, CI-safe) |
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { namedChildren, nameOf, headerSignature, leadingComment } from "../parser.js";
|
|
2
|
+
import { makeSymbol } from "./common.js";
|
|
3
|
+
/* ─── helpers ─────────────────────────────────────────────────────────────── */
|
|
4
|
+
function childOfType(node, type) {
|
|
5
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
6
|
+
const c = node.child(i);
|
|
7
|
+
if (c && c.type === type)
|
|
8
|
+
return c;
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
/** Recursively unwrap a declarator chain to get the identifier text. */
|
|
13
|
+
function nameFromDeclarator(node) {
|
|
14
|
+
if (!node)
|
|
15
|
+
return null;
|
|
16
|
+
switch (node.type) {
|
|
17
|
+
case "identifier":
|
|
18
|
+
case "field_identifier":
|
|
19
|
+
case "type_identifier":
|
|
20
|
+
return node.text;
|
|
21
|
+
case "pointer_declarator":
|
|
22
|
+
case "array_declarator":
|
|
23
|
+
case "parenthesized_declarator":
|
|
24
|
+
return nameFromDeclarator(node.childForFieldName("declarator"));
|
|
25
|
+
case "function_declarator": {
|
|
26
|
+
const d = node.childForFieldName("declarator");
|
|
27
|
+
return nameFromDeclarator(d);
|
|
28
|
+
}
|
|
29
|
+
case "init_declarator":
|
|
30
|
+
return nameFromDeclarator(node.childForFieldName("declarator"));
|
|
31
|
+
default:
|
|
32
|
+
// best-effort: find first identifier-like child
|
|
33
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
34
|
+
const c = node.namedChild(i);
|
|
35
|
+
if (c && (c.type === "identifier" || c.type === "field_identifier" || c.type === "type_identifier"))
|
|
36
|
+
return c.text;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function hasStaticStorage(node) {
|
|
42
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
43
|
+
const c = node.child(i);
|
|
44
|
+
if (c && c.type === "storage_class_specifier" && c.text === "static")
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
/* ─── imports (#include) ──────────────────────────────────────────────────── */
|
|
50
|
+
export function extractImportsC(root, _source) {
|
|
51
|
+
const out = [];
|
|
52
|
+
for (const child of namedChildren(root)) {
|
|
53
|
+
if (child.type !== "preproc_include")
|
|
54
|
+
continue;
|
|
55
|
+
const pathNode = childOfType(child, "system_lib_string") ?? childOfType(child, "string_literal");
|
|
56
|
+
if (!pathNode)
|
|
57
|
+
continue;
|
|
58
|
+
const raw = pathNode.text.replace(/^[<"]|[>"]$/g, "");
|
|
59
|
+
const base = raw.split("/").pop() ?? raw;
|
|
60
|
+
const sym = base.replace(/\.[hH]$|\.hpp$|\.hxx$|\.hh$/, "");
|
|
61
|
+
out.push({ symbol: sym, from: raw });
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
/* ─── symbol extraction ───────────────────────────────────────────────────── */
|
|
66
|
+
export function extractC(root, _source) {
|
|
67
|
+
return collect(namedChildren(root));
|
|
68
|
+
}
|
|
69
|
+
function collect(nodes) {
|
|
70
|
+
const out = [];
|
|
71
|
+
for (const n of nodes) {
|
|
72
|
+
const res = handle(n);
|
|
73
|
+
if (Array.isArray(res))
|
|
74
|
+
out.push(...res);
|
|
75
|
+
else if (res)
|
|
76
|
+
out.push(res);
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
function handle(node) {
|
|
81
|
+
switch (node.type) {
|
|
82
|
+
case "struct_specifier":
|
|
83
|
+
case "union_specifier": {
|
|
84
|
+
const name = nameOf(node);
|
|
85
|
+
if (!name)
|
|
86
|
+
return null;
|
|
87
|
+
const body = node.childForFieldName("body");
|
|
88
|
+
return makeSymbol({
|
|
89
|
+
name,
|
|
90
|
+
kind: "struct",
|
|
91
|
+
node,
|
|
92
|
+
rawKind: node.type,
|
|
93
|
+
doc: leadingComment(node),
|
|
94
|
+
children: body ? structFields(body) : [],
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
case "enum_specifier": {
|
|
98
|
+
const name = nameOf(node);
|
|
99
|
+
if (!name)
|
|
100
|
+
return null;
|
|
101
|
+
return makeSymbol({
|
|
102
|
+
name,
|
|
103
|
+
kind: "enum",
|
|
104
|
+
node,
|
|
105
|
+
rawKind: node.type,
|
|
106
|
+
doc: leadingComment(node),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
case "function_definition": {
|
|
110
|
+
const decl = node.childForFieldName("declarator");
|
|
111
|
+
const name = nameFromDeclarator(decl);
|
|
112
|
+
if (!name)
|
|
113
|
+
return null;
|
|
114
|
+
const isStatic = hasStaticStorage(node);
|
|
115
|
+
return makeSymbol({
|
|
116
|
+
name,
|
|
117
|
+
kind: "function",
|
|
118
|
+
node,
|
|
119
|
+
rawKind: node.type,
|
|
120
|
+
signature: headerSignature(node, node.childForFieldName("body")),
|
|
121
|
+
visibility: isStatic ? "private" : "public",
|
|
122
|
+
exported: !isStatic,
|
|
123
|
+
doc: leadingComment(node),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
case "declaration": {
|
|
127
|
+
// top-level variable/function declarations (prototypes, externs, etc.)
|
|
128
|
+
const decl = node.childForFieldName("declarator");
|
|
129
|
+
const name = nameFromDeclarator(decl);
|
|
130
|
+
if (!name)
|
|
131
|
+
return null;
|
|
132
|
+
// skip function prototypes — focus on real defs (function_definition)
|
|
133
|
+
if (decl && containsFunctionDeclarator(decl))
|
|
134
|
+
return null;
|
|
135
|
+
return makeSymbol({
|
|
136
|
+
name,
|
|
137
|
+
kind: "var",
|
|
138
|
+
node,
|
|
139
|
+
rawKind: node.type,
|
|
140
|
+
signature: node.text.replace(/\s+/g, " ").replace(/;$/, "").trim(),
|
|
141
|
+
visibility: hasStaticStorage(node) ? "private" : "public",
|
|
142
|
+
exported: !hasStaticStorage(node),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
case "preproc_def":
|
|
146
|
+
case "preproc_function_def": {
|
|
147
|
+
const name = nameOf(node);
|
|
148
|
+
if (!name)
|
|
149
|
+
return null;
|
|
150
|
+
return makeSymbol({
|
|
151
|
+
name,
|
|
152
|
+
kind: "const",
|
|
153
|
+
node,
|
|
154
|
+
rawKind: node.type,
|
|
155
|
+
signature: node.text.replace(/\s+/g, " ").trim(),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
case "type_definition": {
|
|
159
|
+
// typedef — name is in the declarator (last identifier)
|
|
160
|
+
const decl = node.childForFieldName("declarator");
|
|
161
|
+
const name = nameFromDeclarator(decl);
|
|
162
|
+
if (!name)
|
|
163
|
+
return null;
|
|
164
|
+
return makeSymbol({
|
|
165
|
+
name,
|
|
166
|
+
kind: "type",
|
|
167
|
+
node,
|
|
168
|
+
rawKind: node.type,
|
|
169
|
+
signature: node.text.replace(/\s+/g, " ").replace(/;$/, "").trim(),
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
default:
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function containsFunctionDeclarator(node) {
|
|
177
|
+
if (node.type === "function_declarator")
|
|
178
|
+
return true;
|
|
179
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
180
|
+
const c = node.namedChild(i);
|
|
181
|
+
if (c && containsFunctionDeclarator(c))
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
function structFields(body) {
|
|
187
|
+
const out = [];
|
|
188
|
+
for (const field of namedChildren(body)) {
|
|
189
|
+
if (field.type !== "field_declaration")
|
|
190
|
+
continue;
|
|
191
|
+
const decl = field.childForFieldName("declarator");
|
|
192
|
+
const name = nameFromDeclarator(decl);
|
|
193
|
+
if (!name)
|
|
194
|
+
continue;
|
|
195
|
+
out.push(makeSymbol({
|
|
196
|
+
name,
|
|
197
|
+
kind: "field",
|
|
198
|
+
node: field,
|
|
199
|
+
rawKind: field.type,
|
|
200
|
+
signature: field.text.replace(/\s+/g, " ").replace(/;$/, "").trim(),
|
|
201
|
+
}));
|
|
202
|
+
}
|
|
203
|
+
return out;
|
|
204
|
+
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { namedChildren, nameOf, headerSignature, leadingComment } from "../parser.js";
|
|
2
|
+
import { makeSymbol } from "./common.js";
|
|
3
|
+
/* ─── helpers (shared with C extractor in spirit but kept local) ──────────── */
|
|
4
|
+
function childOfType(node, type) {
|
|
5
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
6
|
+
const c = node.child(i);
|
|
7
|
+
if (c && c.type === type)
|
|
8
|
+
return c;
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
function nameFromDeclarator(node) {
|
|
13
|
+
if (!node)
|
|
14
|
+
return null;
|
|
15
|
+
switch (node.type) {
|
|
16
|
+
case "identifier":
|
|
17
|
+
case "field_identifier":
|
|
18
|
+
case "type_identifier":
|
|
19
|
+
return node.text;
|
|
20
|
+
case "pointer_declarator":
|
|
21
|
+
case "array_declarator":
|
|
22
|
+
case "parenthesized_declarator":
|
|
23
|
+
case "reference_declarator":
|
|
24
|
+
return nameFromDeclarator(node.childForFieldName("declarator") ?? node.namedChild(0));
|
|
25
|
+
case "function_declarator":
|
|
26
|
+
case "init_declarator":
|
|
27
|
+
return nameFromDeclarator(node.childForFieldName("declarator"));
|
|
28
|
+
case "qualified_identifier": {
|
|
29
|
+
// Foo::bar — use "bar" as the leaf name
|
|
30
|
+
const last = node.childForFieldName("name");
|
|
31
|
+
return last ? last.text : node.text;
|
|
32
|
+
}
|
|
33
|
+
case "operator_name":
|
|
34
|
+
case "destructor_name":
|
|
35
|
+
return node.text;
|
|
36
|
+
default:
|
|
37
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
38
|
+
const c = node.namedChild(i);
|
|
39
|
+
if (c && (c.type === "identifier" || c.type === "field_identifier" || c.type === "type_identifier"))
|
|
40
|
+
return c.text;
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function containsFunctionDeclarator(node) {
|
|
46
|
+
if (node.type === "function_declarator")
|
|
47
|
+
return true;
|
|
48
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
49
|
+
const c = node.namedChild(i);
|
|
50
|
+
if (c && containsFunctionDeclarator(c))
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
function hasStaticStorage(node) {
|
|
56
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
57
|
+
const c = node.child(i);
|
|
58
|
+
if (c && c.type === "storage_class_specifier" && c.text === "static")
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
/* ─── imports (#include) ──────────────────────────────────────────────────── */
|
|
64
|
+
export function extractImportsCpp(root, _source) {
|
|
65
|
+
const out = [];
|
|
66
|
+
const visit = (n) => {
|
|
67
|
+
for (const c of namedChildren(n)) {
|
|
68
|
+
if (c.type === "preproc_include") {
|
|
69
|
+
const p = childOfType(c, "system_lib_string") ?? childOfType(c, "string_literal");
|
|
70
|
+
if (p) {
|
|
71
|
+
const raw = p.text.replace(/^[<"]|[>"]$/g, "");
|
|
72
|
+
const base = raw.split("/").pop() ?? raw;
|
|
73
|
+
out.push({ symbol: base.replace(/\.[hH](pp|xx|h)?$/, ""), from: raw });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (c.type === "namespace_definition" || c.type === "linkage_specification") {
|
|
77
|
+
const body = c.childForFieldName("body");
|
|
78
|
+
if (body)
|
|
79
|
+
visit(body);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
visit(root);
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
/* ─── symbol extraction ───────────────────────────────────────────────────── */
|
|
87
|
+
export function extractCpp(root, _source) {
|
|
88
|
+
return collect(namedChildren(root));
|
|
89
|
+
}
|
|
90
|
+
function collect(nodes) {
|
|
91
|
+
const out = [];
|
|
92
|
+
for (const n of nodes) {
|
|
93
|
+
const res = handle(n);
|
|
94
|
+
if (Array.isArray(res))
|
|
95
|
+
out.push(...res);
|
|
96
|
+
else if (res)
|
|
97
|
+
out.push(res);
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
function handle(node) {
|
|
102
|
+
switch (node.type) {
|
|
103
|
+
case "namespace_definition":
|
|
104
|
+
case "linkage_specification": {
|
|
105
|
+
// Recurse into body, flattening namespace contents to top level.
|
|
106
|
+
const body = node.childForFieldName("body");
|
|
107
|
+
return body ? collect(namedChildren(body)) : null;
|
|
108
|
+
}
|
|
109
|
+
case "class_specifier": {
|
|
110
|
+
const name = nameOf(node);
|
|
111
|
+
if (!name)
|
|
112
|
+
return null;
|
|
113
|
+
const body = node.childForFieldName("body");
|
|
114
|
+
return makeSymbol({
|
|
115
|
+
name,
|
|
116
|
+
kind: "class",
|
|
117
|
+
node,
|
|
118
|
+
rawKind: node.type,
|
|
119
|
+
doc: leadingComment(node),
|
|
120
|
+
children: body ? classMembers(body, "private") : [],
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
case "struct_specifier": {
|
|
124
|
+
const name = nameOf(node);
|
|
125
|
+
if (!name)
|
|
126
|
+
return null;
|
|
127
|
+
const body = node.childForFieldName("body");
|
|
128
|
+
return makeSymbol({
|
|
129
|
+
name,
|
|
130
|
+
kind: "struct",
|
|
131
|
+
node,
|
|
132
|
+
rawKind: node.type,
|
|
133
|
+
doc: leadingComment(node),
|
|
134
|
+
children: body ? classMembers(body, "public") : [],
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
case "enum_specifier": {
|
|
138
|
+
const name = nameOf(node);
|
|
139
|
+
if (!name)
|
|
140
|
+
return null;
|
|
141
|
+
return makeSymbol({
|
|
142
|
+
name,
|
|
143
|
+
kind: "enum",
|
|
144
|
+
node,
|
|
145
|
+
rawKind: node.type,
|
|
146
|
+
doc: leadingComment(node),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
case "function_definition": {
|
|
150
|
+
const decl = node.childForFieldName("declarator");
|
|
151
|
+
const name = nameFromDeclarator(decl);
|
|
152
|
+
if (!name)
|
|
153
|
+
return null;
|
|
154
|
+
return makeSymbol({
|
|
155
|
+
name,
|
|
156
|
+
kind: "function",
|
|
157
|
+
node,
|
|
158
|
+
rawKind: node.type,
|
|
159
|
+
signature: headerSignature(node, node.childForFieldName("body")),
|
|
160
|
+
visibility: hasStaticStorage(node) ? "private" : "public",
|
|
161
|
+
exported: !hasStaticStorage(node),
|
|
162
|
+
doc: leadingComment(node),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
case "template_declaration": {
|
|
166
|
+
// The actual declaration is buried; recurse to find it.
|
|
167
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
168
|
+
const c = node.namedChild(i);
|
|
169
|
+
if (!c)
|
|
170
|
+
continue;
|
|
171
|
+
if (c.type === "class_specifier" ||
|
|
172
|
+
c.type === "struct_specifier" ||
|
|
173
|
+
c.type === "function_definition" ||
|
|
174
|
+
c.type === "declaration") {
|
|
175
|
+
const res = handle(c);
|
|
176
|
+
if (res)
|
|
177
|
+
return res;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
case "alias_declaration":
|
|
183
|
+
case "type_definition": {
|
|
184
|
+
const decl = node.childForFieldName("declarator");
|
|
185
|
+
const name = nameOf(node) ?? nameFromDeclarator(decl);
|
|
186
|
+
if (!name)
|
|
187
|
+
return null;
|
|
188
|
+
return makeSymbol({
|
|
189
|
+
name,
|
|
190
|
+
kind: "type",
|
|
191
|
+
node,
|
|
192
|
+
rawKind: node.type,
|
|
193
|
+
signature: node.text.replace(/\s+/g, " ").replace(/;$/, "").trim(),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
case "declaration": {
|
|
197
|
+
const decl = node.childForFieldName("declarator");
|
|
198
|
+
const name = nameFromDeclarator(decl);
|
|
199
|
+
if (!name)
|
|
200
|
+
return null;
|
|
201
|
+
if (decl && containsFunctionDeclarator(decl))
|
|
202
|
+
return null; // prototype
|
|
203
|
+
return makeSymbol({
|
|
204
|
+
name,
|
|
205
|
+
kind: "var",
|
|
206
|
+
node,
|
|
207
|
+
rawKind: node.type,
|
|
208
|
+
signature: node.text.replace(/\s+/g, " ").replace(/;$/, "").trim(),
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
case "preproc_def":
|
|
212
|
+
case "preproc_function_def": {
|
|
213
|
+
const name = nameOf(node);
|
|
214
|
+
if (!name)
|
|
215
|
+
return null;
|
|
216
|
+
return makeSymbol({
|
|
217
|
+
name,
|
|
218
|
+
kind: "const",
|
|
219
|
+
node,
|
|
220
|
+
rawKind: node.type,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
default:
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/** Walk class/struct body, tracking the current access_specifier (default given). */
|
|
228
|
+
function classMembers(body, defaultAccess) {
|
|
229
|
+
let current = defaultAccess;
|
|
230
|
+
const out = [];
|
|
231
|
+
for (let i = 0; i < body.childCount; i++) {
|
|
232
|
+
const c = body.child(i);
|
|
233
|
+
if (!c)
|
|
234
|
+
continue;
|
|
235
|
+
if (c.type === "access_specifier") {
|
|
236
|
+
current = /\bpublic\b/.test(c.text) ? "public" : "private";
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (!c.isNamed)
|
|
240
|
+
continue;
|
|
241
|
+
if (c.type === "field_declaration") {
|
|
242
|
+
const dec = c.childForFieldName("declarator");
|
|
243
|
+
const name = nameFromDeclarator(dec);
|
|
244
|
+
if (!name)
|
|
245
|
+
continue;
|
|
246
|
+
const isFunc = dec && containsFunctionDeclarator(dec);
|
|
247
|
+
out.push(makeSymbol({
|
|
248
|
+
name,
|
|
249
|
+
kind: isFunc ? "method" : "field",
|
|
250
|
+
node: c,
|
|
251
|
+
rawKind: c.type,
|
|
252
|
+
signature: c.text.replace(/\s+/g, " ").replace(/;$/, "").trim(),
|
|
253
|
+
visibility: current,
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
else if (c.type === "function_definition") {
|
|
257
|
+
const dec = c.childForFieldName("declarator");
|
|
258
|
+
const name = nameFromDeclarator(dec);
|
|
259
|
+
if (!name)
|
|
260
|
+
continue;
|
|
261
|
+
out.push(makeSymbol({
|
|
262
|
+
name,
|
|
263
|
+
kind: "method",
|
|
264
|
+
node: c,
|
|
265
|
+
rawKind: c.type,
|
|
266
|
+
signature: headerSignature(c, c.childForFieldName("body")),
|
|
267
|
+
visibility: current,
|
|
268
|
+
}));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return out;
|
|
272
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { namedChildren, headerSignature, leadingComment } from "../parser.js";
|
|
2
|
+
import { makeSymbol } from "./common.js";
|
|
3
|
+
/* ─── helpers ─────────────────────────────────────────────────────────────── */
|
|
4
|
+
function childOfType(node, type) {
|
|
5
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
6
|
+
const c = node.child(i);
|
|
7
|
+
if (c && c.type === type)
|
|
8
|
+
return c;
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
function firstChildOfTypes(node, types) {
|
|
13
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
14
|
+
const c = node.namedChild(i);
|
|
15
|
+
if (c && types.has(c.type))
|
|
16
|
+
return c;
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const TYPE_NAME_NODES = new Set(["type_identifier", "simple_identifier"]);
|
|
21
|
+
const SIMPLE_NAME_NODES = new Set(["simple_identifier"]);
|
|
22
|
+
function modifiersText(node) {
|
|
23
|
+
const m = childOfType(node, "modifiers");
|
|
24
|
+
return m ? m.text : "";
|
|
25
|
+
}
|
|
26
|
+
function vis(node) {
|
|
27
|
+
const m = modifiersText(node);
|
|
28
|
+
if (/\b(private|protected|internal)\b/.test(m))
|
|
29
|
+
return "private";
|
|
30
|
+
return "public"; // Kotlin default is public
|
|
31
|
+
}
|
|
32
|
+
function exported(node) {
|
|
33
|
+
const m = modifiersText(node);
|
|
34
|
+
if (/\b(private|protected|internal)\b/.test(m))
|
|
35
|
+
return false;
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
function classKind(node) {
|
|
39
|
+
const m = modifiersText(node);
|
|
40
|
+
if (/\bdata\b/.test(node.text.slice(0, 80)))
|
|
41
|
+
return "class";
|
|
42
|
+
if (/\benum\b/.test(node.text.slice(0, 80)))
|
|
43
|
+
return "enum";
|
|
44
|
+
return "class";
|
|
45
|
+
}
|
|
46
|
+
/* ─── imports + package ───────────────────────────────────────────────────── */
|
|
47
|
+
export function extractDirectivesKotlin(root, _source) {
|
|
48
|
+
for (const c of namedChildren(root)) {
|
|
49
|
+
if (c.type === "package_header") {
|
|
50
|
+
const id = childOfType(c, "identifier");
|
|
51
|
+
if (id)
|
|
52
|
+
return [`package:${id.text}`];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
export function extractImportsKotlin(root, _source) {
|
|
58
|
+
const out = [];
|
|
59
|
+
const list = childOfType(root, "import_list");
|
|
60
|
+
if (!list)
|
|
61
|
+
return out;
|
|
62
|
+
for (const h of namedChildren(list)) {
|
|
63
|
+
if (h.type !== "import_header")
|
|
64
|
+
continue;
|
|
65
|
+
const id = childOfType(h, "identifier");
|
|
66
|
+
if (!id)
|
|
67
|
+
continue;
|
|
68
|
+
const isWildcard = /\.\*\s*$/.test(h.text);
|
|
69
|
+
const from = id.text;
|
|
70
|
+
const sym = isWildcard ? "*" : (from.split(".").pop() ?? from);
|
|
71
|
+
out.push({ symbol: sym, from, isNamespaceImport: isWildcard });
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
/* ─── symbol extraction ───────────────────────────────────────────────────── */
|
|
76
|
+
export function extractKotlin(root, _source) {
|
|
77
|
+
return collect(namedChildren(root), false);
|
|
78
|
+
}
|
|
79
|
+
function collect(nodes, insideClass) {
|
|
80
|
+
const out = [];
|
|
81
|
+
for (const n of nodes) {
|
|
82
|
+
const res = handle(n, insideClass);
|
|
83
|
+
if (res)
|
|
84
|
+
out.push(res);
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
function handle(node, insideClass) {
|
|
89
|
+
switch (node.type) {
|
|
90
|
+
case "class_declaration": {
|
|
91
|
+
const nameNode = firstChildOfTypes(node, TYPE_NAME_NODES);
|
|
92
|
+
if (!nameNode)
|
|
93
|
+
return null;
|
|
94
|
+
const body = childOfType(node, "class_body") ?? childOfType(node, "enum_class_body");
|
|
95
|
+
return makeSymbol({
|
|
96
|
+
name: nameNode.text,
|
|
97
|
+
kind: classKind(node),
|
|
98
|
+
node,
|
|
99
|
+
rawKind: node.type,
|
|
100
|
+
visibility: vis(node),
|
|
101
|
+
exported: exported(node),
|
|
102
|
+
doc: leadingComment(node),
|
|
103
|
+
children: body ? collect(namedChildren(body), true) : [],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
case "object_declaration": {
|
|
107
|
+
const nameNode = firstChildOfTypes(node, TYPE_NAME_NODES);
|
|
108
|
+
if (!nameNode)
|
|
109
|
+
return null;
|
|
110
|
+
const body = childOfType(node, "class_body");
|
|
111
|
+
return makeSymbol({
|
|
112
|
+
name: nameNode.text,
|
|
113
|
+
kind: "class",
|
|
114
|
+
node,
|
|
115
|
+
rawKind: node.type,
|
|
116
|
+
visibility: vis(node),
|
|
117
|
+
exported: exported(node),
|
|
118
|
+
doc: leadingComment(node),
|
|
119
|
+
children: body ? collect(namedChildren(body), true) : [],
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
case "function_declaration": {
|
|
123
|
+
const nameNode = firstChildOfTypes(node, SIMPLE_NAME_NODES);
|
|
124
|
+
if (!nameNode)
|
|
125
|
+
return null;
|
|
126
|
+
const body = childOfType(node, "function_body");
|
|
127
|
+
return makeSymbol({
|
|
128
|
+
name: nameNode.text,
|
|
129
|
+
kind: insideClass ? "method" : "function",
|
|
130
|
+
node,
|
|
131
|
+
rawKind: node.type,
|
|
132
|
+
signature: headerSignature(node, body),
|
|
133
|
+
visibility: vis(node),
|
|
134
|
+
exported: exported(node),
|
|
135
|
+
doc: leadingComment(node),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
case "property_declaration": {
|
|
139
|
+
// variable_declaration → simple_identifier
|
|
140
|
+
const vd = childOfType(node, "variable_declaration");
|
|
141
|
+
const nameNode = vd ? firstChildOfTypes(vd, SIMPLE_NAME_NODES) : firstChildOfTypes(node, SIMPLE_NAME_NODES);
|
|
142
|
+
if (!nameNode)
|
|
143
|
+
return null;
|
|
144
|
+
const m = modifiersText(node);
|
|
145
|
+
const kind = insideClass ? "field" : (/\bconst\b/.test(m) ? "const" : "var");
|
|
146
|
+
return makeSymbol({
|
|
147
|
+
name: nameNode.text,
|
|
148
|
+
kind,
|
|
149
|
+
node,
|
|
150
|
+
rawKind: node.type,
|
|
151
|
+
signature: node.text.replace(/\s+/g, " ").trim(),
|
|
152
|
+
visibility: vis(node),
|
|
153
|
+
exported: exported(node),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
default:
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { namedChildren, nameOf, headerSignature, leadingComment } from "../parser.js";
|
|
2
|
+
import { makeSymbol } from "./common.js";
|
|
3
|
+
/* ─── helpers ─────────────────────────────────────────────────────────────── */
|
|
4
|
+
function childOfType(node, type) {
|
|
5
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
6
|
+
const c = node.child(i);
|
|
7
|
+
if (c && c.type === type)
|
|
8
|
+
return c;
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
function modifiersText(node) {
|
|
13
|
+
const m = childOfType(node, "modifiers");
|
|
14
|
+
return m ? m.text : "";
|
|
15
|
+
}
|
|
16
|
+
function vis(node) {
|
|
17
|
+
const m = modifiersText(node);
|
|
18
|
+
if (/\b(private|fileprivate)\b/.test(m))
|
|
19
|
+
return "private";
|
|
20
|
+
return "public"; // treat internal/public/open as public
|
|
21
|
+
}
|
|
22
|
+
function exported(node) {
|
|
23
|
+
const m = modifiersText(node);
|
|
24
|
+
return /\b(public|open)\b/.test(m) || !/\b(private|fileprivate|internal)\b/.test(m);
|
|
25
|
+
}
|
|
26
|
+
/** Swift uses class_declaration for `class`, `struct`, `enum`, `actor`, `extension`. */
|
|
27
|
+
function classDeclKind(node) {
|
|
28
|
+
const head = node.text.slice(0, 80);
|
|
29
|
+
if (/\bstruct\b/.test(head))
|
|
30
|
+
return "struct";
|
|
31
|
+
if (/\benum\b/.test(head))
|
|
32
|
+
return "enum";
|
|
33
|
+
const body = childOfType(node, "enum_class_body");
|
|
34
|
+
if (body)
|
|
35
|
+
return "enum";
|
|
36
|
+
return "class";
|
|
37
|
+
}
|
|
38
|
+
/* ─── imports ─────────────────────────────────────────────────────────────── */
|
|
39
|
+
export function extractImportsSwift(root, _source) {
|
|
40
|
+
const out = [];
|
|
41
|
+
for (const c of namedChildren(root)) {
|
|
42
|
+
if (c.type !== "import_declaration")
|
|
43
|
+
continue;
|
|
44
|
+
const id = childOfType(c, "identifier");
|
|
45
|
+
const text = id ? id.text : c.text.replace(/^import\s+/, "").trim();
|
|
46
|
+
out.push({ symbol: text.split(".").pop() ?? text, from: text });
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
/* ─── symbol extraction ───────────────────────────────────────────────────── */
|
|
51
|
+
export function extractSwift(root, _source) {
|
|
52
|
+
return collect(namedChildren(root), false);
|
|
53
|
+
}
|
|
54
|
+
function collect(nodes, insideClass) {
|
|
55
|
+
const out = [];
|
|
56
|
+
for (const n of nodes) {
|
|
57
|
+
const res = handle(n, insideClass);
|
|
58
|
+
if (res)
|
|
59
|
+
out.push(res);
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
function handle(node, insideClass) {
|
|
64
|
+
switch (node.type) {
|
|
65
|
+
case "class_declaration": {
|
|
66
|
+
const name = nameOf(node);
|
|
67
|
+
if (!name)
|
|
68
|
+
return null;
|
|
69
|
+
const kind = classDeclKind(node);
|
|
70
|
+
const body = childOfType(node, "class_body") ?? childOfType(node, "enum_class_body");
|
|
71
|
+
return makeSymbol({
|
|
72
|
+
name,
|
|
73
|
+
kind,
|
|
74
|
+
node,
|
|
75
|
+
rawKind: node.type,
|
|
76
|
+
visibility: vis(node),
|
|
77
|
+
exported: exported(node),
|
|
78
|
+
doc: leadingComment(node),
|
|
79
|
+
children: body ? collect(namedChildren(body), true) : [],
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
case "protocol_declaration": {
|
|
83
|
+
const name = nameOf(node);
|
|
84
|
+
if (!name)
|
|
85
|
+
return null;
|
|
86
|
+
const body = childOfType(node, "protocol_body");
|
|
87
|
+
const kids = [];
|
|
88
|
+
if (body) {
|
|
89
|
+
for (const m of namedChildren(body)) {
|
|
90
|
+
if (m.type === "protocol_function_declaration") {
|
|
91
|
+
const n = nameOf(m);
|
|
92
|
+
if (n) {
|
|
93
|
+
kids.push(makeSymbol({
|
|
94
|
+
name: n,
|
|
95
|
+
kind: "method",
|
|
96
|
+
node: m,
|
|
97
|
+
rawKind: m.type,
|
|
98
|
+
signature: headerSignature(m, null),
|
|
99
|
+
visibility: "public",
|
|
100
|
+
exported: true,
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return makeSymbol({
|
|
107
|
+
name,
|
|
108
|
+
kind: "interface",
|
|
109
|
+
node,
|
|
110
|
+
rawKind: node.type,
|
|
111
|
+
visibility: vis(node),
|
|
112
|
+
exported: exported(node),
|
|
113
|
+
doc: leadingComment(node),
|
|
114
|
+
children: kids,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
case "function_declaration": {
|
|
118
|
+
const name = nameOf(node);
|
|
119
|
+
if (!name)
|
|
120
|
+
return null;
|
|
121
|
+
const body = childOfType(node, "function_body");
|
|
122
|
+
return makeSymbol({
|
|
123
|
+
name,
|
|
124
|
+
kind: insideClass ? "method" : "function",
|
|
125
|
+
node,
|
|
126
|
+
rawKind: node.type,
|
|
127
|
+
signature: headerSignature(node, body),
|
|
128
|
+
visibility: vis(node),
|
|
129
|
+
exported: exported(node),
|
|
130
|
+
doc: leadingComment(node),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
case "init_declaration": {
|
|
134
|
+
return makeSymbol({
|
|
135
|
+
name: "init",
|
|
136
|
+
kind: "method",
|
|
137
|
+
node,
|
|
138
|
+
rawKind: node.type,
|
|
139
|
+
signature: headerSignature(node, childOfType(node, "function_body")),
|
|
140
|
+
visibility: vis(node),
|
|
141
|
+
exported: exported(node),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
case "property_declaration": {
|
|
145
|
+
// name is `pattern` field; the pattern contains simple_identifier
|
|
146
|
+
const pat = node.childForFieldName("name");
|
|
147
|
+
let name = null;
|
|
148
|
+
if (pat) {
|
|
149
|
+
const id = pat.type === "simple_identifier" ? pat : findFirstNamed(pat, "simple_identifier");
|
|
150
|
+
name = id ? id.text : null;
|
|
151
|
+
}
|
|
152
|
+
if (!name)
|
|
153
|
+
return null;
|
|
154
|
+
const isLet = /\blet\b/.test(node.text.slice(0, 30));
|
|
155
|
+
return makeSymbol({
|
|
156
|
+
name,
|
|
157
|
+
kind: insideClass ? "field" : (isLet ? "const" : "var"),
|
|
158
|
+
node,
|
|
159
|
+
rawKind: node.type,
|
|
160
|
+
signature: node.text.replace(/\s+/g, " ").trim(),
|
|
161
|
+
visibility: vis(node),
|
|
162
|
+
exported: exported(node),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
case "enum_entry": {
|
|
166
|
+
const name = nameOf(node);
|
|
167
|
+
if (!name)
|
|
168
|
+
return null;
|
|
169
|
+
return makeSymbol({
|
|
170
|
+
name,
|
|
171
|
+
kind: "field",
|
|
172
|
+
node,
|
|
173
|
+
rawKind: node.type,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
default:
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function findFirstNamed(node, type) {
|
|
181
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
182
|
+
const c = node.namedChild(i);
|
|
183
|
+
if (!c)
|
|
184
|
+
continue;
|
|
185
|
+
if (c.type === type)
|
|
186
|
+
return c;
|
|
187
|
+
const deep = findFirstNamed(c, type);
|
|
188
|
+
if (deep)
|
|
189
|
+
return deep;
|
|
190
|
+
}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
package/dist/registry.js
CHANGED
|
@@ -5,6 +5,10 @@ import { extractGo, extractImportsGo } from "./extractors/go.js";
|
|
|
5
5
|
import { extractRust, extractImportsRust } from "./extractors/rust.js";
|
|
6
6
|
import { extractJava, extractDirectivesJava, extractImportsJava } from "./extractors/java.js";
|
|
7
7
|
import { extractCSharp, extractDirectivesCSharp, extractImportsCSharp } from "./extractors/csharp.js";
|
|
8
|
+
import { extractC, extractImportsC } from "./extractors/c.js";
|
|
9
|
+
import { extractCpp, extractImportsCpp } from "./extractors/cpp.js";
|
|
10
|
+
import { extractKotlin, extractDirectivesKotlin, extractImportsKotlin } from "./extractors/kotlin.js";
|
|
11
|
+
import { extractSwift, extractImportsSwift } from "./extractors/swift.js";
|
|
8
12
|
const TS_ENTRY = (language, grammar) => ({
|
|
9
13
|
language,
|
|
10
14
|
grammar,
|
|
@@ -26,19 +30,30 @@ const BY_EXT = {
|
|
|
26
30
|
".go": { language: "go", grammar: "go", extract: extractGo, extractImports: extractImportsGo },
|
|
27
31
|
".rs": { language: "rust", grammar: "rust", extract: extractRust, extractImports: extractImportsRust },
|
|
28
32
|
".java": {
|
|
29
|
-
language: "java",
|
|
30
|
-
|
|
31
|
-
extract: extractJava,
|
|
32
|
-
extractDirectives: extractDirectivesJava,
|
|
33
|
-
extractImports: extractImportsJava,
|
|
33
|
+
language: "java", grammar: "java",
|
|
34
|
+
extract: extractJava, extractDirectives: extractDirectivesJava, extractImports: extractImportsJava,
|
|
34
35
|
},
|
|
35
36
|
".cs": {
|
|
36
|
-
language: "csharp",
|
|
37
|
-
|
|
38
|
-
extract: extractCSharp,
|
|
39
|
-
extractDirectives: extractDirectivesCSharp,
|
|
40
|
-
extractImports: extractImportsCSharp,
|
|
37
|
+
language: "csharp", grammar: "c_sharp",
|
|
38
|
+
extract: extractCSharp, extractDirectives: extractDirectivesCSharp, extractImports: extractImportsCSharp,
|
|
41
39
|
},
|
|
40
|
+
".c": { language: "c", grammar: "c", extract: extractC, extractImports: extractImportsC },
|
|
41
|
+
".h": { language: "c", grammar: "c", extract: extractC, extractImports: extractImportsC },
|
|
42
|
+
".cpp": { language: "cpp", grammar: "cpp", extract: extractCpp, extractImports: extractImportsCpp },
|
|
43
|
+
".cxx": { language: "cpp", grammar: "cpp", extract: extractCpp, extractImports: extractImportsCpp },
|
|
44
|
+
".cc": { language: "cpp", grammar: "cpp", extract: extractCpp, extractImports: extractImportsCpp },
|
|
45
|
+
".hpp": { language: "cpp", grammar: "cpp", extract: extractCpp, extractImports: extractImportsCpp },
|
|
46
|
+
".hxx": { language: "cpp", grammar: "cpp", extract: extractCpp, extractImports: extractImportsCpp },
|
|
47
|
+
".hh": { language: "cpp", grammar: "cpp", extract: extractCpp, extractImports: extractImportsCpp },
|
|
48
|
+
".kt": {
|
|
49
|
+
language: "kotlin", grammar: "kotlin",
|
|
50
|
+
extract: extractKotlin, extractDirectives: extractDirectivesKotlin, extractImports: extractImportsKotlin,
|
|
51
|
+
},
|
|
52
|
+
".kts": {
|
|
53
|
+
language: "kotlin", grammar: "kotlin",
|
|
54
|
+
extract: extractKotlin, extractDirectives: extractDirectivesKotlin, extractImports: extractImportsKotlin,
|
|
55
|
+
},
|
|
56
|
+
".swift": { language: "swift", grammar: "swift", extract: extractSwift, extractImports: extractImportsSwift },
|
|
42
57
|
};
|
|
43
58
|
export function detectLanguage(filePath) {
|
|
44
59
|
return BY_EXT[path.extname(filePath).toLowerCase()] ?? null;
|
package/package.json
CHANGED