diffninja 0.1.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.
Files changed (154) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +259 -0
  3. package/dist/calltree.d.ts +47 -0
  4. package/dist/calltree.js +296 -0
  5. package/dist/cli.d.ts +57 -0
  6. package/dist/cli.js +340 -0
  7. package/dist/diff.d.ts +7 -0
  8. package/dist/diff.js +114 -0
  9. package/dist/extract.d.ts +26 -0
  10. package/dist/extract.js +152 -0
  11. package/dist/git.d.ts +40 -0
  12. package/dist/git.js +288 -0
  13. package/dist/index.d.ts +9 -0
  14. package/dist/index.js +8 -0
  15. package/dist/infer.d.ts +21 -0
  16. package/dist/infer.js +189 -0
  17. package/dist/languages/bash.d.ts +2 -0
  18. package/dist/languages/bash.js +208 -0
  19. package/dist/languages/c.d.ts +2 -0
  20. package/dist/languages/c.js +218 -0
  21. package/dist/languages/call-syntax.d.ts +125 -0
  22. package/dist/languages/call-syntax.js +997 -0
  23. package/dist/languages/cpp.d.ts +2 -0
  24. package/dist/languages/cpp.js +321 -0
  25. package/dist/languages/csharp.d.ts +2 -0
  26. package/dist/languages/csharp.js +324 -0
  27. package/dist/languages/elixir.d.ts +2 -0
  28. package/dist/languages/elixir.js +331 -0
  29. package/dist/languages/go.d.ts +2 -0
  30. package/dist/languages/go.js +299 -0
  31. package/dist/languages/grammars.d.ts +50 -0
  32. package/dist/languages/grammars.js +351 -0
  33. package/dist/languages/haskell.d.ts +2 -0
  34. package/dist/languages/haskell.js +250 -0
  35. package/dist/languages/java.d.ts +2 -0
  36. package/dist/languages/java.js +351 -0
  37. package/dist/languages/javascript.d.ts +4 -0
  38. package/dist/languages/javascript.js +648 -0
  39. package/dist/languages/kotlin.d.ts +2 -0
  40. package/dist/languages/kotlin.js +368 -0
  41. package/dist/languages/lua.d.ts +2 -0
  42. package/dist/languages/lua.js +212 -0
  43. package/dist/languages/ocaml.d.ts +2 -0
  44. package/dist/languages/ocaml.js +291 -0
  45. package/dist/languages/perl.d.ts +2 -0
  46. package/dist/languages/perl.js +418 -0
  47. package/dist/languages/php.d.ts +2 -0
  48. package/dist/languages/php.js +397 -0
  49. package/dist/languages/python.d.ts +2 -0
  50. package/dist/languages/python.js +376 -0
  51. package/dist/languages/registry.d.ts +7 -0
  52. package/dist/languages/registry.js +69 -0
  53. package/dist/languages/ruby.d.ts +2 -0
  54. package/dist/languages/ruby.js +391 -0
  55. package/dist/languages/rust.d.ts +2 -0
  56. package/dist/languages/rust.js +261 -0
  57. package/dist/languages/scala.d.ts +2 -0
  58. package/dist/languages/scala.js +307 -0
  59. package/dist/languages/solidity.d.ts +2 -0
  60. package/dist/languages/solidity.js +240 -0
  61. package/dist/languages/swift.d.ts +2 -0
  62. package/dist/languages/swift.js +268 -0
  63. package/dist/languages/types.d.ts +36 -0
  64. package/dist/languages/types.js +74 -0
  65. package/dist/languages/typescript-contracts.d.ts +57 -0
  66. package/dist/languages/typescript-contracts.js +528 -0
  67. package/dist/languages/typescript-dispatch.d.ts +68 -0
  68. package/dist/languages/typescript-dispatch.js +710 -0
  69. package/dist/languages/typescript.d.ts +4 -0
  70. package/dist/languages/typescript.js +722 -0
  71. package/dist/languages/zig.d.ts +2 -0
  72. package/dist/languages/zig.js +243 -0
  73. package/dist/loc.d.ts +17 -0
  74. package/dist/loc.js +34 -0
  75. package/dist/reach.d.ts +17 -0
  76. package/dist/reach.js +65 -0
  77. package/dist/render.d.ts +18 -0
  78. package/dist/render.js +83 -0
  79. package/dist/review/brand.d.ts +8 -0
  80. package/dist/review/brand.js +25 -0
  81. package/dist/review/call-context.d.ts +27 -0
  82. package/dist/review/call-context.js +446 -0
  83. package/dist/review/call-flow-html.d.ts +32 -0
  84. package/dist/review/call-flow-html.js +1870 -0
  85. package/dist/review/call-flow-nav.d.ts +151 -0
  86. package/dist/review/call-flow-nav.js +317 -0
  87. package/dist/review/call-flow.d.ts +47 -0
  88. package/dist/review/call-flow.js +229 -0
  89. package/dist/review/change-facts.d.ts +69 -0
  90. package/dist/review/change-facts.js +729 -0
  91. package/dist/review/cli.d.ts +2 -0
  92. package/dist/review/cli.js +50 -0
  93. package/dist/review/connected-analysis.d.ts +100 -0
  94. package/dist/review/connected-analysis.js +163 -0
  95. package/dist/review/connected-html.d.ts +17 -0
  96. package/dist/review/connected-html.js +2853 -0
  97. package/dist/review/connected.d.ts +23 -0
  98. package/dist/review/connected.js +141 -0
  99. package/dist/review/escape-html.d.ts +2 -0
  100. package/dist/review/escape-html.js +9 -0
  101. package/dist/review/evidence-html.d.ts +21 -0
  102. package/dist/review/evidence-html.js +521 -0
  103. package/dist/review/evidence-syntax.d.ts +132 -0
  104. package/dist/review/evidence-syntax.js +478 -0
  105. package/dist/review/evidence-types.d.ts +62 -0
  106. package/dist/review/evidence-types.js +1 -0
  107. package/dist/review/evidence.d.ts +31 -0
  108. package/dist/review/evidence.js +1603 -0
  109. package/dist/review/file-role.d.ts +9 -0
  110. package/dist/review/file-role.js +29 -0
  111. package/dist/review/github.d.ts +204 -0
  112. package/dist/review/github.js +1245 -0
  113. package/dist/review/history.d.ts +101 -0
  114. package/dist/review/history.js +412 -0
  115. package/dist/review/html.d.ts +34 -0
  116. package/dist/review/html.js +1104 -0
  117. package/dist/review/input.d.ts +10 -0
  118. package/dist/review/input.js +113 -0
  119. package/dist/review/intent.d.ts +4 -0
  120. package/dist/review/intent.js +75 -0
  121. package/dist/review/mcp-cli.d.ts +2 -0
  122. package/dist/review/mcp-cli.js +25 -0
  123. package/dist/review/mcp.d.ts +12 -0
  124. package/dist/review/mcp.js +414 -0
  125. package/dist/review/module-resolution.d.ts +2 -0
  126. package/dist/review/module-resolution.js +86 -0
  127. package/dist/review/palette.d.ts +7 -0
  128. package/dist/review/palette.js +104 -0
  129. package/dist/review/pipeline.d.ts +77 -0
  130. package/dist/review/pipeline.js +227 -0
  131. package/dist/review/pr-input.d.ts +19 -0
  132. package/dist/review/pr-input.js +130 -0
  133. package/dist/review/questions.d.ts +201 -0
  134. package/dist/review/questions.js +174 -0
  135. package/dist/review/reference-check.d.ts +7 -0
  136. package/dist/review/reference-check.js +733 -0
  137. package/dist/review/report-pages.d.ts +109 -0
  138. package/dist/review/report-pages.js +328 -0
  139. package/dist/review/service.d.ts +23 -0
  140. package/dist/review/service.js +198 -0
  141. package/dist/review/setup.d.ts +112 -0
  142. package/dist/review/setup.js +549 -0
  143. package/dist/review/source.d.ts +26 -0
  144. package/dist/review/source.js +276 -0
  145. package/dist/review/toml.d.ts +38 -0
  146. package/dist/review/toml.js +565 -0
  147. package/dist/review/types.d.ts +179 -0
  148. package/dist/review/types.js +1 -0
  149. package/dist/run.d.ts +49 -0
  150. package/dist/run.js +311 -0
  151. package/dist/types.d.ts +366 -0
  152. package/dist/types.js +83 -0
  153. package/package.json +88 -0
  154. package/scripts/ensure-native-grammar.mjs +188 -0
