universal-ast-mapper 2.0.0 → 2.0.2

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.
Files changed (75) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +261 -12
  3. package/dist/ai-refactor.js +185 -0
  4. package/dist/ai-testgen.js +105 -0
  5. package/dist/analysis.js +134 -0
  6. package/dist/arch-rules.js +82 -0
  7. package/dist/callgraph.js +467 -0
  8. package/dist/check.js +112 -0
  9. package/dist/cli.js +2284 -0
  10. package/dist/complexity.js +98 -0
  11. package/dist/config.js +53 -0
  12. package/dist/contextpack.js +79 -0
  13. package/dist/coupling.js +35 -0
  14. package/dist/covmerge.js +176 -0
  15. package/dist/crosslang.js +425 -0
  16. package/dist/dashboard.js +259 -0
  17. package/dist/diagram.js +264 -0
  18. package/dist/diskcache.js +97 -0
  19. package/dist/docgen.js +156 -0
  20. package/dist/embeddings.js +136 -0
  21. package/dist/explain.js +123 -0
  22. package/dist/explorer.js +123 -0
  23. package/dist/extractors/c.js +204 -0
  24. package/dist/extractors/common.js +56 -0
  25. package/dist/extractors/cpp.js +272 -0
  26. package/dist/extractors/csharp.js +209 -0
  27. package/dist/extractors/go.js +212 -0
  28. package/dist/extractors/java.js +152 -0
  29. package/dist/extractors/kotlin.js +159 -0
  30. package/dist/extractors/php.js +208 -0
  31. package/dist/extractors/python.js +153 -0
  32. package/dist/extractors/ruby.js +146 -0
  33. package/dist/extractors/rust.js +249 -0
  34. package/dist/extractors/swift.js +192 -0
  35. package/dist/extractors/typescript.js +577 -0
  36. package/dist/fix.js +92 -0
  37. package/dist/gitdiff.js +178 -0
  38. package/dist/graph-analysis.js +279 -0
  39. package/dist/graph.js +165 -0
  40. package/dist/history.js +36 -0
  41. package/dist/html.js +658 -0
  42. package/dist/incremental.js +122 -0
  43. package/dist/index.js +1945 -0
  44. package/dist/indexstore.js +105 -0
  45. package/dist/layers.js +36 -0
  46. package/dist/lsp.js +238 -0
  47. package/dist/modulecoupling.js +0 -0
  48. package/dist/parser.js +84 -0
  49. package/dist/patch.js +199 -0
  50. package/dist/plugins.js +88 -0
  51. package/dist/pool.js +114 -0
  52. package/dist/prompts.js +67 -0
  53. package/dist/registry.js +87 -0
  54. package/dist/report.js +441 -0
  55. package/dist/resolver.js +222 -0
  56. package/dist/roots.js +47 -0
  57. package/dist/search.js +68 -0
  58. package/dist/security.js +178 -0
  59. package/dist/semantic.js +365 -0
  60. package/dist/serve.js +328 -0
  61. package/dist/sfc.js +27 -0
  62. package/dist/similar.js +98 -0
  63. package/dist/skeleton.js +132 -0
  64. package/dist/smells.js +285 -0
  65. package/dist/sourcemap.js +60 -0
  66. package/dist/testgen.js +280 -0
  67. package/dist/testmap.js +167 -0
  68. package/dist/tsconfig.js +212 -0
  69. package/dist/typeflow.js +124 -0
  70. package/dist/types.js +5 -0
  71. package/dist/unused-params.js +127 -0
  72. package/dist/webapp.js +646 -0
  73. package/dist/worker.js +27 -0
  74. package/dist/workspace.js +330 -0
  75. package/package.json +2 -1
