universal-ast-mapper 2.0.0 → 2.0.1

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 +9 -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 +185 -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 +341 -0
  73. package/dist/worker.js +27 -0
  74. package/dist/workspace.js +330 -0
  75. package/package.json +2 -1
@@ -0,0 +1,146 @@
1
+ import { namedChildren, nameOf, headerSignature, leadingComment } from "../parser.js";
2
+ import { makeSymbol } from "./common.js";
3
+ // ─── Ruby extractor (tree-sitter-ruby) ────────────────────────────────────────
4
+ // Tracks `private` / `protected` visibility sections inside class bodies.
5
+ export function extractRuby(root, _source) {
6
+ return collect(namedChildren(root), false);
7
+ }
8
+ function collect(nodes, insideClass) {
9
+ const out = [];
10
+ let visibility = "public";
11
+ for (const n of nodes) {
12
+ // Bare `private` / `protected` / `public` switches the section.
13
+ if (n.type === "identifier") {
14
+ if (n.text === "private" || n.text === "protected")
15
+ visibility = "private";
16
+ else if (n.text === "public")
17
+ visibility = "public";
18
+ continue;
19
+ }
20
+ const sym = handle(n, insideClass, visibility);
21
+ if (sym)
22
+ out.push(sym);
23
+ }
24
+ return out;
25
+ }
26
+ function bodyOf(node) {
27
+ const byField = node.childForFieldName("body");
28
+ if (byField)
29
+ return byField;
30
+ for (const c of namedChildren(node)) {
31
+ if (c.type === "body_statement")
32
+ return c;
33
+ }
34
+ return null;
35
+ }
36
+ function handle(node, insideClass, visibility) {
37
+ switch (node.type) {
38
+ case "class": {
39
+ const body = bodyOf(node);
40
+ return makeSymbol({
41
+ name: nameOf(node) ?? "(class)",
42
+ kind: "class",
43
+ node,
44
+ rawKind: node.type,
45
+ signature: headerSignature(node, body),
46
+ doc: leadingComment(node),
47
+ children: body ? collect(namedChildren(body), true) : [],
48
+ });
49
+ }
50
+ case "module": {
51
+ const body = bodyOf(node);
52
+ return makeSymbol({
53
+ name: nameOf(node) ?? "(module)",
54
+ kind: "namespace",
55
+ node,
56
+ rawKind: node.type,
57
+ signature: headerSignature(node, body),
58
+ doc: leadingComment(node),
59
+ children: body ? collect(namedChildren(body), true) : [],
60
+ });
61
+ }
62
+ case "method": {
63
+ const body = bodyOf(node);
64
+ const name = nameOf(node) ?? "(method)";
65
+ return makeSymbol({
66
+ name,
67
+ kind: insideClass ? "method" : "function",
68
+ node,
69
+ rawKind: node.type,
70
+ signature: headerSignature(node, body),
71
+ visibility,
72
+ exported: visibility === "public",
73
+ doc: leadingComment(node),
74
+ });
75
+ }
76
+ case "singleton_method": {
77
+ const body = bodyOf(node);
78
+ const name = nameOf(node) ?? "(method)";
79
+ return makeSymbol({
80
+ name: `self.${name}`,
81
+ kind: insideClass ? "method" : "function",
82
+ node,
83
+ rawKind: node.type,
84
+ signature: headerSignature(node, body),
85
+ visibility,
86
+ exported: visibility === "public",
87
+ doc: leadingComment(node),
88
+ });
89
+ }
90
+ case "assignment": {
91
+ // Top-level / class-level CONSTANT = ...
92
+ const left = namedChildren(node)[0];
93
+ if (left?.type === "constant") {
94
+ return makeSymbol({
95
+ name: left.text,
96
+ kind: "const",
97
+ node,
98
+ rawKind: node.type,
99
+ });
100
+ }
101
+ return null;
102
+ }
103
+ default:
104
+ return null;
105
+ }
106
+ }
107
+ // ─── Import extraction ────────────────────────────────────────────────────────
108
+ // `require 'x'` (external) and `require_relative './x'` (relative).
109
+ export function extractImportsRuby(root, _source) {
110
+ const imports = [];
111
+ for (const n of namedChildren(root))
112
+ collectRequire(n, imports, 0);
113
+ return imports;
114
+ }
115
+ function collectRequire(node, out, depth) {
116
+ if (depth > 3)
117
+ return;
118
+ if (node.type === "call") {
119
+ const fn = namedChildren(node)[0];
120
+ if (fn?.type === "identifier" && (fn.text === "require" || fn.text === "require_relative")) {
121
+ const args = node.childForFieldName("arguments") ?? findArgs(node);
122
+ const str = args ? firstString(args) : null;
123
+ if (str) {
124
+ const from = fn.text === "require_relative" && !str.startsWith(".") ? `./${str}` : str;
125
+ out.push({ symbol: "*", from, isSideEffect: true });
126
+ }
127
+ return;
128
+ }
129
+ }
130
+ for (const c of namedChildren(node))
131
+ collectRequire(c, out, depth + 1);
132
+ }
133
+ function findArgs(node) {
134
+ for (const c of namedChildren(node))
135
+ if (c.type === "argument_list")
136
+ return c;
137
+ return null;
138
+ }
139
+ function firstString(args) {
140
+ for (const c of namedChildren(args)) {
141
+ if (c.type === "string") {
142
+ return c.text.replace(/^['"]|['"]$/g, "");
143
+ }
144
+ }
145
+ return null;
146
+ }
@@ -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
+ }