From 3f43d4cb53d402866761aca6197045c77a8ac6d2 Mon Sep 17 00:00:00 2001 From: camc314 <18101008+camc314@users.noreply.github.com> Date: Sat, 31 Jan 2026 16:27:20 +0000 Subject: [PATCH] fix(linter): accept bools as valid values for `fixable` (#18772) fixes https://github.com/oxc-project/oxc/issues/17967 fixes https://github.com/oxc-project/oxc/issues/18700 closes https://github.com/oxc-project/oxc/pull/18011 This PR allows boolean values as valid options for meta.fixable. While this technically doesn't align exactly with eslint, it reduces some friction about getting users to migrate from exlint to oxlint, by increasing the number of plugins that are compatible. --- apps/oxlint/src-js/plugins/load.ts | 11 +++- .../fixtures/fixable_boolean/.oxlintrc.json | 10 ++++ .../fixtures/fixable_boolean/files/index.js | 2 + .../test/fixtures/fixable_boolean/fix.snap.md | 28 ++++++++++ .../fixtures/fixable_boolean/options.json | 3 ++ .../fixtures/fixable_boolean/output.snap.md | 28 ++++++++++ .../test/fixtures/fixable_boolean/plugin.ts | 54 +++++++++++++++++++ 7 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 apps/oxlint/test/fixtures/fixable_boolean/.oxlintrc.json create mode 100644 apps/oxlint/test/fixtures/fixable_boolean/files/index.js create mode 100644 apps/oxlint/test/fixtures/fixable_boolean/fix.snap.md create mode 100644 apps/oxlint/test/fixtures/fixable_boolean/options.json create mode 100644 apps/oxlint/test/fixtures/fixable_boolean/output.snap.md create mode 100644 apps/oxlint/test/fixtures/fixable_boolean/plugin.ts 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;