@@ -0,0 +1,351 @@
1
+ import { heuristicCallSyntax } from "./call-syntax.js";
2
+ import { childByType, declaredParamsOf, collapseWs, locFromNode, namedChildren, sameNode, } from "./types.js";
3
+ function isPrivate(node) {
4
+ const mods = childByType(node, "modifiers");
5
+ if (!mods)
6
+ return false;
7
+ return /\bprivate\b/.test(mods.text);
8
+ }
9
+ function getParamsLabel(params) {
10
+ if (!params || params.type !== "formal_parameters")
11
+ return "()";
12
+ const names = [];
13
+ for (const p of namedChildren(params)) {
14
+ if (p.type === "formal_parameter" || p.type === "spread_parameter") {
15
+ const id = childByType(p, "identifier");
16
+ names.push(id?.text ?? "_");
17
+ }
18
+ }
19
+ return names.length === 0 ? "()" : `(${names.join(", ")})`;
20
+ }
21
+ /**
22
+ * method_invocation children shapes:
23
+ * foo() → identifier, argument_list
24
+ * obj.bar() → identifier/this, identifier, argument_list
25
+ * Super.qux() → identifier, identifier, argument_list
26
+ * a.b.c() → field_access, identifier, argument_list
27
+ */
28
+ function methodInvocationKey(node, className) {
29
+ const kids = namedChildren(node).filter((c) => c.type !== "argument_list");
30
+ if (kids.length === 0)
31
+ return null;
32
+ if (kids.length === 1) {
33
+ // bare foo()
34
+ return kids[0].type === "identifier" ? kids[0].text : null;
35
+ }
36
+ // receiver + method name
37
+ const method = kids[kids.length - 1];
38
+ const receiver = kids[0];
39
+ if (method.type !== "identifier")
40
+ return null;
41
+ const prop = method.text;
42
+ if (receiver.type === "this" && className) {
43
+ return `${className}.${prop}`;
44
+ }
45
+ if (receiver.type === "identifier") {
46
+ return `${receiver.text}.${prop}`;
47
+ }
48
+ if (receiver.type === "field_access") {
49
+ // a.b.c() → keep last segment as object name heuristic
50
+ const lastId = namedChildren(receiver).filter((c) => c.type === "identifier").at(-1) ??
51
+ null;
52
+ if (lastId)
53
+ return `${lastId.text}.${prop}`;
54
+ }
55
+ if (className)
56
+ return `${className}.${prop}`;
57
+ return prop;
58
+ }
59
+ function statementsOf(node) {
60
+ if (node.type === "block" || node.type === "constructor_body") {
61
+ return namedChildren(node);
62
+ }
63
+ return [node];
64
+ }
65
+ function collectStatements(file, statements, className) {
66
+ const steps = [];
67
+ const seen = new Set();
68
+ const addCall = (key, node) => {
69
+ const mark = `${key}:${node.startIndex}`;
70
+ if (seen.has(mark))
71
+ return;
72
+ seen.add(mark);
73
+ const step = { type: "call", key, ...locFromNode(file, node) };
74
+ step.syntax = heuristicCallSyntax(node, key);
75
+ steps.push(step);
76
+ };
77
+ const walk = (node) => {
78
+ if (node.type === "method_declaration" ||
79
+ node.type === "constructor_declaration" ||
80
+ node.type === "class_declaration" ||
81
+ node.type === "lambda_expression") {
82
+ return;
83
+ }
84
+ if (node.type === "if_statement") {
85
+ // CST: if_statement → parenthesized_expression, block, [block] (else has no else_clause wrapper)
86
+ const kids = namedChildren(node);
87
+ const cond = childByType(node, "parenthesized_expression") ??
88
+ kids.find((c) => c.type !== "block") ??
89
+ null;
90
+ const blocks = kids.filter((c) => c.type === "block");
91
+ // consequent may also be a non-block statement
92
+ const consequent = blocks[0] ??
93
+ kids.find((c) => c.type !== "parenthesized_expression" && !sameNode(c, cond)) ??
94
+ null;
95
+ const alternate = blocks[1] ?? null;
96
+ const condInner = cond?.type === "parenthesized_expression"
97
+ ? (cond.namedChild(0) ?? cond)
98
+ : cond;
99
+ const condText = condInner ? collapseWs(condInner.text) : "";
100
+ steps.push({
101
+ type: "branch",
102
+ key: condText ? `if:${condText}` : "if",
103
+ label: condText ? `if (${condText})` : "if",
104
+ ...locFromNode(file, condInner ?? node),
105
+ children: consequent
106
+ ? collectStatements(file, statementsOf(consequent), className)
107
+ : [],
108
+ });
109
+ if (alternate) {
110
+ // else-if: alternate block might actually be... no, else if is nested if_statement as alternate
111
+ // When `else if`, the third named child is another if_statement, not a block
112
+ steps.push({
113
+ type: "branch",
114
+ key: "else",
115
+ label: "else",
116
+ ...locFromNode(file, alternate),
117
+ children: collectStatements(file, statementsOf(alternate), className),
118
+ });
119
+ }
120
+ else {
121
+ // Look for else-if: a trailing if_statement child
122
+ const elseIf = kids.find((c) => c.type === "if_statement");
123
+ if (elseIf) {
124
+ // Flatten: treat nested if as else-if / else chain
125
+ const nested = collectStatements(file, [elseIf], className);
126
+ for (const step of nested) {
127
+ if (step.type === "branch" && step.key.startsWith("if:")) {
128
+ steps.push({
129
+ ...step,
130
+ key: step.key.replace(/^if:/, "else-if:"),
131
+ label: step.label.replace(/^if /, "else if "),
132
+ });
133
+ }
134
+ else {
135
+ steps.push(step);
136
+ }
137
+ }
138
+ }
139
+ }
140
+ return;
141
+ }
142
+ if (node.type === "try_statement") {
143
+ const tryBlock = childByType(node, "block");
144
+ steps.push({
145
+ type: "branch",
146
+ key: "try",
147
+ label: "try",
148
+ ...locFromNode(file, node),
149
+ children: tryBlock
150
+ ? collectStatements(file, statementsOf(tryBlock), className)
151
+ : [],
152
+ });
153
+ for (const clause of namedChildren(node)) {
154
+ if (clause.type === "catch_clause") {
155
+ const catchType = childByType(clause, "catch_formal_parameter") ??
156
+ childByType(clause, "catch_type") ??
157
+ null;
158
+ const typeNode = catchType
159
+ ? (childByType(catchType, "catch_type") ??
160
+ childByType(catchType, "type_identifier") ??
161
+ catchType)
162
+ : null;
163
+ const text = typeNode
164
+ ? collapseWs((childByType(typeNode, "type_identifier") ?? typeNode).text)
165
+ : "";
166
+ const block = childByType(clause, "block");
167
+ steps.push({
168
+ type: "branch",
169
+ key: text ? `catch:${text}` : "catch",
170
+ label: text ? `catch (${text})` : "catch",
171
+ ...locFromNode(file, typeNode ?? clause),
172
+ children: block
173
+ ? collectStatements(file, statementsOf(block), className)
174
+ : [],
175
+ });
176
+ }
177
+ if (clause.type === "finally_clause") {
178
+ const block = childByType(clause, "block");
179
+ steps.push({
180
+ type: "branch",
181
+ key: "finally",
182
+ label: "finally",
183
+ ...locFromNode(file, clause),
184
+ children: block
185
+ ? collectStatements(file, statementsOf(block), className)
186
+ : [],
187
+ });
188
+ }
189
+ }
190
+ return;
191
+ }
192
+ if (node.type === "switch_expression" ||
193
+ node.type === "switch_statement") {
194
+ const body = childByType(node, "switch_block") ??
195
+ childByType(node, "switch_body") ??
196
+ null;
197
+ for (const group of body ? namedChildren(body) : []) {
198
+ if (group.type === "switch_block_statement_group") {
199
+ const labels = namedChildren(group).filter((c) => c.type === "switch_label");
200
+ const stmts = namedChildren(group).filter((c) => c.type !== "switch_label" && c.type !== "break_statement");
201
+ for (const label of labels) {
202
+ const isDefault = label.namedChildCount === 0 || /\bdefault\b/.test(label.text);
203
+ if (isDefault) {
204
+ steps.push({
205
+ type: "branch",
206
+ key: "default",
207
+ label: "default",
208
+ ...locFromNode(file, label),
209
+ children: collectStatements(file, stmts, className),
210
+ });
211
+ }
212
+ else {
213
+ const value = label.namedChild(0);
214
+ const text = value ? collapseWs(value.text) : "";
215
+ steps.push({
216
+ type: "branch",
217
+ key: text ? `case:${text}` : "case",
218
+ label: text ? `case ${text}` : "case",
219
+ ...locFromNode(file, value ?? label),
220
+ children: collectStatements(file, stmts, className),
221
+ });
222
+ }
223
+ }
224
+ }
225
+ else if (group.type === "switch_rule") {
226
+ // switch expression arrow form: case 1 -> expr;
227
+ const label = childByType(group, "switch_label");
228
+ const bodyNode = namedChildren(group).find((c) => c.type !== "switch_label") ?? null;
229
+ if (!label)
230
+ continue;
231
+ const isDefault = label.namedChildCount === 0 || /\bdefault\b/.test(label.text);
232
+ const children = bodyNode
233
+ ? collectStatements(file, statementsOf(bodyNode), className)
234
+ : [];
235
+ if (isDefault) {
236
+ steps.push({
237
+ type: "branch",
238
+ key: "default",
239
+ label: "default",
240
+ ...locFromNode(file, label),
241
+ children,
242
+ });
243
+ }
244
+ else {
245
+ const value = label.namedChild(0);
246
+ const text = value ? collapseWs(value.text) : "";
247
+ steps.push({
248
+ type: "branch",
249
+ key: text ? `case:${text}` : "case",
250
+ label: text ? `case ${text}` : "case",
251
+ ...locFromNode(file, value ?? label),
252
+ children,
253
+ });
254
+ }
255
+ }
256
+ }
257
+ return;
258
+ }
259
+ if (node.type === "method_invocation") {
260
+ const key = methodInvocationKey(node, className);
261
+ if (key)
262
+ addCall(key, node);
263
+ }
264
+ else if (node.type === "object_creation_expression") {
265
+ const typeId = childByType(node, "type_identifier") ??
266
+ childByType(node, "generic_type");
267
+ const name = typeId?.type === "type_identifier"
268
+ ? typeId.text
269
+ : childByType(typeId ?? node, "type_identifier")?.text;
270
+ if (name)
271
+ addCall(`new ${name}`, node);
272
+ }
273
+ for (const child of namedChildren(node))
274
+ walk(child);
275
+ };
276
+ for (const stmt of statements)
277
+ walk(stmt);
278
+ return steps;
279
+ }
280
+ function handleMethod(file, node, className, functions) {
281
+ const name = childByType(node, "identifier")?.text ?? null;
282
+ if (!name)
283
+ return;
284
+ const params = childByType(node, "formal_parameters");
285
+ const body = childByType(node, "block");
286
+ const key = `${className}.${name}`;
287
+ functions.push({
288
+ key,
289
+ label: `${key}${getParamsLabel(params)}`,
290
+ params: declaredParamsOf(node),
291
+ file,
292
+ steps: body ? collectStatements(file, statementsOf(body), className) : [],
293
+ exported: !isPrivate(node),
294
+ start: node.startIndex,
295
+ end: node.endIndex,
296
+ });
297
+ }
298
+ function handleConstructor(file, node, className, functions) {
299
+ const params = childByType(node, "formal_parameters");
300
+ const body = childByType(node, "constructor_body");
301
+ const info = {
302
+ key: `${className}.constructor`,
303
+ label: `new ${className}${getParamsLabel(params)}`,
304
+ params: declaredParamsOf(node),
305
+ file,
306
+ steps: body ? collectStatements(file, statementsOf(body), className) : [],
307
+ exported: !isPrivate(node),
308
+ start: node.startIndex,
309
+ end: node.endIndex,
310
+ };
311
+ functions.push(info);
312
+ functions.push({
313
+ ...info,
314
+ key: `new ${className}`,
315
+ });
316
+ }
317
+ function handleClass(file, node, functions) {
318
+ const className = childByType(node, "identifier")?.text ?? null;
319
+ if (!className)
320
+ return;
321
+ const body = childByType(node, "class_body");
322
+ if (!body)
323
+ return;
324
+ for (const element of namedChildren(body)) {
325
+ if (element.type === "method_declaration") {
326
+ handleMethod(file, element, className, functions);
327
+ }
328
+ else if (element.type === "constructor_declaration") {
329
+ handleConstructor(file, element, className, functions);
330
+ }
331
+ else if (element.type === "class_declaration") {
332
+ handleClass(file, element, functions);
333
+ }
334
+ }
335
+ }
336
+ function extractFromTree(file, _source, tree) {
337
+ const functions = [];
338
+ for (const stmt of namedChildren(tree.rootNode)) {
339
+ if (stmt.type === "class_declaration") {
340
+ handleClass(file, stmt, functions);
341
+ }
342
+ // Skip package/import; top-level methods don't exist in Java
343
+ }
344
+ return functions;
345
+ }
346
+ export const javaExtractor = {
347
+ id: "java",
348
+ extensions: [".java"],
349
+ grammarPackage: "tree-sitter-java",
350
+ extract: extractFromTree,
351
+ };
@@ -0,0 +1,4 @@
1
+ import { type LanguageExtractor } from "./types.js";
2
+ export declare const javascriptExtractor: LanguageExtractor;
3
+ /** JSX (.jsx) — same grammar as JS; tree-sitter-javascript parses both. */
4
+ export declare const javascriptreactExtractor: LanguageExtractor;