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,188 @@
1
+ #!/usr/bin/env node
2
+ // Postinstall heal for tree-sitter-typescript's native binding.
3
+ //
4
+ // Why this exists: tree-sitter-typescript@0.23.2 publishes an x86-64 ELF as its
5
+ // `prebuilds/linux-arm64/` binary, so on Linux ARM64 the addon cannot load. The
6
+ // package's own `install` script (`node-gyp-build`) notices the load failure and
7
+ // falls back to `node-gyp rebuild`, but that build aborts `npm install` outright:
8
+ // under Node 22 the generated Makefile for node-addon-api's exception support is
9
+ // malformed and node-gyp exits non-zero. Because the package is declared as an
10
+ // *optional* dependency of diffninja, npm now survives that failure and leaves
11
+ // the package's binding unusable — and diffninja's TypeScript/TSX extraction
12
+ // would fall through to the on-demand grammar cache, which needs the same
13
+ // toolchain and network. This script repairs the installed copy instead: it
14
+ // drops the wrong-architecture prebuild and compiles the grammar from source,
15
+ // which is exactly what the fix upstream (activeloopai/hivemind cd8642e) does.
16
+ //
17
+ // On every platform whose prebuild loads (Linux/Windows/macOS x64, macOS arm64)
18
+ // the probe below succeeds and this is a fast no-op that touches nothing.
19
+ //
20
+ // This is a heal, not a gate: it always exits 0, including when no C/C++ toolchain
21
+ // is present. Extraction degrades to a per-file warning in that case, and a user
22
+ // can retry later with `npm run rebuild:native`.
23
+ import { execFileSync } from "node:child_process";
24
+ import { existsSync, readFileSync, rmSync } from "node:fs";
25
+ import { createRequire } from "node:module";
26
+ import { dirname, isAbsolute, join } from "node:path";
27
+ import { fileURLToPath } from "node:url";
28
+
29
+ /** The one grammar package with a broken prebuild; see the header comment. */
30
+ const PACKAGE = "tree-sitter-typescript";
31
+ /** Parse shape used by the probe: TypeScript syntax only this grammar accepts. */
32
+ const PROBE_SOURCE = "const x: number = 1;";
33
+ /** Set for the nested npm calls below, which re-enter this package's lifecycle. */
34
+ const RECURSION_GUARD = "DIFFNINJA_NATIVE_GRAMMAR_HEAL";
35
+ /** Generous for a source compile; a hung npm must not hang the install forever. */
36
+ const NPM_TIMEOUT_MS = 900_000;
37
+
38
+ const root = fileURLToPath(new URL("../", import.meta.url));
39
+ const require = createRequire(new URL("../package.json", import.meta.url));
40
+
41
+ /**
42
+ * Real end-to-end check: require the parser and the grammar, set the language and
43
+ * parse. A prebuild that exists but targets another CPU fails here, which is the
44
+ * only reliable signal — the file is present and its wrapper loads.
45
+ */
46
+ function grammarWorks() {
47
+ try {
48
+ const Parser = require("tree-sitter");
49
+ const parser = new Parser();
50
+ parser.setLanguage(require(PACKAGE).typescript);
51
+ parser.parse(PROBE_SOURCE);
52
+ return true;
53
+ } catch {
54
+ return false;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Same parse, in a child process. The in-process probe above already failed once
60
+ * in this process, and an installer's process is a poor place to judge the result
61
+ * of an install it just performed; a fresh process is what the next `diffninja`
62
+ * run will do. Run with `-e` and cwd at the package root, so a bare `require`
63
+ * resolves through the same `node_modules` chain the CLI uses. Only the failure
64
+ * reason is echoed — a child's full stack trace would bury the outcome line.
65
+ */
66
+ function grammarWorksInFreshProcess() {
67
+ const script = `
68
+ const Parser = require("tree-sitter");
69
+ const parser = new Parser();
70
+ parser.setLanguage(require(${JSON.stringify(PACKAGE)}).typescript);
71
+ parser.parse(${JSON.stringify(PROBE_SOURCE)});
72
+ `;
73
+ try {
74
+ execFileSync(process.execPath, ["-e", script], { cwd: root, stdio: ["ignore", "pipe", "pipe"] });
75
+ return true;
76
+ } catch (error) {
77
+ const lines = String(error.stderr ?? "").split("\n").filter(line => line.trim() !== "");
78
+ const reason = lines.find(line => line.includes("Error")) ?? lines[0];
79
+ if (reason) console.error(`[native-grammar] probe still fails: ${reason.trim()}`);
80
+ return false;
81
+ }
82
+ }
83
+
84
+ /** Parsed JSON, or null when the file is missing or unreadable. */
85
+ function readJson(path) {
86
+ try {
87
+ return JSON.parse(readFileSync(path, "utf8"));
88
+ } catch {
89
+ return null;
90
+ }
91
+ }
92
+
93
+ /**
94
+ * On Windows, npm.cmd is a shell script that Node refuses to spawn directly. Run
95
+ * npm's JS entry through the current Node executable instead — same reasoning as
96
+ * `npmSpawnSpec` in src/languages/grammars.ts.
97
+ */
98
+ function npmSpawnSpec(args) {
99
+ if (process.platform !== "win32") return { file: "npm", args };
100
+ const directories = [...(process.env.PATH ?? "").split(";"), dirname(process.execPath)];
101
+ for (const raw of directories) {
102
+ const directory = raw.trim().replace(/^"|"$/g, "");
103
+ if (!isAbsolute(directory)) continue;
104
+ const cli = join(directory, "node_modules", "npm", "bin", "npm-cli.js");
105
+ if (existsSync(cli)) return { file: process.execPath, args: [cli, ...args] };
106
+ }
107
+ throw new Error("Cannot locate npm's npm-cli.js on PATH.");
108
+ }
109
+
110
+ /** CXXFLAGS with C++20, which the Node 22+ headers require and binding.gyp omits. */
111
+ function withCxx20(cxxflags) {
112
+ const flags = (cxxflags ?? "").trim();
113
+ if (/(?:^|\s)-std=/.test(flags)) return flags;
114
+ return flags ? `${flags} -std=c++20` : "-std=c++20";
115
+ }
116
+
117
+ /**
118
+ * Installed directory of PACKAGE, by walking up the same `node_modules` chain the
119
+ * loader walks: nested in the package (global installs) or hoisted beside it
120
+ * (local project installs), whichever npm produced.
121
+ *
122
+ * Deliberately not `require.resolve`: that asks the loader, whose state belongs to
123
+ * this already-failed process. An earlier revision resolved this way and still got
124
+ * MODULE_NOT_FOUND after the npm install below landed the package (a fresh process
125
+ * resolved the same path fine). A filesystem check reads what is on disk now.
126
+ */
127
+ function packageRoot() {
128
+ for (let dir = root; ; dir = dirname(dir)) {
129
+ const manifest = join(dir, "node_modules", PACKAGE, "package.json");
130
+ if (readJson(manifest)?.name === PACKAGE) return dirname(manifest);
131
+ if (dirname(dir) === dir) throw new Error(`Cannot locate the installed ${PACKAGE} directory`);
132
+ }
133
+ }
134
+
135
+ function heal() {
136
+ const manifest = readJson(join(root, "package.json"));
137
+ const spec = manifest?.optionalDependencies?.[PACKAGE] ?? manifest?.dependencies?.[PACKAGE] ?? "latest";
138
+ const env = { ...process.env, [RECURSION_GUARD]: "1" };
139
+ if (process.platform !== "win32") env.CXXFLAGS = withCxx20(process.env.CXXFLAGS);
140
+ const npm = args => {
141
+ const { file, args: argv } = npmSpawnSpec(args);
142
+ execFileSync(file, argv, { cwd: root, env, stdio: "inherit", timeout: NPM_TIMEOUT_MS });
143
+ };
144
+
145
+ // npm removes an optional dependency whose install script failed, so the package
146
+ // may be absent rather than merely broken. Fetch it without running its scripts:
147
+ // the compile below is the single source of truth for the binding.
148
+ //
149
+ // No `--omit=dev`: `npm install <spec>` reconciles the whole tree, so adding it
150
+ // would delete a developer's devDependencies (measured: 54 packages removed from
151
+ // a checkout) to save inert packages in a consumer's global install. The probe
152
+ // above means this branch only runs where npm actually dropped the package.
153
+ if (!existsSync(join(root, "node_modules", PACKAGE, "package.json"))) {
154
+ console.error(`[native-grammar] ${PACKAGE} is missing; fetching ${spec}`);
155
+ npm(["install", `${PACKAGE}@${spec}`, "--no-save", "--ignore-scripts", "--no-audit", "--no-fund"]);
156
+ }
157
+
158
+ // node-gyp-build loads build/Release ahead of prebuilds, and reports "already
159
+ // built" when either exists. Removing both forces one from-source compile, with
160
+ // the wrong-architecture prebuild that caused this gone for good.
161
+ const installed = packageRoot();
162
+ for (const stale of ["prebuilds", "build"]) {
163
+ rmSync(join(installed, stale), { recursive: true, force: true });
164
+ }
165
+ npm(["rebuild", PACKAGE, "--no-audit", "--no-fund"]);
166
+ }
167
+
168
+ if (!process.env[RECURSION_GUARD] && !grammarWorks()) {
169
+ console.error(
170
+ `[native-grammar] ${PACKAGE} does not load on ${process.platform}/${process.arch}; rebuilding from source`,
171
+ );
172
+ try {
173
+ heal();
174
+ } catch (error) {
175
+ console.error(`[native-grammar] rebuild failed: ${error.message}`);
176
+ }
177
+ if (grammarWorksInFreshProcess()) {
178
+ console.error(`[native-grammar] OK — ${PACKAGE} loads after the rebuild`);
179
+ } else {
180
+ console.error(
181
+ `[native-grammar] WARNING: ${PACKAGE} still does not load. Install a C/C++ toolchain ` +
182
+ "(build-essential on Linux) and re-run `npm run rebuild:native`. TypeScript/TSX " +
183
+ "extraction warns per file until then; nothing else is affected.",
184
+ );
185
+ }
186
+ }
187
+
188
+ process.exit(0);