pi-lens 2.2.9 → 3.0.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 +198 -0
- package/README.md +709 -519
- package/clients/__tests__/file-time.test.js +216 -0
- package/clients/__tests__/file-time.test.ts +276 -0
- package/clients/__tests__/format-service.test.js +245 -0
- package/clients/__tests__/format-service.test.ts +339 -0
- package/clients/__tests__/formatters.test.js +271 -0
- package/clients/__tests__/formatters.test.ts +401 -0
- package/clients/amain-types.js +164 -0
- package/clients/amain-types.ts +165 -0
- package/clients/architect-client.js +56 -12
- package/clients/architect-client.ts +81 -16
- package/clients/ast-grep-client.js +2 -2
- package/clients/ast-grep-client.ts +14 -39
- package/clients/ast-grep-parser.ts +1 -1
- package/clients/ast-grep-rule-manager.js +8 -0
- package/clients/ast-grep-rule-manager.ts +10 -1
- package/clients/ast-grep-types.js +9 -0
- package/clients/ast-grep-types.ts +106 -0
- package/clients/auto-loop.js +10 -0
- package/clients/auto-loop.ts +14 -1
- package/clients/biome-client.js +81 -19
- package/clients/biome-client.ts +103 -22
- package/clients/bus/bus.js +191 -0
- package/clients/bus/bus.ts +251 -0
- package/clients/bus/events.js +214 -0
- package/clients/bus/events.ts +279 -0
- package/clients/bus/index.js +8 -0
- package/clients/bus/index.ts +9 -0
- package/clients/bus/integration.js +158 -0
- package/clients/bus/integration.ts +214 -0
- package/clients/complexity-client.js +13 -7
- package/clients/complexity-client.ts +13 -7
- package/clients/config-validator.js +465 -0
- package/clients/config-validator.ts +558 -0
- package/clients/dependency-checker.js +4 -10
- package/clients/dependency-checker.ts +4 -10
- package/clients/dispatch/__tests__/autofix-integration.test.js +245 -0
- package/clients/dispatch/__tests__/autofix-integration.test.ts +300 -0
- package/clients/dispatch/__tests__/runner-registration.test.js +236 -0
- package/clients/dispatch/__tests__/runner-registration.test.ts +282 -0
- package/clients/dispatch/bus-dispatcher.js +177 -0
- package/clients/dispatch/bus-dispatcher.ts +251 -0
- package/clients/dispatch/dispatcher.edge.test.js +82 -0
- package/clients/dispatch/dispatcher.edge.test.ts +100 -0
- package/clients/dispatch/dispatcher.format.test.js +46 -0
- package/clients/dispatch/dispatcher.format.test.ts +58 -0
- package/clients/dispatch/dispatcher.inline.test.js +74 -0
- package/clients/dispatch/dispatcher.inline.test.ts +93 -0
- package/clients/dispatch/dispatcher.js +19 -53
- package/clients/dispatch/dispatcher.ts +20 -67
- package/clients/dispatch/plan.js +9 -4
- package/clients/dispatch/plan.ts +9 -4
- package/clients/dispatch/runners/architect.js +21 -7
- package/clients/dispatch/runners/architect.test.js +138 -0
- package/clients/dispatch/runners/architect.test.ts +162 -0
- package/clients/dispatch/runners/architect.ts +22 -7
- package/clients/dispatch/runners/ast-grep-napi.js +462 -0
- package/clients/dispatch/runners/ast-grep-napi.test.js +111 -0
- package/clients/dispatch/runners/ast-grep-napi.test.ts +133 -0
- package/clients/dispatch/runners/ast-grep-napi.ts +506 -0
- package/clients/dispatch/runners/ast-grep.js +62 -19
- package/clients/dispatch/runners/ast-grep.ts +70 -18
- package/clients/dispatch/runners/biome.js +29 -53
- package/clients/dispatch/runners/biome.ts +29 -63
- package/clients/dispatch/runners/config-validation.js +67 -0
- package/clients/dispatch/runners/config-validation.ts +82 -0
- package/clients/dispatch/runners/go-vet.js +4 -28
- package/clients/dispatch/runners/go-vet.ts +4 -32
- package/clients/dispatch/runners/index.js +30 -10
- package/clients/dispatch/runners/index.ts +30 -10
- package/clients/dispatch/runners/oxlint.js +141 -0
- package/clients/dispatch/runners/oxlint.test.js +230 -0
- package/clients/dispatch/runners/oxlint.test.ts +303 -0
- package/clients/dispatch/runners/oxlint.ts +175 -0
- package/clients/dispatch/runners/pyright.js +40 -70
- package/clients/dispatch/runners/pyright.test.js +16 -2
- package/clients/dispatch/runners/pyright.test.ts +14 -2
- package/clients/dispatch/runners/pyright.ts +48 -91
- package/clients/dispatch/runners/python-slop.js +97 -0
- package/clients/dispatch/runners/python-slop.test.js +203 -0
- package/clients/dispatch/runners/python-slop.test.ts +298 -0
- package/clients/dispatch/runners/python-slop.ts +124 -0
- package/clients/dispatch/runners/ruff.js +18 -71
- package/clients/dispatch/runners/ruff.ts +19 -79
- package/clients/dispatch/runners/rust-clippy.js +28 -32
- package/clients/dispatch/runners/rust-clippy.ts +29 -31
- package/clients/dispatch/runners/scan_codebase.test.js +89 -0
- package/clients/dispatch/runners/scan_codebase.test.ts +105 -0
- package/clients/dispatch/runners/shellcheck.js +147 -0
- package/clients/dispatch/runners/shellcheck.test.js +98 -0
- package/clients/dispatch/runners/shellcheck.test.ts +129 -0
- package/clients/dispatch/runners/shellcheck.ts +188 -0
- package/clients/dispatch/runners/similarity.js +230 -0
- package/clients/dispatch/runners/similarity.ts +339 -0
- package/clients/dispatch/runners/spellcheck.js +106 -0
- package/clients/dispatch/runners/spellcheck.test.js +158 -0
- package/clients/dispatch/runners/spellcheck.test.ts +214 -0
- package/clients/dispatch/runners/spellcheck.ts +136 -0
- package/clients/dispatch/runners/tree-sitter.js +107 -0
- package/clients/dispatch/runners/tree-sitter.ts +135 -0
- package/clients/dispatch/runners/ts-lsp.js +104 -33
- package/clients/dispatch/runners/ts-lsp.ts +120 -38
- package/clients/dispatch/runners/ts-slop.js +113 -0
- package/clients/dispatch/runners/ts-slop.test.js +180 -0
- package/clients/dispatch/runners/ts-slop.test.ts +230 -0
- package/clients/dispatch/runners/ts-slop.ts +142 -0
- package/clients/dispatch/runners/utils/diagnostic-parsers.js +134 -0
- package/clients/dispatch/runners/utils/diagnostic-parsers.ts +186 -0
- package/clients/dispatch/runners/utils/runner-helpers.js +115 -0
- package/clients/dispatch/runners/utils/runner-helpers.ts +167 -0
- package/clients/dispatch/runners/utils.js +2 -4
- package/clients/dispatch/runners/utils.ts +2 -4
- package/clients/dispatch/types.ts +1 -1
- package/clients/dispatch/utils/format-utils.js +49 -0
- package/clients/dispatch/utils/format-utils.ts +60 -0
- package/clients/dogfood.test.js +201 -0
- package/clients/dogfood.test.ts +269 -0
- package/clients/file-time.js +152 -0
- package/clients/file-time.ts +208 -0
- package/clients/file-utils.js +40 -0
- package/clients/file-utils.ts +44 -0
- package/clients/fix-scanners.js +10 -20
- package/clients/fix-scanners.ts +10 -22
- package/clients/format-service.js +172 -0
- package/clients/format-service.ts +254 -0
- package/clients/formatters.js +435 -0
- package/clients/formatters.ts +508 -0
- package/clients/go-client.js +5 -14
- package/clients/go-client.ts +5 -13
- package/clients/installer/index.js +356 -0
- package/clients/installer/index.ts +426 -0
- package/clients/jscpd-client.js +11 -9
- package/clients/jscpd-client.ts +12 -8
- package/clients/knip-client.js +3 -7
- package/clients/knip-client.ts +3 -6
- package/clients/lsp/__tests__/client.test.js +325 -0
- package/clients/lsp/__tests__/client.test.ts +434 -0
- package/clients/lsp/__tests__/config.test.js +166 -0
- package/clients/lsp/__tests__/config.test.ts +209 -0
- package/clients/lsp/__tests__/error-recovery.test.js +213 -0
- package/clients/lsp/__tests__/error-recovery.test.ts +279 -0
- package/clients/lsp/__tests__/integration.test.js +127 -0
- package/clients/lsp/__tests__/integration.test.ts +160 -0
- package/clients/lsp/__tests__/launch.test.js +260 -0
- package/clients/lsp/__tests__/launch.test.ts +329 -0
- package/clients/lsp/__tests__/server.test.js +259 -0
- package/clients/lsp/__tests__/server.test.ts +332 -0
- package/clients/lsp/__tests__/service.test.js +417 -0
- package/clients/lsp/__tests__/service.test.ts +499 -0
- package/clients/lsp/client.js +235 -0
- package/clients/lsp/client.ts +328 -0
- package/clients/lsp/config.js +115 -0
- package/clients/lsp/config.ts +149 -0
- package/clients/lsp/index.js +222 -0
- package/clients/lsp/index.ts +280 -0
- package/clients/lsp/installer/index.js +391 -0
- package/clients/lsp/interactive-install.js +210 -0
- package/clients/lsp/interactive-install.ts +251 -0
- package/clients/lsp/language.js +170 -0
- package/clients/lsp/language.ts +216 -0
- package/clients/lsp/launch.js +174 -0
- package/clients/lsp/launch.ts +240 -0
- package/clients/lsp/lsp/launch.js +116 -0
- package/clients/lsp/lsp/server.js +532 -0
- package/clients/lsp/lsp-index.js +10 -0
- package/clients/lsp/lsp-index.ts +11 -0
- package/clients/lsp/path-utils.js +48 -0
- package/clients/lsp/path-utils.ts +52 -0
- package/clients/lsp/server.js +615 -0
- package/clients/lsp/server.ts +800 -0
- package/clients/lsp/test-py-spawn/requirements.txt +1 -0
- package/clients/lsp/test-py-spawn/test.py +3 -0
- package/clients/lsp/test-py-svc/requirements.txt +1 -0
- package/clients/lsp/test-py-svc/test.py +3 -0
- package/clients/lsp/test-python-project/requirements.txt +1 -0
- package/clients/lsp/test-python-project/test.py +5 -0
- package/clients/metrics-history.js +2 -2
- package/clients/metrics-history.ts +2 -2
- package/clients/production-readiness.js +522 -0
- package/clients/production-readiness.ts +556 -0
- package/clients/project-index.js +255 -0
- package/clients/project-index.ts +383 -0
- package/clients/project-metadata.js +531 -0
- package/clients/project-metadata.ts +624 -0
- package/clients/ruff-client.js +56 -16
- package/clients/ruff-client.ts +72 -15
- package/clients/runner-tracker.js +152 -0
- package/clients/runner-tracker.ts +213 -0
- package/clients/rust-client.js +4 -11
- package/clients/rust-client.ts +5 -11
- package/clients/safe-spawn.js +96 -0
- package/clients/safe-spawn.ts +128 -0
- package/clients/scan-architectural-debt.js +3 -6
- package/clients/scan-architectural-debt.ts +3 -6
- package/clients/scan-utils.js +5 -20
- package/clients/scan-utils.ts +5 -29
- package/clients/secrets-scanner.js +3 -17
- package/clients/secrets-scanner.ts +4 -20
- package/clients/services/__tests__/effect-integration.test.js +86 -0
- package/clients/services/__tests__/effect-integration.test.ts +111 -0
- package/clients/services/effect-integration.js +194 -0
- package/clients/services/effect-integration.ts +268 -0
- package/clients/services/index.js +7 -0
- package/clients/services/index.ts +8 -0
- package/clients/services/runner-service.js +105 -0
- package/clients/services/runner-service.ts +179 -0
- package/clients/sg-runner.js +87 -13
- package/clients/sg-runner.ts +97 -13
- package/clients/state-matrix.js +160 -0
- package/clients/state-matrix.ts +202 -0
- package/clients/subprocess-client.js +10 -9
- package/clients/subprocess-client.ts +10 -8
- package/clients/test-runner-client.js +3 -7
- package/clients/test-runner-client.ts +3 -6
- package/clients/tool-availability.js +4 -10
- package/clients/tool-availability.ts +4 -9
- package/clients/tree-sitter-client.js +564 -0
- package/clients/tree-sitter-client.ts +797 -0
- package/clients/tree-sitter-query-loader.js +355 -0
- package/clients/tree-sitter-query-loader.ts +425 -0
- package/clients/type-coverage-client.js +3 -7
- package/clients/type-coverage-client.ts +3 -6
- package/clients/typescript-client.codefix.test.js +157 -0
- package/clients/typescript-client.codefix.test.ts +186 -0
- package/clients/typescript-client.js +43 -0
- package/clients/typescript-client.ts +98 -0
- package/commands/booboo.js +799 -219
- package/commands/booboo.ts +1004 -225
- package/commands/clients/ast-grep-client.js +250 -0
- package/commands/clients/ast-grep-parser.js +86 -0
- package/commands/clients/ast-grep-rule-manager.js +91 -0
- package/commands/clients/ast-grep-types.js +9 -0
- package/commands/clients/biome-client.js +380 -0
- package/commands/clients/complexity-client.js +667 -0
- package/commands/clients/file-kinds.js +177 -0
- package/commands/clients/file-utils.js +40 -0
- package/commands/clients/jscpd-client.js +169 -0
- package/commands/clients/knip-client.js +211 -0
- package/commands/clients/ruff-client.js +297 -0
- package/commands/clients/safe-spawn.js +88 -0
- package/commands/clients/scan-utils.js +83 -0
- package/commands/clients/sg-runner.js +190 -0
- package/commands/clients/types.js +11 -0
- package/commands/clients/typescript-client.js +505 -0
- package/commands/fix-from-booboo.js +398 -0
- package/commands/fix-from-booboo.ts +485 -0
- package/commands/fix-simplified.js +618 -0
- package/commands/fix-simplified.ts +768 -0
- package/commands/rate.js +10 -14
- package/commands/rate.ts +9 -16
- package/default-architect.yaml +59 -15
- package/index.ts +342 -429
- package/package.json +16 -3
- package/rules/ast-grep-rules/rules/empty-catch.yml +38 -13
- package/rules/ast-grep-rules/rules/no-array-constructor.yml +1 -0
- package/rules/ast-grep-rules/rules/no-debugger.yml +2 -0
- package/rules/python-slop-rules/.sgconfig.yml +4 -0
- package/rules/python-slop-rules/rules/slop-rules.yml +647 -0
- package/rules/tree-sitter-queries/python/bare-except.yml +54 -0
- package/rules/tree-sitter-queries/python/eval-exec.yml +50 -0
- package/rules/tree-sitter-queries/python/is-vs-equals.yml +60 -0
- package/rules/tree-sitter-queries/python/mutable-default-arg.yml +57 -0
- package/rules/tree-sitter-queries/python/unreachable-except.yml +60 -0
- package/rules/tree-sitter-queries/python/wildcard-import.yml +46 -0
- package/rules/tree-sitter-queries/tsx/dangerously-set-inner-html.yml +63 -0
- package/rules/tree-sitter-queries/typescript/await-in-loop.yml +56 -0
- package/rules/tree-sitter-queries/typescript/console-statement.yml +47 -0
- package/rules/tree-sitter-queries/typescript/debugger.yml +47 -0
- package/rules/tree-sitter-queries/typescript/deep-nesting.yml +117 -0
- package/rules/tree-sitter-queries/typescript/deep-promise-chain.yml +73 -0
- package/rules/tree-sitter-queries/typescript/empty-catch.yml +64 -0
- package/rules/tree-sitter-queries/typescript/eval.yml +48 -0
- package/rules/tree-sitter-queries/typescript/hardcoded-secrets.yml +78 -0
- package/rules/tree-sitter-queries/typescript/long-parameter-list.yml +62 -0
- package/rules/tree-sitter-queries/typescript/mixed-async-styles.yml +49 -0
- package/rules/tree-sitter-queries/typescript/nested-ternary.yml +45 -0
- package/rules/ts-slop-rules/.sgconfig.yml +4 -0
- package/rules/ts-slop-rules/rules/in-correct-optional-input-type.yml +10 -0
- package/rules/ts-slop-rules/rules/jwt-no-verify.yml +13 -0
- package/rules/ts-slop-rules/rules/no-architecture-violation.yml +10 -0
- package/rules/ts-slop-rules/rules/no-case-declarations.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dangerously-set-inner-html.yml +10 -0
- package/rules/ts-slop-rules/rules/no-debugger.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-args.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-class-members.yml +10 -0
- package/rules/ts-slop-rules/rules/no-dupe-keys.yml +10 -0
- package/rules/ts-slop-rules/rules/no-eval.yml +13 -0
- package/rules/ts-slop-rules/rules/no-hardcoded-secrets.yml +12 -0
- package/rules/ts-slop-rules/rules/no-implied-eval.yml +12 -0
- package/rules/ts-slop-rules/rules/no-inner-html.yml +13 -0
- package/rules/ts-slop-rules/rules/no-javascript-url.yml +10 -0
- package/rules/ts-slop-rules/rules/no-mutable-default.yml +10 -0
- package/rules/ts-slop-rules/rules/no-nested-links.yml +12 -0
- package/rules/ts-slop-rules/rules/no-new-symbol.yml +10 -0
- package/rules/ts-slop-rules/rules/no-new-wrappers.yml +13 -0
- package/rules/ts-slop-rules/rules/no-open-redirect.yml +16 -0
- package/rules/ts-slop-rules/rules/slop-rules.yml +455 -0
- package/rules/ts-slop-rules/rules/weak-rsa-key.yml +12 -0
- package/skills/ast-grep/SKILL.md +182 -0
- package/clients/dispatch/runners/secrets.js +0 -109
- package/commands/fix.js +0 -244
- package/commands/fix.ts +0 -373
- package/rules/ast-grep-rules/rules/no-lonely-if.yml +0 -13
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Autofix Integration Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for auto-format and auto-fix behavior.
|
|
5
|
+
* Validates that autofix runs by default and can be disabled.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, expect, it, vi } from "vitest";
|
|
8
|
+
// --- Mock Runners ---
|
|
9
|
+
const createAutofixRunner = (id) => ({
|
|
10
|
+
id,
|
|
11
|
+
appliesTo: ["jsts"],
|
|
12
|
+
priority: 10,
|
|
13
|
+
enabledByDefault: true,
|
|
14
|
+
when: async (ctx) => ctx.autofix,
|
|
15
|
+
async run(ctx) {
|
|
16
|
+
return {
|
|
17
|
+
status: "succeeded",
|
|
18
|
+
diagnostics: [
|
|
19
|
+
{
|
|
20
|
+
id: `${id}:fixed`,
|
|
21
|
+
message: `Fixed by ${id}`,
|
|
22
|
+
filePath: ctx.filePath,
|
|
23
|
+
line: 1,
|
|
24
|
+
column: 1,
|
|
25
|
+
severity: "info",
|
|
26
|
+
semantic: "fixed",
|
|
27
|
+
tool: id,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
semantic: "fixed",
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
const createNonAutofixRunner = (id) => ({
|
|
35
|
+
id,
|
|
36
|
+
appliesTo: ["jsts"],
|
|
37
|
+
priority: 20,
|
|
38
|
+
enabledByDefault: true,
|
|
39
|
+
async run(ctx) {
|
|
40
|
+
return {
|
|
41
|
+
status: "succeeded",
|
|
42
|
+
diagnostics: [
|
|
43
|
+
{
|
|
44
|
+
id: `${id}:info`,
|
|
45
|
+
message: `Info from ${id}`,
|
|
46
|
+
filePath: ctx.filePath,
|
|
47
|
+
line: 1,
|
|
48
|
+
column: 1,
|
|
49
|
+
severity: "info",
|
|
50
|
+
semantic: "silent",
|
|
51
|
+
tool: id,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
semantic: "none",
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
const createMockContext = (filePath = "test.ts", autofix = true) => ({
|
|
59
|
+
filePath,
|
|
60
|
+
cwd: "/test",
|
|
61
|
+
kind: "jsts",
|
|
62
|
+
pi: {
|
|
63
|
+
getFlag: vi.fn((flag) => {
|
|
64
|
+
if (flag === "no-autofix")
|
|
65
|
+
return !autofix;
|
|
66
|
+
return autofix;
|
|
67
|
+
}),
|
|
68
|
+
},
|
|
69
|
+
autofix,
|
|
70
|
+
deltaMode: false,
|
|
71
|
+
baselines: new Map(),
|
|
72
|
+
hasTool: vi.fn(() => Promise.resolve(false)),
|
|
73
|
+
log: vi.fn(),
|
|
74
|
+
});
|
|
75
|
+
const _createMockGroup = (runners) => ({
|
|
76
|
+
runnerIds: runners.map((r) => r.id),
|
|
77
|
+
mode: "all",
|
|
78
|
+
});
|
|
79
|
+
// --- Tests ---
|
|
80
|
+
describe("Autofix Integration", () => {
|
|
81
|
+
describe("Autofix by Default", () => {
|
|
82
|
+
it("should run autofix runners when enabled", async () => {
|
|
83
|
+
const autofixRunner = createAutofixRunner("biome-fix");
|
|
84
|
+
const ctx = createMockContext("test.ts", true);
|
|
85
|
+
// The runner should apply (autofix is true)
|
|
86
|
+
const shouldRun = await autofixRunner.when?.(ctx);
|
|
87
|
+
expect(shouldRun).toBe(true);
|
|
88
|
+
});
|
|
89
|
+
it("should skip autofix runners when disabled", async () => {
|
|
90
|
+
const autofixRunner = createAutofixRunner("biome-fix");
|
|
91
|
+
const ctx = createMockContext("test.ts", false);
|
|
92
|
+
// The runner should not apply (autofix is false)
|
|
93
|
+
const shouldRun = await autofixRunner.when?.(ctx);
|
|
94
|
+
expect(shouldRun).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe("--no-autofix Flag", () => {
|
|
98
|
+
it("should disable autofix with --no-autofix flag", () => {
|
|
99
|
+
const mockPi = {
|
|
100
|
+
getFlag: vi.fn((flag) => flag === "no-autofix"),
|
|
101
|
+
};
|
|
102
|
+
// Simulate flag check in dispatch context
|
|
103
|
+
const autofixEnabled = !mockPi.getFlag("no-autofix");
|
|
104
|
+
expect(autofixEnabled).toBe(false);
|
|
105
|
+
});
|
|
106
|
+
it("should enable autofix without --no-autofix flag", () => {
|
|
107
|
+
const mockPi = {
|
|
108
|
+
getFlag: vi.fn((_flag) => false),
|
|
109
|
+
};
|
|
110
|
+
const autofixEnabled = !mockPi.getFlag("no-autofix");
|
|
111
|
+
expect(autofixEnabled).toBe(true);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe("File Modification Warnings", () => {
|
|
115
|
+
it("should track when format changes files", async () => {
|
|
116
|
+
// Simulate format result
|
|
117
|
+
const formatResult = {
|
|
118
|
+
formatChanged: true,
|
|
119
|
+
fixedCount: 0,
|
|
120
|
+
};
|
|
121
|
+
// Should show warning
|
|
122
|
+
const shouldWarn = formatResult.formatChanged || formatResult.fixedCount > 0;
|
|
123
|
+
expect(shouldWarn).toBe(true);
|
|
124
|
+
});
|
|
125
|
+
it("should track when autofix changes files", async () => {
|
|
126
|
+
// Simulate autofix result
|
|
127
|
+
const fixResult = {
|
|
128
|
+
formatChanged: false,
|
|
129
|
+
fixedCount: 3,
|
|
130
|
+
};
|
|
131
|
+
// Should show warning
|
|
132
|
+
const shouldWarn = fixResult.formatChanged || fixResult.fixedCount > 0;
|
|
133
|
+
expect(shouldWarn).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
it("should show warning message format", () => {
|
|
136
|
+
const warningMessage = "⚠️ **File modified by auto-format/fix. Re-read before next edit.**";
|
|
137
|
+
expect(warningMessage).toContain("File modified");
|
|
138
|
+
expect(warningMessage).toContain("auto-format");
|
|
139
|
+
expect(warningMessage).toContain("fix");
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe("Runner Categories", () => {
|
|
143
|
+
it("should have autofix runners with when conditions", () => {
|
|
144
|
+
const autofixRunner = createAutofixRunner("ruff-fix");
|
|
145
|
+
expect(autofixRunner.when).toBeDefined();
|
|
146
|
+
expect(typeof autofixRunner.when).toBe("function");
|
|
147
|
+
});
|
|
148
|
+
it("should have non-autofix runners without when conditions", () => {
|
|
149
|
+
const regularRunner = createNonAutofixRunner("ts-lsp");
|
|
150
|
+
// Regular runners run regardless of autofix setting
|
|
151
|
+
expect(regularRunner.when).toBeUndefined();
|
|
152
|
+
});
|
|
153
|
+
it("should categorize fixed diagnostics correctly", async () => {
|
|
154
|
+
const autofixRunner = createAutofixRunner("biome-fix");
|
|
155
|
+
const ctx = createMockContext("test.ts", true);
|
|
156
|
+
const result = await autofixRunner.run(ctx);
|
|
157
|
+
// Should have semantic: "fixed"
|
|
158
|
+
expect(result.semantic).toBe("fixed");
|
|
159
|
+
// Diagnostics should also be fixed
|
|
160
|
+
for (const diag of result.diagnostics || []) {
|
|
161
|
+
expect(diag.semantic).toBe("fixed");
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
describe("Format vs Autofix Coordination", () => {
|
|
166
|
+
it("should run format before lint", async () => {
|
|
167
|
+
const order = [];
|
|
168
|
+
const formatRunner = {
|
|
169
|
+
id: "format",
|
|
170
|
+
appliesTo: ["jsts"],
|
|
171
|
+
priority: 5, // Lower = runs first
|
|
172
|
+
enabledByDefault: true,
|
|
173
|
+
async run() {
|
|
174
|
+
order.push("format");
|
|
175
|
+
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
const lintRunner = {
|
|
179
|
+
id: "lint",
|
|
180
|
+
appliesTo: ["jsts"],
|
|
181
|
+
priority: 10, // Higher = runs after
|
|
182
|
+
enabledByDefault: true,
|
|
183
|
+
async run() {
|
|
184
|
+
order.push("lint");
|
|
185
|
+
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
// Verify priority ordering
|
|
189
|
+
expect(formatRunner.priority).toBeLessThan(lintRunner.priority);
|
|
190
|
+
});
|
|
191
|
+
it("should handle format and lint race conditions", async () => {
|
|
192
|
+
// Simulate format changing file while lint is running
|
|
193
|
+
const _ctx = createMockContext("test.ts", true);
|
|
194
|
+
// Format result
|
|
195
|
+
const formatChanged = true;
|
|
196
|
+
// Lint should still work
|
|
197
|
+
const lintResult = {
|
|
198
|
+
status: "succeeded",
|
|
199
|
+
diagnostics: [],
|
|
200
|
+
semantic: "none",
|
|
201
|
+
};
|
|
202
|
+
// Both should complete without error
|
|
203
|
+
expect(formatChanged).toBe(true);
|
|
204
|
+
expect(lintResult.status).toBe("succeeded");
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
describe("Real-world Scenarios", () => {
|
|
208
|
+
it("should handle ruff autofix flow", async () => {
|
|
209
|
+
const ruffRunner = createAutofixRunner("ruff");
|
|
210
|
+
const ctxWithAutofix = createMockContext("test.py", true);
|
|
211
|
+
const ctxNoAutofix = createMockContext("test.py", false);
|
|
212
|
+
// With autofix
|
|
213
|
+
const shouldRunWith = await ruffRunner.when?.(ctxWithAutofix);
|
|
214
|
+
expect(shouldRunWith).toBe(true);
|
|
215
|
+
// Without autofix
|
|
216
|
+
const shouldRunWithout = await ruffRunner.when?.(ctxNoAutofix);
|
|
217
|
+
expect(shouldRunWithout).toBe(false);
|
|
218
|
+
});
|
|
219
|
+
it("should handle biome autofix flow", async () => {
|
|
220
|
+
const biomeRunner = createAutofixRunner("biome-fix");
|
|
221
|
+
const ctxWithAutofix = createMockContext("test.ts", true);
|
|
222
|
+
const ctxNoAutofix = createMockContext("test.ts", false);
|
|
223
|
+
// With autofix
|
|
224
|
+
const shouldRunWith = await biomeRunner.when?.(ctxWithAutofix);
|
|
225
|
+
expect(shouldRunWith).toBe(true);
|
|
226
|
+
// Without autofix
|
|
227
|
+
const shouldRunWithout = await biomeRunner.when?.(ctxNoAutofix);
|
|
228
|
+
expect(shouldRunWithout).toBe(false);
|
|
229
|
+
});
|
|
230
|
+
it("should show file modification warning only when changes made", async () => {
|
|
231
|
+
// No changes
|
|
232
|
+
const noChanges = { formatChanged: false, fixedCount: 0 };
|
|
233
|
+
expect(noChanges.formatChanged || noChanges.fixedCount > 0).toBe(false);
|
|
234
|
+
// Format only
|
|
235
|
+
const formatOnly = { formatChanged: true, fixedCount: 0 };
|
|
236
|
+
expect(formatOnly.formatChanged || formatOnly.fixedCount > 0).toBe(true);
|
|
237
|
+
// Fix only
|
|
238
|
+
const fixOnly = { formatChanged: false, fixedCount: 5 };
|
|
239
|
+
expect(fixOnly.formatChanged || fixOnly.fixedCount > 0).toBe(true);
|
|
240
|
+
// Both
|
|
241
|
+
const both = { formatChanged: true, fixedCount: 3 };
|
|
242
|
+
expect(both.formatChanged || both.fixedCount > 0).toBe(true);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
});
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Autofix Integration Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for auto-format and auto-fix behavior.
|
|
5
|
+
* Validates that autofix runs by default and can be disabled.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, expect, it, vi } from "vitest";
|
|
9
|
+
import type {
|
|
10
|
+
DispatchContext,
|
|
11
|
+
RunnerDefinition,
|
|
12
|
+
RunnerGroup,
|
|
13
|
+
} from "../types.js";
|
|
14
|
+
|
|
15
|
+
// --- Mock Runners ---
|
|
16
|
+
|
|
17
|
+
const createAutofixRunner = (id: string): RunnerDefinition => ({
|
|
18
|
+
id,
|
|
19
|
+
appliesTo: ["jsts"],
|
|
20
|
+
priority: 10,
|
|
21
|
+
enabledByDefault: true,
|
|
22
|
+
when: async (ctx) => ctx.autofix,
|
|
23
|
+
async run(ctx: DispatchContext) {
|
|
24
|
+
return {
|
|
25
|
+
status: "succeeded",
|
|
26
|
+
diagnostics: [
|
|
27
|
+
{
|
|
28
|
+
id: `${id}:fixed`,
|
|
29
|
+
message: `Fixed by ${id}`,
|
|
30
|
+
filePath: ctx.filePath,
|
|
31
|
+
line: 1,
|
|
32
|
+
column: 1,
|
|
33
|
+
severity: "info",
|
|
34
|
+
semantic: "fixed",
|
|
35
|
+
tool: id,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
semantic: "fixed",
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const createNonAutofixRunner = (id: string): RunnerDefinition => ({
|
|
44
|
+
id,
|
|
45
|
+
appliesTo: ["jsts"],
|
|
46
|
+
priority: 20,
|
|
47
|
+
enabledByDefault: true,
|
|
48
|
+
async run(ctx: DispatchContext) {
|
|
49
|
+
return {
|
|
50
|
+
status: "succeeded",
|
|
51
|
+
diagnostics: [
|
|
52
|
+
{
|
|
53
|
+
id: `${id}:info`,
|
|
54
|
+
message: `Info from ${id}`,
|
|
55
|
+
filePath: ctx.filePath,
|
|
56
|
+
line: 1,
|
|
57
|
+
column: 1,
|
|
58
|
+
severity: "info",
|
|
59
|
+
semantic: "silent",
|
|
60
|
+
tool: id,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
semantic: "none",
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const createMockContext = (
|
|
69
|
+
filePath: string = "test.ts",
|
|
70
|
+
autofix: boolean = true,
|
|
71
|
+
): DispatchContext => ({
|
|
72
|
+
filePath,
|
|
73
|
+
cwd: "/test",
|
|
74
|
+
kind: "jsts",
|
|
75
|
+
pi: {
|
|
76
|
+
getFlag: vi.fn((flag: string) => {
|
|
77
|
+
if (flag === "no-autofix") return !autofix;
|
|
78
|
+
return autofix;
|
|
79
|
+
}),
|
|
80
|
+
},
|
|
81
|
+
autofix,
|
|
82
|
+
deltaMode: false,
|
|
83
|
+
baselines: new Map(),
|
|
84
|
+
hasTool: vi.fn(() => Promise.resolve(false)),
|
|
85
|
+
log: vi.fn(),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const _createMockGroup = (runners: RunnerDefinition[]): RunnerGroup => ({
|
|
89
|
+
runnerIds: runners.map((r) => r.id),
|
|
90
|
+
mode: "all",
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// --- Tests ---
|
|
94
|
+
|
|
95
|
+
describe("Autofix Integration", () => {
|
|
96
|
+
describe("Autofix by Default", () => {
|
|
97
|
+
it("should run autofix runners when enabled", async () => {
|
|
98
|
+
const autofixRunner = createAutofixRunner("biome-fix");
|
|
99
|
+
const ctx = createMockContext("test.ts", true);
|
|
100
|
+
|
|
101
|
+
// The runner should apply (autofix is true)
|
|
102
|
+
const shouldRun = await autofixRunner.when?.(ctx);
|
|
103
|
+
expect(shouldRun).toBe(true);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("should skip autofix runners when disabled", async () => {
|
|
107
|
+
const autofixRunner = createAutofixRunner("biome-fix");
|
|
108
|
+
const ctx = createMockContext("test.ts", false);
|
|
109
|
+
|
|
110
|
+
// The runner should not apply (autofix is false)
|
|
111
|
+
const shouldRun = await autofixRunner.when?.(ctx);
|
|
112
|
+
expect(shouldRun).toBe(false);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe("--no-autofix Flag", () => {
|
|
117
|
+
it("should disable autofix with --no-autofix flag", () => {
|
|
118
|
+
const mockPi = {
|
|
119
|
+
getFlag: vi.fn((flag: string) => flag === "no-autofix"),
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Simulate flag check in dispatch context
|
|
123
|
+
const autofixEnabled = !mockPi.getFlag("no-autofix");
|
|
124
|
+
expect(autofixEnabled).toBe(false);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("should enable autofix without --no-autofix flag", () => {
|
|
128
|
+
const mockPi = {
|
|
129
|
+
getFlag: vi.fn((_flag: string) => false),
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const autofixEnabled = !mockPi.getFlag("no-autofix");
|
|
133
|
+
expect(autofixEnabled).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe("File Modification Warnings", () => {
|
|
138
|
+
it("should track when format changes files", async () => {
|
|
139
|
+
// Simulate format result
|
|
140
|
+
const formatResult = {
|
|
141
|
+
formatChanged: true,
|
|
142
|
+
fixedCount: 0,
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// Should show warning
|
|
146
|
+
const shouldWarn =
|
|
147
|
+
formatResult.formatChanged || formatResult.fixedCount > 0;
|
|
148
|
+
expect(shouldWarn).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("should track when autofix changes files", async () => {
|
|
152
|
+
// Simulate autofix result
|
|
153
|
+
const fixResult = {
|
|
154
|
+
formatChanged: false,
|
|
155
|
+
fixedCount: 3,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// Should show warning
|
|
159
|
+
const shouldWarn = fixResult.formatChanged || fixResult.fixedCount > 0;
|
|
160
|
+
expect(shouldWarn).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it("should show warning message format", () => {
|
|
164
|
+
const warningMessage =
|
|
165
|
+
"⚠️ **File modified by auto-format/fix. Re-read before next edit.**";
|
|
166
|
+
expect(warningMessage).toContain("File modified");
|
|
167
|
+
expect(warningMessage).toContain("auto-format");
|
|
168
|
+
expect(warningMessage).toContain("fix");
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
describe("Runner Categories", () => {
|
|
173
|
+
it("should have autofix runners with when conditions", () => {
|
|
174
|
+
const autofixRunner = createAutofixRunner("ruff-fix");
|
|
175
|
+
|
|
176
|
+
expect(autofixRunner.when).toBeDefined();
|
|
177
|
+
expect(typeof autofixRunner.when).toBe("function");
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("should have non-autofix runners without when conditions", () => {
|
|
181
|
+
const regularRunner = createNonAutofixRunner("ts-lsp");
|
|
182
|
+
|
|
183
|
+
// Regular runners run regardless of autofix setting
|
|
184
|
+
expect(regularRunner.when).toBeUndefined();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("should categorize fixed diagnostics correctly", async () => {
|
|
188
|
+
const autofixRunner = createAutofixRunner("biome-fix");
|
|
189
|
+
const ctx = createMockContext("test.ts", true);
|
|
190
|
+
|
|
191
|
+
const result = await autofixRunner.run(ctx);
|
|
192
|
+
|
|
193
|
+
// Should have semantic: "fixed"
|
|
194
|
+
expect(result.semantic).toBe("fixed");
|
|
195
|
+
|
|
196
|
+
// Diagnostics should also be fixed
|
|
197
|
+
for (const diag of result.diagnostics || []) {
|
|
198
|
+
expect(diag.semantic).toBe("fixed");
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe("Format vs Autofix Coordination", () => {
|
|
204
|
+
it("should run format before lint", async () => {
|
|
205
|
+
const order: string[] = [];
|
|
206
|
+
|
|
207
|
+
const formatRunner: RunnerDefinition = {
|
|
208
|
+
id: "format",
|
|
209
|
+
appliesTo: ["jsts"],
|
|
210
|
+
priority: 5, // Lower = runs first
|
|
211
|
+
enabledByDefault: true,
|
|
212
|
+
async run() {
|
|
213
|
+
order.push("format");
|
|
214
|
+
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const lintRunner: RunnerDefinition = {
|
|
219
|
+
id: "lint",
|
|
220
|
+
appliesTo: ["jsts"],
|
|
221
|
+
priority: 10, // Higher = runs after
|
|
222
|
+
enabledByDefault: true,
|
|
223
|
+
async run() {
|
|
224
|
+
order.push("lint");
|
|
225
|
+
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// Verify priority ordering
|
|
230
|
+
expect(formatRunner.priority).toBeLessThan(lintRunner.priority!);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it("should handle format and lint race conditions", async () => {
|
|
234
|
+
// Simulate format changing file while lint is running
|
|
235
|
+
const _ctx = createMockContext("test.ts", true);
|
|
236
|
+
|
|
237
|
+
// Format result
|
|
238
|
+
const formatChanged = true;
|
|
239
|
+
|
|
240
|
+
// Lint should still work
|
|
241
|
+
const lintResult = {
|
|
242
|
+
status: "succeeded",
|
|
243
|
+
diagnostics: [],
|
|
244
|
+
semantic: "none",
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// Both should complete without error
|
|
248
|
+
expect(formatChanged).toBe(true);
|
|
249
|
+
expect(lintResult.status).toBe("succeeded");
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
describe("Real-world Scenarios", () => {
|
|
254
|
+
it("should handle ruff autofix flow", async () => {
|
|
255
|
+
const ruffRunner = createAutofixRunner("ruff");
|
|
256
|
+
const ctxWithAutofix = createMockContext("test.py", true);
|
|
257
|
+
const ctxNoAutofix = createMockContext("test.py", false);
|
|
258
|
+
|
|
259
|
+
// With autofix
|
|
260
|
+
const shouldRunWith = await ruffRunner.when?.(ctxWithAutofix);
|
|
261
|
+
expect(shouldRunWith).toBe(true);
|
|
262
|
+
|
|
263
|
+
// Without autofix
|
|
264
|
+
const shouldRunWithout = await ruffRunner.when?.(ctxNoAutofix);
|
|
265
|
+
expect(shouldRunWithout).toBe(false);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it("should handle biome autofix flow", async () => {
|
|
269
|
+
const biomeRunner = createAutofixRunner("biome-fix");
|
|
270
|
+
const ctxWithAutofix = createMockContext("test.ts", true);
|
|
271
|
+
const ctxNoAutofix = createMockContext("test.ts", false);
|
|
272
|
+
|
|
273
|
+
// With autofix
|
|
274
|
+
const shouldRunWith = await biomeRunner.when?.(ctxWithAutofix);
|
|
275
|
+
expect(shouldRunWith).toBe(true);
|
|
276
|
+
|
|
277
|
+
// Without autofix
|
|
278
|
+
const shouldRunWithout = await biomeRunner.when?.(ctxNoAutofix);
|
|
279
|
+
expect(shouldRunWithout).toBe(false);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("should show file modification warning only when changes made", async () => {
|
|
283
|
+
// No changes
|
|
284
|
+
const noChanges = { formatChanged: false, fixedCount: 0 };
|
|
285
|
+
expect(noChanges.formatChanged || noChanges.fixedCount > 0).toBe(false);
|
|
286
|
+
|
|
287
|
+
// Format only
|
|
288
|
+
const formatOnly = { formatChanged: true, fixedCount: 0 };
|
|
289
|
+
expect(formatOnly.formatChanged || formatOnly.fixedCount > 0).toBe(true);
|
|
290
|
+
|
|
291
|
+
// Fix only
|
|
292
|
+
const fixOnly = { formatChanged: false, fixedCount: 5 };
|
|
293
|
+
expect(fixOnly.formatChanged || fixOnly.fixedCount > 0).toBe(true);
|
|
294
|
+
|
|
295
|
+
// Both
|
|
296
|
+
const both = { formatChanged: true, fixedCount: 3 };
|
|
297
|
+
expect(both.formatChanged || both.fixedCount > 0).toBe(true);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
});
|