@@ -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,209 @@
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
+ let s = "";
14
+ for (let i = 0; i < node.childCount; i++) {
15
+ const c = node.child(i);
16
+ if (c && c.type === "modifier")
17
+ s += c.text + " ";
18
+ }
19
+ return s;
20
+ }
21
+ function vis(node) {
22
+ return /\bpublic\b/.test(modifiersText(node)) ? "public" : "private";
23
+ }
24
+ function exported(node) {
25
+ return /\bpublic\b/.test(modifiersText(node));
26
+ }
27
+ function bodyLike(node) {
28
+ return (node.childForFieldName("body") ??
29
+ childOfType(node, "accessor_list") ??
30
+ childOfType(node, "arrow_expression_clause") ??
31
+ childOfType(node, "block"));
32
+ }
33
+ /* ─── directives (namespace declarations) ─────────────────────────────────── */
34
+ export function extractDirectivesCSharp(root, _source) {
35
+ const out = [];
36
+ const visit = (node) => {
37
+ for (const c of namedChildren(node)) {
38
+ if (c.type === "namespace_declaration" || c.type === "file_scoped_namespace_declaration") {
39
+ const name = c.childForFieldName("name");
40
+ if (name)
41
+ out.push(`namespace:${name.text}`);
42
+ const body = c.childForFieldName("body");
43
+ if (body)
44
+ visit(body);
45
+ }
46
+ }
47
+ };
48
+ visit(root);
49
+ return out;
50
+ }
51
+ /* ─── import extraction ───────────────────────────────────────────────────── */
52
+ export function extractImportsCSharp(root, _source) {
53
+ const out = [];
54
+ walkUsings(root, out);
55
+ return out;
56
+ }
57
+ function walkUsings(node, out) {
58
+ for (const child of namedChildren(node)) {
59
+ if (child.type === "using_directive") {
60
+ const isStatic = /\bstatic\b/.test(child.text);
61
+ const alias = childOfType(child, "name_equals");
62
+ const pathNode = childOfType(child, "qualified_name") ?? childOfType(child, "identifier");
63
+ const from = pathNode ? pathNode.text : child.text.replace(/^using\s+|;\s*$/g, "").trim();
64
+ const symbol = from.split(".").pop() ?? from;
65
+ const ref = { symbol, from, isNamespaceImport: !isStatic && !alias };
66
+ if (alias) {
67
+ const aliasId = childOfType(alias, "identifier");
68
+ if (aliasId)
69
+ ref.alias = aliasId.text;
70
+ }
71
+ out.push(ref);
72
+ }
73
+ else if (child.type === "namespace_declaration" ||
74
+ child.type === "file_scoped_namespace_declaration") {
75
+ const body = child.childForFieldName("body");
76
+ if (body)
77
+ walkUsings(body, out);
78
+ }
79
+ }
80
+ }
81
+ /* ─── symbol extraction ───────────────────────────────────────────────────── */
82
+ export function extractCSharp(root, _source) {
83
+ return collect(namedChildren(root));
84
+ }
85
+ function collect(nodes) {
86
+ const out = [];
87
+ for (const n of nodes) {
88
+ const res = handle(n);
89
+ if (Array.isArray(res))
90
+ out.push(...res);
91
+ else if (res)
92
+ out.push(res);
93
+ }
94
+ return out;
95
+ }
96
+ function handle(node) {
97
+ switch (node.type) {
98
+ case "namespace_declaration":
99
+ case "file_scoped_namespace_declaration": {
100
+ const body = node.childForFieldName("body");
101
+ return body ? collect(namedChildren(body)) : null;
102
+ }
103
+ case "class_declaration":
104
+ case "record_declaration":
105
+ case "record_struct_declaration": {
106
+ const body = node.childForFieldName("body");
107
+ return makeSymbol({
108
+ name: nameOf(node) ?? "(class)",
109
+ kind: "class",
110
+ node,
111
+ rawKind: node.type,
112
+ visibility: vis(node),
113
+ exported: exported(node),
114
+ doc: leadingComment(node),
115
+ children: body ? collect(namedChildren(body)) : [],
116
+ });
117
+ }
118
+ case "struct_declaration": {
119
+ const body = node.childForFieldName("body");
120
+ return makeSymbol({
121
+ name: nameOf(node) ?? "(struct)",
122
+ kind: "struct",
123
+ node,
124
+ rawKind: node.type,
125
+ visibility: vis(node),
126
+ exported: exported(node),
127
+ doc: leadingComment(node),
128
+ children: body ? collect(namedChildren(body)) : [],
129
+ });
130
+ }
131
+ case "interface_declaration": {
132
+ const body = node.childForFieldName("body");
133
+ return makeSymbol({
134
+ name: nameOf(node) ?? "(interface)",
135
+ kind: "interface",
136
+ node,
137
+ rawKind: node.type,
138
+ visibility: vis(node),
139
+ exported: exported(node),
140
+ doc: leadingComment(node),
141
+ children: body ? collect(namedChildren(body)) : [],
142
+ });
143
+ }
144
+ case "enum_declaration":
145
+ return makeSymbol({
146
+ name: nameOf(node) ?? "(enum)",
147
+ kind: "enum",
148
+ node,
149
+ rawKind: node.type,
150
+ visibility: vis(node),
151
+ exported: exported(node),
152
+ doc: leadingComment(node),
153
+ });
154
+ case "method_declaration":
155
+ case "constructor_declaration":
156
+ case "destructor_declaration":
157
+ case "operator_declaration":
158
+ return makeSymbol({
159
+ name: nameOf(node) ?? "(method)",
160
+ kind: "method",
161
+ node,
162
+ rawKind: node.type,
163
+ signature: headerSignature(node, bodyLike(node)),
164
+ visibility: vis(node),
165
+ exported: exported(node),
166
+ doc: leadingComment(node),
167
+ });
168
+ case "property_declaration":
169
+ return makeSymbol({
170
+ name: nameOf(node) ?? "(property)",
171
+ kind: "field",
172
+ node,
173
+ rawKind: node.type,
174
+ signature: headerSignature(node, bodyLike(node)),
175
+ visibility: vis(node),
176
+ exported: exported(node),
177
+ doc: leadingComment(node),
178
+ });
179
+ case "field_declaration":
180
+ return fieldDeclarators(node);
181
+ default:
182
+ return null;
183
+ }
184
+ }
185
+ function fieldDeclarators(node) {
186
+ const m = modifiersText(node);
187
+ const kind = /\bconst\b/.test(m) || (/\bstatic\b/.test(m) && /\breadonly\b/.test(m)) ? "const" : "field";
188
+ const decl = childOfType(node, "variable_declaration");
189
+ if (!decl)
190
+ return [];
191
+ const out = [];
192
+ for (const d of namedChildren(decl)) {
193
+ if (d.type !== "variable_declarator")
194
+ continue;
195
+ const id = childOfType(d, "identifier") ?? d.namedChild(0);
196
+ if (!id)
197
+ continue;
198
+ out.push(makeSymbol({
199
+ name: id.text,
200
+ kind,
201
+ node: d,
202
+ rawKind: node.type,
203
+ signature: node.text.replace(/\s+/g, " ").replace(/;$/, "").trim(),
204
+ visibility: vis(node),
205
+ exported: exported(node),
206
+ }));
207
+ }
208
+ return out;
209
+ }
@@ -0,0 +1,212 @@
1
+ import { namedChildren, nameOf, headerSignature, leadingComment } from "../parser.js";
2
+ import { makeSymbol, startsUpper } from "./common.js";
3
+ // ─── Import extraction ────────────────────────────────────────────────────────
4
+ export function extractImportsGo(root, _source) {
5
+ const imports = [];
6
+ for (const child of namedChildren(root)) {
7
+ if (child.type === "import_declaration")
8
+ parseGoImportDecl(child, imports);
9
+ }
10
+ return imports;
11
+ }
12
+ function parseGoImportDecl(node, out) {
13
+ for (let i = 0; i < node.namedChildCount; i++) {
14
+ const c = node.namedChild(i);
15
+ if (!c)
16
+ continue;
17
+ if (c.type === "import_spec")
18
+ parseGoImportSpec(c, out);
19
+ else if (c.type === "import_spec_list") {
20
+ for (let j = 0; j < c.namedChildCount; j++) {
21
+ const spec = c.namedChild(j);
22
+ if (spec && spec.type === "import_spec")
23
+ parseGoImportSpec(spec, out);
24
+ }
25
+ }
26
+ }
27
+ }
28
+ function parseGoImportSpec(spec, out) {
29
+ const pathNode = spec.childForFieldName("path");
30
+ const nameNode = spec.childForFieldName("name");
31
+ if (!pathNode)
32
+ return;
33
+ const from = pathNode.text.replace(/^['"`]|['"`]$/g, "");
34
+ const pkgName = from.split("/").pop() ?? from;
35
+ if (!nameNode) {
36
+ out.push({ symbol: pkgName, from });
37
+ }
38
+ else if (nameNode.text === ".") {
39
+ out.push({ symbol: ".", from, isNamespaceImport: true });
40
+ }
41
+ else if (nameNode.text === "_") {
42
+ out.push({ symbol: "_", from, isSideEffect: true });
43
+ }
44
+ else {
45
+ out.push({ symbol: pkgName, from, alias: nameNode.text });
46
+ }
47
+ }
48
+ // ─── Symbol extraction ────────────────────────────────────────────────────────
49
+ export function extractGo(root, _source) {
50
+ const out = [];
51
+ for (const n of namedChildren(root)) {
52
+ const res = handle(n);
53
+ if (Array.isArray(res))
54
+ out.push(...res);
55
+ else if (res)
56
+ out.push(res);
57
+ }
58
+ return out;
59
+ }
60
+ function handle(node) {
61
+ switch (node.type) {
62
+ case "function_declaration": {
63
+ const name = nameOf(node) ?? "(func)";
64
+ return makeSymbol({
65
+ name,
66
+ kind: "function",
67
+ node,
68
+ rawKind: node.type,
69
+ signature: headerSignature(node, node.childForFieldName("body")),
70
+ visibility: startsUpper(name) ? "public" : "private",
71
+ exported: startsUpper(name),
72
+ doc: leadingComment(node),
73
+ });
74
+ }
75
+ case "method_declaration": {
76
+ const name = nameOf(node) ?? "(method)";
77
+ return makeSymbol({
78
+ name,
79
+ kind: "method",
80
+ node,
81
+ rawKind: node.type,
82
+ signature: headerSignature(node, node.childForFieldName("body")),
83
+ visibility: startsUpper(name) ? "public" : "private",
84
+ exported: startsUpper(name),
85
+ doc: leadingComment(node),
86
+ });
87
+ }
88
+ case "type_declaration": {
89
+ const out = [];
90
+ for (const spec of namedChildren(node)) {
91
+ if (spec.type === "type_spec" || spec.type === "type_alias") {
92
+ const sym = fromTypeSpec(spec, node);
93
+ if (sym)
94
+ out.push(sym);
95
+ }
96
+ }
97
+ return out;
98
+ }
99
+ case "const_declaration":
100
+ return fromValueSpecs(node, "const");
101
+ case "var_declaration":
102
+ return fromValueSpecs(node, "var");
103
+ default:
104
+ return null;
105
+ }
106
+ }
107
+ function fromTypeSpec(spec, declNode) {
108
+ const name = nameOf(spec);
109
+ if (!name)
110
+ return null;
111
+ const typeNode = spec.childForFieldName("type");
112
+ const exported = startsUpper(name);
113
+ const visibility = exported ? "public" : "private";
114
+ const doc = leadingComment(declNode);
115
+ if (typeNode && typeNode.type === "struct_type") {
116
+ return makeSymbol({
117
+ name,
118
+ kind: "struct",
119
+ node: spec,
120
+ rawKind: spec.type,
121
+ visibility,
122
+ exported,
123
+ doc,
124
+ children: structFields(typeNode),
125
+ });
126
+ }
127
+ if (typeNode && typeNode.type === "interface_type") {
128
+ return makeSymbol({
129
+ name,
130
+ kind: "interface",
131
+ node: spec,
132
+ rawKind: spec.type,
133
+ visibility,
134
+ exported,
135
+ doc,
136
+ children: interfaceMethods(typeNode),
137
+ });
138
+ }
139
+ return makeSymbol({
140
+ name,
141
+ kind: "type",
142
+ node: spec,
143
+ rawKind: spec.type,
144
+ signature: headerSignature(spec, null),
145
+ visibility,
146
+ exported,
147
+ doc,
148
+ });
149
+ }
150
+ function structFields(structType) {
151
+ const list = namedChildren(structType).find((c) => c.type === "field_declaration_list");
152
+ if (!list)
153
+ return [];
154
+ const out = [];
155
+ for (const field of namedChildren(list)) {
156
+ if (field.type !== "field_declaration")
157
+ continue;
158
+ const name = nameOf(field);
159
+ if (!name)
160
+ continue; // skip embedded fields
161
+ out.push(makeSymbol({
162
+ name,
163
+ kind: "field",
164
+ node: field,
165
+ rawKind: field.type,
166
+ signature: field.text.replace(/\s+/g, " ").trim(),
167
+ visibility: startsUpper(name) ? "public" : "private",
168
+ exported: startsUpper(name),
169
+ }));
170
+ }
171
+ return out;
172
+ }
173
+ function interfaceMethods(interfaceType) {
174
+ const out = [];
175
+ for (const m of namedChildren(interfaceType)) {
176
+ if (m.type !== "method_spec" && m.type !== "method_elem")
177
+ continue;
178
+ const name = nameOf(m);
179
+ if (!name)
180
+ continue;
181
+ out.push(makeSymbol({
182
+ name,
183
+ kind: "method",
184
+ node: m,
185
+ rawKind: m.type,
186
+ signature: headerSignature(m, null),
187
+ visibility: startsUpper(name) ? "public" : "private",
188
+ exported: startsUpper(name),
189
+ }));
190
+ }
191
+ return out;
192
+ }
193
+ function fromValueSpecs(node, kind) {
194
+ const out = [];
195
+ for (const spec of namedChildren(node)) {
196
+ if (spec.type !== "const_spec" && spec.type !== "var_spec")
197
+ continue;
198
+ const name = nameOf(spec);
199
+ if (!name)
200
+ continue;
201
+ out.push(makeSymbol({
202
+ name,
203
+ kind,
204
+ node: spec,
205
+ rawKind: spec.type,
206
+ signature: spec.text.replace(/\s+/g, " ").trim(),
207
+ visibility: startsUpper(name) ? "public" : "private",
208
+ exported: startsUpper(name),
209
+ }));
210
+ }
211
+ return out;
212
+ }