universal-ast-mapper 0.5.3 → 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 +34 -6
- package/dist/callgraph.js +266 -86
- package/dist/crosslang.js +312 -0
- package/dist/extractors/c.js +204 -0
- package/dist/extractors/cpp.js +272 -0
- package/dist/extractors/csharp.js +209 -0
- package/dist/extractors/java.js +152 -0
- package/dist/extractors/kotlin.js +159 -0
- package/dist/extractors/rust.js +249 -0
- package/dist/extractors/swift.js +192 -0
- package/dist/graph.js +77 -38
- package/dist/registry.js +33 -1
- package/dist/resolver.js +117 -60
- package/package.json +1 -1
|
@@ -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,249 @@
|
|
|
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
|
+
/** Rust: `pub`, `pub(crate)`, ... = public; anything else = module-private. */
|
|
13
|
+
function isPub(node) {
|
|
14
|
+
const vis = childOfType(node, "visibility_modifier");
|
|
15
|
+
return !!vis && vis.text.startsWith("pub");
|
|
16
|
+
}
|
|
17
|
+
function vis(node) {
|
|
18
|
+
return isPub(node) ? "public" : "private";
|
|
19
|
+
}
|
|
20
|
+
/* ─── import extraction ───────────────────────────────────────────────────── */
|
|
21
|
+
export function extractImportsRust(root, _source) {
|
|
22
|
+
const out = [];
|
|
23
|
+
for (const child of namedChildren(root)) {
|
|
24
|
+
if (child.type === "use_declaration") {
|
|
25
|
+
const arg = child.namedChild(0);
|
|
26
|
+
if (arg)
|
|
27
|
+
resolveUse(arg, "", out);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
function resolveUse(node, prefix, out) {
|
|
33
|
+
switch (node.type) {
|
|
34
|
+
case "identifier":
|
|
35
|
+
case "type_identifier":
|
|
36
|
+
out.push({ symbol: node.text, from: join(prefix, node.text) });
|
|
37
|
+
return;
|
|
38
|
+
case "scoped_identifier": {
|
|
39
|
+
const full = node.text;
|
|
40
|
+
const sym = full.split("::").pop() ?? full;
|
|
41
|
+
out.push({ symbol: sym, from: full });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
case "use_as_clause": {
|
|
45
|
+
const path = node.namedChild(0);
|
|
46
|
+
const alias = node.namedChild(1);
|
|
47
|
+
const full = path ? path.text : "";
|
|
48
|
+
const sym = full.split("::").pop() ?? full;
|
|
49
|
+
out.push({ symbol: sym, from: full, alias: alias?.text });
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
case "use_wildcard": {
|
|
53
|
+
const path = node.namedChild(0);
|
|
54
|
+
out.push({ symbol: "*", from: path ? path.text : prefix, isNamespaceImport: true });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
case "scoped_use_list": {
|
|
58
|
+
const base = node.namedChild(0);
|
|
59
|
+
const list = childOfType(node, "use_list");
|
|
60
|
+
const newPrefix = base ? base.text : prefix;
|
|
61
|
+
if (list) {
|
|
62
|
+
for (const item of namedChildren(list))
|
|
63
|
+
resolveUse(item, newPrefix, out);
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
case "use_list":
|
|
68
|
+
for (const item of namedChildren(node))
|
|
69
|
+
resolveUse(item, prefix, out);
|
|
70
|
+
return;
|
|
71
|
+
default:
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function join(prefix, name) {
|
|
76
|
+
return prefix ? `${prefix}::${name}` : name;
|
|
77
|
+
}
|
|
78
|
+
/* ─── symbol extraction ───────────────────────────────────────────────────── */
|
|
79
|
+
export function extractRust(root, _source) {
|
|
80
|
+
return collect(namedChildren(root));
|
|
81
|
+
}
|
|
82
|
+
function collect(nodes) {
|
|
83
|
+
const out = [];
|
|
84
|
+
for (const n of nodes) {
|
|
85
|
+
const res = handle(n);
|
|
86
|
+
if (Array.isArray(res))
|
|
87
|
+
out.push(...res);
|
|
88
|
+
else if (res)
|
|
89
|
+
out.push(res);
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
function handle(node) {
|
|
94
|
+
switch (node.type) {
|
|
95
|
+
case "struct_item": {
|
|
96
|
+
const name = nameOf(node) ?? "(struct)";
|
|
97
|
+
const body = node.childForFieldName("body");
|
|
98
|
+
return makeSymbol({
|
|
99
|
+
name,
|
|
100
|
+
kind: "struct",
|
|
101
|
+
node,
|
|
102
|
+
rawKind: node.type,
|
|
103
|
+
visibility: vis(node),
|
|
104
|
+
exported: isPub(node),
|
|
105
|
+
doc: leadingComment(node),
|
|
106
|
+
children: body && body.type === "field_declaration_list" ? structFields(body) : [],
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
case "trait_item": {
|
|
110
|
+
const name = nameOf(node) ?? "(trait)";
|
|
111
|
+
const body = node.childForFieldName("body");
|
|
112
|
+
return makeSymbol({
|
|
113
|
+
name,
|
|
114
|
+
kind: "interface",
|
|
115
|
+
node,
|
|
116
|
+
rawKind: node.type,
|
|
117
|
+
visibility: vis(node),
|
|
118
|
+
exported: isPub(node),
|
|
119
|
+
doc: leadingComment(node),
|
|
120
|
+
children: body ? traitMethods(body) : [],
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
case "enum_item":
|
|
124
|
+
return makeSymbol({
|
|
125
|
+
name: nameOf(node) ?? "(enum)",
|
|
126
|
+
kind: "enum",
|
|
127
|
+
node,
|
|
128
|
+
rawKind: node.type,
|
|
129
|
+
visibility: vis(node),
|
|
130
|
+
exported: isPub(node),
|
|
131
|
+
doc: leadingComment(node),
|
|
132
|
+
});
|
|
133
|
+
case "function_item": {
|
|
134
|
+
const name = nameOf(node) ?? "(fn)";
|
|
135
|
+
return makeSymbol({
|
|
136
|
+
name,
|
|
137
|
+
kind: "function",
|
|
138
|
+
node,
|
|
139
|
+
rawKind: node.type,
|
|
140
|
+
signature: headerSignature(node, node.childForFieldName("body")),
|
|
141
|
+
visibility: vis(node),
|
|
142
|
+
exported: isPub(node),
|
|
143
|
+
doc: leadingComment(node),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
case "impl_item": {
|
|
147
|
+
// Surface impl methods as `Type::method` so the association is visible.
|
|
148
|
+
const typeNode = node.childForFieldName("type");
|
|
149
|
+
const typeName = typeNode ? typeNode.text : "";
|
|
150
|
+
const body = node.childForFieldName("body");
|
|
151
|
+
const out = [];
|
|
152
|
+
if (body) {
|
|
153
|
+
for (const m of namedChildren(body)) {
|
|
154
|
+
if (m.type !== "function_item")
|
|
155
|
+
continue;
|
|
156
|
+
const mName = nameOf(m) ?? "(fn)";
|
|
157
|
+
out.push(makeSymbol({
|
|
158
|
+
name: typeName ? `${typeName}::${mName}` : mName,
|
|
159
|
+
kind: "method",
|
|
160
|
+
node: m,
|
|
161
|
+
rawKind: m.type,
|
|
162
|
+
signature: headerSignature(m, m.childForFieldName("body")),
|
|
163
|
+
visibility: vis(m),
|
|
164
|
+
exported: isPub(m),
|
|
165
|
+
doc: leadingComment(m),
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
case "const_item":
|
|
172
|
+
return makeSymbol({
|
|
173
|
+
name: nameOf(node) ?? "(const)",
|
|
174
|
+
kind: "const",
|
|
175
|
+
node,
|
|
176
|
+
rawKind: node.type,
|
|
177
|
+
signature: headerSignature(node, node.childForFieldName("value")),
|
|
178
|
+
visibility: vis(node),
|
|
179
|
+
exported: isPub(node),
|
|
180
|
+
});
|
|
181
|
+
case "static_item":
|
|
182
|
+
return makeSymbol({
|
|
183
|
+
name: nameOf(node) ?? "(static)",
|
|
184
|
+
kind: "var",
|
|
185
|
+
node,
|
|
186
|
+
rawKind: node.type,
|
|
187
|
+
signature: headerSignature(node, node.childForFieldName("value")),
|
|
188
|
+
visibility: vis(node),
|
|
189
|
+
exported: isPub(node),
|
|
190
|
+
});
|
|
191
|
+
case "type_item":
|
|
192
|
+
return makeSymbol({
|
|
193
|
+
name: nameOf(node) ?? "(type)",
|
|
194
|
+
kind: "type",
|
|
195
|
+
node,
|
|
196
|
+
rawKind: node.type,
|
|
197
|
+
signature: headerSignature(node, null),
|
|
198
|
+
visibility: vis(node),
|
|
199
|
+
exported: isPub(node),
|
|
200
|
+
});
|
|
201
|
+
case "mod_item": {
|
|
202
|
+
// Flatten module contents to the top level.
|
|
203
|
+
const body = node.childForFieldName("body");
|
|
204
|
+
return body ? collect(namedChildren(body)) : null;
|
|
205
|
+
}
|
|
206
|
+
default:
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function structFields(list) {
|
|
211
|
+
const out = [];
|
|
212
|
+
for (const field of namedChildren(list)) {
|
|
213
|
+
if (field.type !== "field_declaration")
|
|
214
|
+
continue;
|
|
215
|
+
const name = nameOf(field);
|
|
216
|
+
if (!name)
|
|
217
|
+
continue;
|
|
218
|
+
out.push(makeSymbol({
|
|
219
|
+
name,
|
|
220
|
+
kind: "field",
|
|
221
|
+
node: field,
|
|
222
|
+
rawKind: field.type,
|
|
223
|
+
signature: field.text.replace(/\s+/g, " ").trim(),
|
|
224
|
+
visibility: vis(field),
|
|
225
|
+
exported: isPub(field),
|
|
226
|
+
}));
|
|
227
|
+
}
|
|
228
|
+
return out;
|
|
229
|
+
}
|
|
230
|
+
function traitMethods(body) {
|
|
231
|
+
const out = [];
|
|
232
|
+
for (const m of namedChildren(body)) {
|
|
233
|
+
if (m.type !== "function_signature_item" && m.type !== "function_item")
|
|
234
|
+
continue;
|
|
235
|
+
const name = nameOf(m);
|
|
236
|
+
if (!name)
|
|
237
|
+
continue;
|
|
238
|
+
out.push(makeSymbol({
|
|
239
|
+
name,
|
|
240
|
+
kind: "method",
|
|
241
|
+
node: m,
|
|
242
|
+
rawKind: m.type,
|
|
243
|
+
signature: headerSignature(m, m.childForFieldName("body")),
|
|
244
|
+
visibility: "public",
|
|
245
|
+
exported: true,
|
|
246
|
+
}));
|
|
247
|
+
}
|
|
248
|
+
return out;
|
|
249
|
+
}
|
|
@@ -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
|
+
}
|