diff --git a/apps/oxlint/src-js/plugins/load.ts b/apps/oxlint/src-js/plugins/load.ts index 0d155871979fd..92a6c4e098bcb 100644 --- a/apps/oxlint/src-js/plugins/load.ts +++ b/apps/oxlint/src-js/plugins/load.ts @@ -181,10 +181,17 @@ export function registerPlugin( const { fixable } = ruleMeta; if (fixable != null) { - if (fixable !== "code" && fixable !== "whitespace") { + // `true` and `false` aren't valid values for `meta.fixable`, but we accept them for + // backward compatibility with some ESLint plugins + if ( + fixable !== "code" && + fixable !== "whitespace" && + fixable !== true && + fixable !== false + ) { throw new TypeError("Invalid `rule.meta.fixable`"); } - isFixable = true; + isFixable = (fixable as "code" | "whitespace" | true | false) !== false; } // If `schema` provided, compile schema to validator for applying schema defaults to options diff --git a/apps/oxlint/test/fixtures/fixable_boolean/.oxlintrc.json b/apps/oxlint/test/fixtures/fixable_boolean/.oxlintrc.json new file mode 100644 index 0000000000000..ed9f83f162496 --- /dev/null +++ b/apps/oxlint/test/fixtures/fixable_boolean/.oxlintrc.json @@ -0,0 +1,10 @@ +{ + "jsPlugins": ["./plugin.ts"], + "categories": { + "correctness": "off" + }, + "rules": { + "fixable-boolean-plugin/no-debugger-true": "error", + "fixable-boolean-plugin/no-console-false": "error" + } +} diff --git a/apps/oxlint/test/fixtures/fixable_boolean/files/index.js b/apps/oxlint/test/fixtures/fixable_boolean/files/index.js new file mode 100644 index 0000000000000..32c6e6a215c79 --- /dev/null +++ b/apps/oxlint/test/fixtures/fixable_boolean/files/index.js @@ -0,0 +1,2 @@ +debugger; +console.log("test"); diff --git a/apps/oxlint/test/fixtures/fixable_boolean/fix.snap.md b/apps/oxlint/test/fixtures/fixable_boolean/fix.snap.md new file mode 100644 index 0000000000000..e0cf92213a2fc --- /dev/null +++ b/apps/oxlint/test/fixtures/fixable_boolean/fix.snap.md @@ -0,0 +1,28 @@ +# Exit code +1 + +# stdout +``` + x fixable-boolean-plugin(no-console-false): Console with fixable: false + ,-[files/index.js:2:1] + 1 | debugger; + 2 | console.log("test"); + : ^^^^^^^^^^^^^^^^^^^ + `---- + +Found 0 warnings and 1 error. +Finished in Xms on 1 file with 2 rules using X threads. +``` + +# stderr +``` +WARNING: JS plugins are experimental and not subject to semver. +Breaking changes are possible while JS plugins support is under development. +``` + +# File altered: files/index.js +``` + +console.log("test"); + +``` diff --git a/apps/oxlint/test/fixtures/fixable_boolean/options.json b/apps/oxlint/test/fixtures/fixable_boolean/options.json new file mode 100644 index 0000000000000..602385b3bf26d --- /dev/null +++ b/apps/oxlint/test/fixtures/fixable_boolean/options.json @@ -0,0 +1,3 @@ +{ + "fix": true +} diff --git a/apps/oxlint/test/fixtures/fixable_boolean/output.snap.md b/apps/oxlint/test/fixtures/fixable_boolean/output.snap.md new file mode 100644 index 0000000000000..4900842e5c656 --- /dev/null +++ b/apps/oxlint/test/fixtures/fixable_boolean/output.snap.md @@ -0,0 +1,28 @@ +# Exit code +1 + +# stdout +``` + x fixable-boolean-plugin(no-debugger-true): Debugger with fixable: true + ,-[files/index.js:1:1] + 1 | debugger; + : ^^^^^^^^^ + 2 | console.log("test"); + `---- + + x fixable-boolean-plugin(no-console-false): Console with fixable: false + ,-[files/index.js:2:1] + 1 | debugger; + 2 | console.log("test"); + : ^^^^^^^^^^^^^^^^^^^ + `---- + +Found 0 warnings and 2 errors. +Finished in Xms on 1 file with 2 rules using X threads. +``` + +# stderr +``` +WARNING: JS plugins are experimental and not subject to semver. +Breaking changes are possible while JS plugins support is under development. +``` diff --git a/apps/oxlint/test/fixtures/fixable_boolean/plugin.ts b/apps/oxlint/test/fixtures/fixable_boolean/plugin.ts new file mode 100644 index 0000000000000..b7ed4bb48e956 --- /dev/null +++ b/apps/oxlint/test/fixtures/fixable_boolean/plugin.ts @@ -0,0 +1,54 @@ +import type { Plugin } from "#oxlint/plugin"; + +// Test backward compatibility for `meta.fixable: true` and `meta.fixable: false` +// which some ESLint plugins use instead of "code" or "whitespace" +const plugin: Plugin = { + meta: { + name: "fixable-boolean-plugin", + }, + rules: { + // Rule with fixable: true (backward compatibility) + "no-debugger-true": { + meta: { + fixable: true as any, + }, + create(context) { + return { + DebuggerStatement(node) { + context.report({ + message: "Debugger with fixable: true", + node, + fix(fixer) { + return fixer.remove(node); + }, + }); + }, + }; + }, + }, + // Rule with fixable: false (backward compatibility) + "no-console-false": { + meta: { + fixable: false as any, + }, + create(context) { + return { + CallExpression(node) { + if ( + node.callee.type === "MemberExpression" && + node.callee.object.type === "Identifier" && + node.callee.object.name === "console" + ) { + context.report({ + message: "Console with fixable: false", + node, + }); + } + }, + }; + }, + }, + }, +}; + +export default plugin;