pi-lens 3.1.2 → 3.2.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/CHANGELOG.md +55 -0
- package/README.md +16 -12
- package/clients/ast-grep-client.js +8 -1
- package/clients/ast-grep-client.ts +9 -1
- package/clients/biome-client.js +51 -38
- package/clients/biome-client.ts +60 -58
- package/clients/dependency-checker.js +30 -1
- package/clients/dependency-checker.ts +35 -1
- package/clients/dispatch/__tests__/runner-registration.test.ts +286 -282
- package/clients/dispatch/bus-dispatcher.js +15 -14
- package/clients/dispatch/bus-dispatcher.ts +32 -25
- package/clients/dispatch/dispatcher.js +18 -25
- package/clients/dispatch/dispatcher.test.ts +2 -1
- package/clients/dispatch/dispatcher.ts +17 -28
- package/clients/dispatch/plan.js +77 -32
- package/clients/dispatch/plan.ts +78 -32
- package/clients/dispatch/runners/ast-grep-napi.js +36 -376
- package/clients/dispatch/runners/ast-grep-napi.ts +60 -433
- package/clients/dispatch/runners/index.js +8 -4
- package/clients/dispatch/runners/index.ts +8 -4
- package/clients/dispatch/runners/lsp.js +65 -0
- package/clients/dispatch/runners/lsp.ts +125 -0
- package/clients/dispatch/runners/oxlint.js +2 -2
- package/clients/dispatch/runners/oxlint.ts +2 -2
- package/clients/dispatch/runners/pyright.js +24 -8
- package/clients/dispatch/runners/pyright.ts +28 -14
- package/clients/dispatch/runners/rust-clippy.js +2 -2
- package/clients/dispatch/runners/rust-clippy.ts +2 -4
- package/clients/dispatch/runners/tree-sitter.js +14 -2
- package/clients/dispatch/runners/tree-sitter.ts +15 -2
- package/clients/dispatch/runners/ts-lsp.js +3 -3
- package/clients/dispatch/runners/ts-lsp.ts +8 -5
- package/clients/dispatch/runners/yaml-rule-parser.js +292 -0
- package/clients/dispatch/runners/yaml-rule-parser.ts +338 -0
- package/clients/dispatch/types.js +3 -0
- package/clients/dispatch/types.ts +3 -0
- package/clients/formatters.js +67 -14
- package/clients/formatters.ts +68 -15
- package/clients/installer/index.js +78 -10
- package/clients/installer/index.ts +519 -426
- package/clients/jscpd-client.js +28 -0
- package/clients/jscpd-client.ts +41 -3
- package/clients/knip-client.js +30 -1
- package/clients/knip-client.ts +34 -2
- package/clients/lsp/__tests__/client.test.ts +64 -41
- package/clients/lsp/__tests__/config.test.ts +25 -17
- package/clients/lsp/__tests__/launch.test.ts +108 -43
- package/clients/lsp/__tests__/service.test.ts +76 -48
- package/clients/lsp/client.js +87 -2
- package/clients/lsp/client.ts +150 -6
- package/clients/lsp/config.js +8 -11
- package/clients/lsp/config.ts +24 -21
- package/clients/lsp/index.js +69 -0
- package/clients/lsp/index.ts +82 -0
- package/clients/lsp/interactive-install.js +19 -8
- package/clients/lsp/interactive-install.ts +52 -27
- package/clients/lsp/launch.js +182 -32
- package/clients/lsp/launch.ts +241 -38
- package/clients/lsp/path-utils.js +3 -46
- package/clients/lsp/path-utils.ts +11 -51
- package/clients/lsp/server.js +93 -71
- package/clients/lsp/server.ts +173 -131
- package/clients/path-utils.js +142 -0
- package/clients/path-utils.ts +153 -0
- package/clients/ruff-client.js +33 -4
- package/clients/ruff-client.ts +44 -13
- package/clients/safe-spawn.js +3 -1
- package/clients/safe-spawn.ts +3 -1
- package/clients/services/effect-integration.js +11 -7
- package/clients/services/effect-integration.ts +34 -26
- package/clients/sg-runner.js +51 -9
- package/clients/sg-runner.ts +58 -15
- package/clients/tree-sitter-client.js +12 -0
- package/clients/tree-sitter-client.ts +12 -0
- package/clients/typescript-client.js +6 -2
- package/clients/typescript-client.ts +9 -2
- package/commands/booboo.js +2 -4
- package/commands/booboo.ts +2 -4
- package/index.ts +377 -93
- package/package.json +2 -1
- package/rules/tree-sitter-queries/tsx/no-nested-links.yml +45 -0
- package/rules/tree-sitter-queries/typescript/constructor-super.yml +55 -0
- package/rules/tree-sitter-queries/typescript/debugger.yml +1 -1
- package/rules/tree-sitter-queries/typescript/no-dupe-class-members.yml +47 -0
- package/tsconfig.json +1 -1
- package/clients/__tests__/file-time.test.js +0 -216
- package/clients/__tests__/format-service.test.js +0 -245
- package/clients/__tests__/formatters.test.js +0 -271
- package/clients/agent-behavior-client.test.js +0 -94
- package/clients/ast-grep-client.test.js +0 -129
- package/clients/ast-grep-client.test.ts +0 -155
- package/clients/biome-client.test.js +0 -144
- package/clients/cache-manager.test.js +0 -197
- package/clients/complexity-client.test.js +0 -234
- package/clients/dependency-checker.test.js +0 -60
- package/clients/dispatch/__tests__/autofix-integration.test.js +0 -245
- package/clients/dispatch/__tests__/runner-registration.test.js +0 -236
- package/clients/dispatch/dispatcher.edge.test.js +0 -82
- package/clients/dispatch/dispatcher.format.test.js +0 -46
- package/clients/dispatch/dispatcher.inline.test.js +0 -74
- package/clients/dispatch/dispatcher.test.js +0 -115
- package/clients/dispatch/runners/architect.test.js +0 -138
- package/clients/dispatch/runners/ast-grep-napi.test.js +0 -106
- package/clients/dispatch/runners/oxlint.test.js +0 -230
- package/clients/dispatch/runners/pyright.test.js +0 -98
- package/clients/dispatch/runners/python-slop.test.js +0 -203
- package/clients/dispatch/runners/scan_codebase.test.js +0 -89
- package/clients/dispatch/runners/shellcheck.test.js +0 -98
- package/clients/dispatch/runners/spellcheck.test.js +0 -158
- package/clients/dispatch/runners/ts-slop.test.js +0 -180
- package/clients/dispatch/runners/ts-slop.test.ts +0 -230
- package/clients/dogfood.test.js +0 -201
- package/clients/file-kinds.test.js +0 -169
- package/clients/go-client.test.js +0 -127
- package/clients/jscpd-client.test.js +0 -127
- package/clients/knip-client.test.js +0 -112
- package/clients/lsp/__tests__/client.test.js +0 -325
- package/clients/lsp/__tests__/config.test.js +0 -166
- package/clients/lsp/__tests__/error-recovery.test.js +0 -213
- package/clients/lsp/__tests__/integration.test.js +0 -127
- package/clients/lsp/__tests__/launch.test.js +0 -260
- package/clients/lsp/__tests__/server.test.js +0 -259
- package/clients/lsp/__tests__/service.test.js +0 -417
- package/clients/metrics-client.test.js +0 -141
- package/clients/ruff-client.test.js +0 -132
- package/clients/rust-client.test.js +0 -108
- package/clients/sanitize.test.js +0 -177
- package/clients/secrets-scanner.test.js +0 -100
- package/clients/services/__tests__/effect-integration.test.js +0 -86
- package/clients/test-runner-client.test.js +0 -192
- package/clients/todo-scanner.test.js +0 -301
- package/clients/type-coverage-client.test.js +0 -105
- package/clients/typescript-client.codefix.test.js +0 -157
- package/clients/typescript-client.test.js +0 -105
- package/commands/clients/ast-grep-client.js +0 -250
- package/commands/clients/ast-grep-parser.js +0 -86
- package/commands/clients/ast-grep-rule-manager.js +0 -91
- package/commands/clients/ast-grep-types.js +0 -9
- package/commands/clients/biome-client.js +0 -380
- package/commands/clients/complexity-client.js +0 -667
- package/commands/clients/file-kinds.js +0 -177
- package/commands/clients/file-utils.js +0 -40
- package/commands/clients/jscpd-client.js +0 -169
- package/commands/clients/knip-client.js +0 -211
- package/commands/clients/ruff-client.js +0 -297
- package/commands/clients/safe-spawn.js +0 -88
- package/commands/clients/scan-utils.js +0 -83
- package/commands/clients/sg-runner.js +0 -190
- package/commands/clients/types.js +0 -11
- package/commands/clients/typescript-client.js +0 -505
- package/commands/rate.test.js +0 -119
- package/rules/ast-grep-rules/rules/no-dangerously-set-inner-html.yml +0 -13
- package/rules/ast-grep-rules/rules/no-debugger.yml +0 -12
- package/rules/ast-grep-rules/rules/no-eval.yml +0 -13
package/clients/sg-runner.js
CHANGED
|
@@ -15,25 +15,67 @@ import { safeSpawn } from "./safe-spawn.js";
|
|
|
15
15
|
*/
|
|
16
16
|
function escapeWindowsArg(arg) {
|
|
17
17
|
// If no special characters, return as-is
|
|
18
|
-
if (!/[\s
|
|
18
|
+
if (!/[\s"]/.test(arg))
|
|
19
19
|
return arg;
|
|
20
20
|
// Escape quotes by doubling them
|
|
21
|
-
return `"${arg.replace(/"/g, "
|
|
21
|
+
return `"${arg.replace(/"/g, '""')}"`;
|
|
22
22
|
}
|
|
23
23
|
export class SgRunner {
|
|
24
24
|
constructor(verbose = false) {
|
|
25
|
+
this.sgPath = null;
|
|
26
|
+
this.available = null;
|
|
25
27
|
this.log = verbose
|
|
26
28
|
? (msg) => console.error(`[sg-runner] ${msg}`)
|
|
27
29
|
: () => { };
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
|
-
* Check if ast-grep CLI is available
|
|
32
|
+
* Check if ast-grep CLI is available, auto-install if not
|
|
33
|
+
*/
|
|
34
|
+
async ensureAvailable() {
|
|
35
|
+
// Fast path: already checked
|
|
36
|
+
if (this.available !== null)
|
|
37
|
+
return this.available;
|
|
38
|
+
// Check if available in PATH (fast)
|
|
39
|
+
const pathResult = safeSpawn("sg", ["--version"], {
|
|
40
|
+
timeout: 5000,
|
|
41
|
+
});
|
|
42
|
+
if (!pathResult.error && pathResult.status === 0) {
|
|
43
|
+
this.sgPath = "sg";
|
|
44
|
+
this.available = true;
|
|
45
|
+
this.log("ast-grep found in PATH");
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
// Auto-install via pi-lens installer
|
|
49
|
+
this.log("ast-grep not found, attempting auto-install...");
|
|
50
|
+
const { ensureTool } = await import("./installer/index.js");
|
|
51
|
+
const installedPath = await ensureTool("ast-grep");
|
|
52
|
+
if (installedPath) {
|
|
53
|
+
this.sgPath = installedPath;
|
|
54
|
+
this.available = true;
|
|
55
|
+
this.log(`ast-grep auto-installed: ${installedPath}`);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
this.available = false;
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if ast-grep CLI is available (legacy sync method)
|
|
63
|
+
* Prefer ensureAvailable() for auto-install behavior
|
|
31
64
|
*/
|
|
32
65
|
isAvailable() {
|
|
66
|
+
if (this.available !== null)
|
|
67
|
+
return this.available;
|
|
33
68
|
const result = safeSpawn("npx", ["sg", "--version"], {
|
|
34
69
|
timeout: 10000,
|
|
35
70
|
});
|
|
36
|
-
|
|
71
|
+
this.available = !result.error && result.status === 0;
|
|
72
|
+
return this.available;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get the sg command to use (local binary or "sg" from PATH)
|
|
76
|
+
*/
|
|
77
|
+
getSgCommand() {
|
|
78
|
+
return this.sgPath || "sg";
|
|
37
79
|
}
|
|
38
80
|
/**
|
|
39
81
|
* Run ast-grep asynchronously, return parsed matches
|
|
@@ -54,12 +96,12 @@ export class SgRunner {
|
|
|
54
96
|
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
55
97
|
}
|
|
56
98
|
// For other args with spaces/special chars, use double quotes
|
|
57
|
-
if (/[\s
|
|
58
|
-
return `"${arg.replace(/"/g, "
|
|
99
|
+
if (/[\s"]/.test(arg)) {
|
|
100
|
+
return `"${arg.replace(/"/g, '\\"')}"`;
|
|
59
101
|
}
|
|
60
102
|
return arg;
|
|
61
103
|
});
|
|
62
|
-
const bashCommand =
|
|
104
|
+
const bashCommand = `${this.getSgCommand()} ${escapedArgs.join(" ")}`;
|
|
63
105
|
proc = spawn("bash", ["-c", bashCommand], {
|
|
64
106
|
stdio: ["ignore", "pipe", "pipe"],
|
|
65
107
|
windowsHide: true,
|
|
@@ -67,7 +109,7 @@ export class SgRunner {
|
|
|
67
109
|
}
|
|
68
110
|
else if (isWindows) {
|
|
69
111
|
// Fallback: use cmd.exe with standard escaping
|
|
70
|
-
const fullCommand =
|
|
112
|
+
const fullCommand = `${this.getSgCommand()} ${args.map(escapeWindowsArg).join(" ")}`;
|
|
71
113
|
proc = spawn(fullCommand, {
|
|
72
114
|
stdio: ["ignore", "pipe", "pipe"],
|
|
73
115
|
shell: true,
|
|
@@ -76,7 +118,7 @@ export class SgRunner {
|
|
|
76
118
|
}
|
|
77
119
|
else {
|
|
78
120
|
// Unix: normal spawn without shell
|
|
79
|
-
proc = spawn(
|
|
121
|
+
proc = spawn(this.getSgCommand(), args, {
|
|
80
122
|
stdio: ["ignore", "pipe", "pipe"],
|
|
81
123
|
});
|
|
82
124
|
}
|
package/clients/sg-runner.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Handles: spawn, spawnSync, temp dir management, JSON parsing.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { spawn
|
|
8
|
+
import { spawn } from "node:child_process";
|
|
9
9
|
import * as fs from "node:fs";
|
|
10
10
|
import * as os from "node:os";
|
|
11
11
|
import * as path from "node:path";
|
|
@@ -17,10 +17,10 @@ import { safeSpawn } from "./safe-spawn.js";
|
|
|
17
17
|
*/
|
|
18
18
|
function escapeWindowsArg(arg: string): string {
|
|
19
19
|
// If no special characters, return as-is
|
|
20
|
-
if (!/[\s
|
|
20
|
+
if (!/[\s"]/.test(arg)) return arg;
|
|
21
21
|
|
|
22
22
|
// Escape quotes by doubling them
|
|
23
|
-
return `"${arg.replace(/"/g, "
|
|
23
|
+
return `"${arg.replace(/"/g, '""')}"`;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export interface SgMatch {
|
|
@@ -40,6 +40,8 @@ export interface SgResult {
|
|
|
40
40
|
|
|
41
41
|
export class SgRunner {
|
|
42
42
|
private log: (msg: string) => void;
|
|
43
|
+
private sgPath: string | null = null;
|
|
44
|
+
private available: boolean | null = null;
|
|
43
45
|
|
|
44
46
|
constructor(verbose = false) {
|
|
45
47
|
this.log = verbose
|
|
@@ -48,13 +50,58 @@ export class SgRunner {
|
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
/**
|
|
51
|
-
* Check if ast-grep CLI is available
|
|
53
|
+
* Check if ast-grep CLI is available, auto-install if not
|
|
54
|
+
*/
|
|
55
|
+
async ensureAvailable(): Promise<boolean> {
|
|
56
|
+
// Fast path: already checked
|
|
57
|
+
if (this.available !== null) return this.available;
|
|
58
|
+
|
|
59
|
+
// Check if available in PATH (fast)
|
|
60
|
+
const pathResult = safeSpawn("sg", ["--version"], {
|
|
61
|
+
timeout: 5000,
|
|
62
|
+
});
|
|
63
|
+
if (!pathResult.error && pathResult.status === 0) {
|
|
64
|
+
this.sgPath = "sg";
|
|
65
|
+
this.available = true;
|
|
66
|
+
this.log("ast-grep found in PATH");
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Auto-install via pi-lens installer
|
|
71
|
+
this.log("ast-grep not found, attempting auto-install...");
|
|
72
|
+
const { ensureTool } = await import("./installer/index.js");
|
|
73
|
+
const installedPath = await ensureTool("ast-grep");
|
|
74
|
+
|
|
75
|
+
if (installedPath) {
|
|
76
|
+
this.sgPath = installedPath;
|
|
77
|
+
this.available = true;
|
|
78
|
+
this.log(`ast-grep auto-installed: ${installedPath}`);
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
this.available = false;
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Check if ast-grep CLI is available (legacy sync method)
|
|
88
|
+
* Prefer ensureAvailable() for auto-install behavior
|
|
52
89
|
*/
|
|
53
90
|
isAvailable(): boolean {
|
|
91
|
+
if (this.available !== null) return this.available;
|
|
92
|
+
|
|
54
93
|
const result = safeSpawn("npx", ["sg", "--version"], {
|
|
55
94
|
timeout: 10000,
|
|
56
95
|
});
|
|
57
|
-
|
|
96
|
+
this.available = !result.error && result.status === 0;
|
|
97
|
+
return this.available;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get the sg command to use (local binary or "sg" from PATH)
|
|
102
|
+
*/
|
|
103
|
+
private getSgCommand(): string {
|
|
104
|
+
return this.sgPath || "sg";
|
|
58
105
|
}
|
|
59
106
|
|
|
60
107
|
/**
|
|
@@ -77,19 +124,19 @@ export class SgRunner {
|
|
|
77
124
|
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
78
125
|
}
|
|
79
126
|
// For other args with spaces/special chars, use double quotes
|
|
80
|
-
if (/[\s
|
|
81
|
-
return `"${arg.replace(/"/g, "
|
|
127
|
+
if (/[\s"]/.test(arg)) {
|
|
128
|
+
return `"${arg.replace(/"/g, '\\"')}"`;
|
|
82
129
|
}
|
|
83
130
|
return arg;
|
|
84
131
|
});
|
|
85
|
-
const bashCommand =
|
|
132
|
+
const bashCommand = `${this.getSgCommand()} ${escapedArgs.join(" ")}`;
|
|
86
133
|
proc = spawn("bash", ["-c", bashCommand], {
|
|
87
134
|
stdio: ["ignore", "pipe", "pipe"],
|
|
88
135
|
windowsHide: true,
|
|
89
136
|
});
|
|
90
137
|
} else if (isWindows) {
|
|
91
138
|
// Fallback: use cmd.exe with standard escaping
|
|
92
|
-
const fullCommand =
|
|
139
|
+
const fullCommand = `${this.getSgCommand()} ${args.map(escapeWindowsArg).join(" ")}`;
|
|
93
140
|
proc = spawn(fullCommand, {
|
|
94
141
|
stdio: ["ignore", "pipe", "pipe"],
|
|
95
142
|
shell: true,
|
|
@@ -97,7 +144,7 @@ export class SgRunner {
|
|
|
97
144
|
});
|
|
98
145
|
} else {
|
|
99
146
|
// Unix: normal spawn without shell
|
|
100
|
-
proc = spawn(
|
|
147
|
+
proc = spawn(this.getSgCommand(), args, {
|
|
101
148
|
stdio: ["ignore", "pipe", "pipe"],
|
|
102
149
|
});
|
|
103
150
|
}
|
|
@@ -206,11 +253,7 @@ export class SgRunner {
|
|
|
206
253
|
/**
|
|
207
254
|
* Run a rule file scan (temporary config approach) - alias for tempScan
|
|
208
255
|
*/
|
|
209
|
-
scanWithRule(
|
|
210
|
-
ruleYaml: string,
|
|
211
|
-
dir: string,
|
|
212
|
-
timeout = 30000,
|
|
213
|
-
): SgMatch[] {
|
|
256
|
+
scanWithRule(ruleYaml: string, dir: string, timeout = 30000): SgMatch[] {
|
|
214
257
|
const sessionDir = path.join(os.tmpdir(), `sg-scan-${Date.now()}`);
|
|
215
258
|
const rulesSubdir = path.join(sessionDir, "rules");
|
|
216
259
|
const configFile = path.join(sessionDir, ".sgconfig.yml");
|
|
@@ -446,6 +446,18 @@ export class TreeSitterClient {
|
|
|
446
446
|
continue; // Skip console.dbg()
|
|
447
447
|
}
|
|
448
448
|
}
|
|
449
|
+
if (postFilter === "no_super_call") {
|
|
450
|
+
const bodyNode = captures.BODY;
|
|
451
|
+
if (bodyNode) {
|
|
452
|
+
// Check if body contains actual super() call (not in comments)
|
|
453
|
+
const bodyText = bodyNode.text;
|
|
454
|
+
// Match super() or super.method() but not // super() in comments
|
|
455
|
+
const superCallRegex = /(?<!\/\/.*)super\s*\(/;
|
|
456
|
+
const hasSuperCall = superCallRegex.test(bodyText);
|
|
457
|
+
if (hasSuperCall)
|
|
458
|
+
continue; // Skip if has super() - this is the GOOD case
|
|
459
|
+
}
|
|
460
|
+
}
|
|
449
461
|
// Use first capture for position info
|
|
450
462
|
if (match.captures.length > 0) {
|
|
451
463
|
const firstNode = match.captures[0].node;
|
|
@@ -650,6 +650,18 @@ export class TreeSitterClient {
|
|
|
650
650
|
}
|
|
651
651
|
}
|
|
652
652
|
|
|
653
|
+
if (postFilter === "no_super_call") {
|
|
654
|
+
const bodyNode = captures.BODY;
|
|
655
|
+
if (bodyNode) {
|
|
656
|
+
// Check if body contains actual super() call (not in comments)
|
|
657
|
+
const bodyText = bodyNode.text;
|
|
658
|
+
// Match super() or super.method() but not // super() in comments
|
|
659
|
+
const superCallRegex = /(?<!\/\/.*)super\s*\(/;
|
|
660
|
+
const hasSuperCall = superCallRegex.test(bodyText);
|
|
661
|
+
if (hasSuperCall) continue; // Skip if has super() - this is the GOOD case
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
653
665
|
// Use first capture for position info
|
|
654
666
|
if (match.captures.length > 0) {
|
|
655
667
|
const firstNode = match.captures[0].node;
|
|
@@ -462,9 +462,13 @@ export class TypeScriptClient {
|
|
|
462
462
|
* Get all quick fixes for all diagnostics in a file.
|
|
463
463
|
* Returns a map of diagnostic line → fixes.
|
|
464
464
|
*/
|
|
465
|
-
|
|
465
|
+
/**
|
|
466
|
+
* Accept pre-computed diagnostics to avoid a second getSemanticDiagnostics call
|
|
467
|
+
* when the caller already has them (saves ~1–2s on large files).
|
|
468
|
+
*/
|
|
469
|
+
getAllCodeFixes(filePath, precomputedDiags) {
|
|
466
470
|
const fixesByLine = new Map();
|
|
467
|
-
const diagnostics = this.getDiagnostics(filePath);
|
|
471
|
+
const diagnostics = precomputedDiags ?? this.getDiagnostics(filePath);
|
|
468
472
|
for (const diag of diagnostics) {
|
|
469
473
|
if (diag.severity !== 1 || diag.code === undefined)
|
|
470
474
|
continue;
|
|
@@ -617,7 +617,14 @@ export class TypeScriptClient {
|
|
|
617
617
|
* Get all quick fixes for all diagnostics in a file.
|
|
618
618
|
* Returns a map of diagnostic line → fixes.
|
|
619
619
|
*/
|
|
620
|
-
|
|
620
|
+
/**
|
|
621
|
+
* Accept pre-computed diagnostics to avoid a second getSemanticDiagnostics call
|
|
622
|
+
* when the caller already has them (saves ~1–2s on large files).
|
|
623
|
+
*/
|
|
624
|
+
getAllCodeFixes(
|
|
625
|
+
filePath: string,
|
|
626
|
+
precomputedDiags?: Diagnostic[],
|
|
627
|
+
): Map<
|
|
621
628
|
number,
|
|
622
629
|
Array<{
|
|
623
630
|
description: string;
|
|
@@ -644,7 +651,7 @@ export class TypeScriptClient {
|
|
|
644
651
|
}>
|
|
645
652
|
>();
|
|
646
653
|
|
|
647
|
-
const diagnostics = this.getDiagnostics(filePath);
|
|
654
|
+
const diagnostics = precomputedDiags ?? this.getDiagnostics(filePath);
|
|
648
655
|
for (const diag of diagnostics) {
|
|
649
656
|
if (diag.severity !== 1 || diag.code === undefined) continue;
|
|
650
657
|
const fixes = this.getCodeFixes(
|
package/commands/booboo.js
CHANGED
|
@@ -44,8 +44,8 @@ export async function handleBooboo(args, ctx, clients, pi) {
|
|
|
44
44
|
const targetPath = args.trim() || ctx.cwd || process.cwd();
|
|
45
45
|
// Detect project metadata for richer reporting
|
|
46
46
|
const projectMeta = detectProjectMetadata(targetPath);
|
|
47
|
-
const
|
|
48
|
-
|
|
47
|
+
const _metaDisplay = formatProjectMetadata(projectMeta);
|
|
48
|
+
// No noisy notification at start - just run the review silently
|
|
49
49
|
// Detect project type once for all runners
|
|
50
50
|
const isTsProject = nodeFs.existsSync(path.join(targetPath, "tsconfig.json"));
|
|
51
51
|
// Get available commands for the project
|
|
@@ -966,9 +966,7 @@ ${fullReport.join("\n")}`;
|
|
|
966
966
|
const summaryLines = [
|
|
967
967
|
`📊 Code Review: ${totalIssues} issues`,
|
|
968
968
|
...runnerLines,
|
|
969
|
-
` 🔧 ${fixableCount} fixable | 🏗️ ${refactorNeeded} refactor`,
|
|
970
969
|
` ⏱️ Total: ${jsonReport.meta.totalTime}`,
|
|
971
|
-
`📄 JSON: ${jsonPath}`,
|
|
972
970
|
`📄 MD: ${mdPath}`,
|
|
973
971
|
];
|
|
974
972
|
ctx.ui.notify(summaryLines.join("\n"), "info");
|
package/commands/booboo.ts
CHANGED
|
@@ -82,9 +82,9 @@ export async function handleBooboo(
|
|
|
82
82
|
|
|
83
83
|
// Detect project metadata for richer reporting
|
|
84
84
|
const projectMeta = detectProjectMetadata(targetPath);
|
|
85
|
-
const
|
|
85
|
+
const _metaDisplay = formatProjectMetadata(projectMeta);
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
// No noisy notification at start - just run the review silently
|
|
88
88
|
|
|
89
89
|
// Detect project type once for all runners
|
|
90
90
|
const isTsProject = nodeFs.existsSync(path.join(targetPath, "tsconfig.json"));
|
|
@@ -1229,9 +1229,7 @@ ${fullReport.join("\n")}`;
|
|
|
1229
1229
|
const summaryLines = [
|
|
1230
1230
|
`📊 Code Review: ${totalIssues} issues`,
|
|
1231
1231
|
...runnerLines,
|
|
1232
|
-
` 🔧 ${fixableCount} fixable | 🏗️ ${refactorNeeded} refactor`,
|
|
1233
1232
|
` ⏱️ Total: ${jsonReport.meta.totalTime}`,
|
|
1234
|
-
`📄 JSON: ${jsonPath}`,
|
|
1235
1233
|
`📄 MD: ${mdPath}`,
|
|
1236
1234
|
];
|
|
1237
1235
|
|