From 1648deca6976ed83d8b99760fa79cc288031df39 Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Thu, 30 Jan 2025 22:04:34 +0100 Subject: [PATCH 1/3] feat: change behavior of inactive flags Fixes #19337 --- docs/src/_data/flags.js | 17 ++++++++- docs/src/pages/flags.md | 16 ++++++-- lib/eslint/eslint.js | 2 +- lib/linter/linter.js | 23 +++++++++++- lib/shared/flags.js | 15 ++++++-- tests/lib/cli.js | 49 +++++++++++++++++++++++-- tests/lib/eslint/eslint.js | 75 ++++++++++++++++++++++++++++++++------ tests/lib/linter/linter.js | 56 ++++++++++++++++++++++++++-- 8 files changed, 222 insertions(+), 31 deletions(-) diff --git a/docs/src/_data/flags.js b/docs/src/_data/flags.js index 61966c9d6672..63761d870490 100644 --- a/docs/src/_data/flags.js +++ b/docs/src/_data/flags.js @@ -5,6 +5,19 @@ "use strict"; +//----------------------------------------------------------------------------- +// Helpers +//----------------------------------------------------------------------------- + +/** + * Determines whether the flag is used for test purposes only. + * @param {string} flag The flag to check. + * @returns {boolean} `true` if the flag is used for test purposes only. + */ +function isTestOnlyFlag(flag) { + return flag.startsWith("test_only"); +} + //----------------------------------------------------------------------------- // Exports //----------------------------------------------------------------------------- @@ -14,7 +27,7 @@ module.exports = function() { const { activeFlags, inactiveFlags } = require("../../../lib/shared/flags"); return { - active: Object.fromEntries([...activeFlags]), - inactive: Object.fromEntries([...inactiveFlags]) + active: Object.fromEntries([...activeFlags].filter(([name]) => !isTestOnlyFlag(name))), + inactive: Object.fromEntries([...inactiveFlags].filter(([name]) => !isTestOnlyFlag(name))) }; }; diff --git a/docs/src/pages/flags.md b/docs/src/pages/flags.md index 74f7b00ebdd7..8f40add1e907 100644 --- a/docs/src/pages/flags.md +++ b/docs/src/pages/flags.md @@ -20,9 +20,17 @@ ESLint ships experimental and future breaking changes behind feature flags to le The prefix of a flag indicates its status: * `unstable_` indicates that the feature is experimental and the implementation may change before the feature is stabilized. This is a "use at your own risk" feature. -* `v##_` indicates that the feature is stabilized and will be available in the next major release. For example, `v10_some_feature` indicates that this is a breaking change that will be formally released in ESLint v10.0.0. These flags are removed each major release. +* `v##_` indicates that the feature is stabilized and will be available in the next major release. For example, `v10_some_feature` indicates that this is a breaking change that will be formally released in ESLint v10.0.0. These flags are removed each major release, and further use of them throws an error. -A feature may move from unstable to stable without a major release if it is a non-breaking change. +A feature may move from unstable to being enabled by default without a major release if it is a non-breaking change. + +The following policies apply to `unstable_` flags. + +* When the feature is stabilized + * If enabling the feature by default would be a breaking change, a new `v##_` flag is added as active, and the `unstable_` flag becomes inactive. Further use of the `unstable_` flag automatically enables the `v##_` flag but emits a warning. + * Otherwise, the feature is enabled by default, and the `unstable_` flag becomes inactive. Further use of the `unstable_` flag emits a warning. +* If the feature is abandoned, the `unstable_` flag becomes inactive. Further use of it throws an error. +* All inactive `unstable_` flags are removed each major release, and further use of them throws an error. ## Active Flags @@ -54,8 +62,8 @@ The following flags were once used but are no longer active. -{%- for name, desc in flags.inactive -%} - {{name}}{{desc}} +{%- for name, data in flags.inactive -%} + {{name}}{{data.description}} {%- endfor -%} diff --git a/lib/eslint/eslint.js b/lib/eslint/eslint.js index 89583d53f59d..a74d0da7adc1 100644 --- a/lib/eslint/eslint.js +++ b/lib/eslint/eslint.js @@ -470,7 +470,7 @@ class ESLint { defaultConfigs }; - this.#configLoader = processedOptions.flags.includes("unstable_config_lookup_from_file") + this.#configLoader = linter.hasFlag("unstable_config_lookup_from_file") ? new ConfigLoader(configLoaderOptions) : new LegacyConfigLoader(configLoaderOptions); diff --git a/lib/linter/linter.js b/lib/linter/linter.js index 1baa0b8bf350..1582941657d8 100644 --- a/lib/linter/linter.js +++ b/lib/linter/linter.js @@ -1326,19 +1326,38 @@ class Linter { */ constructor({ cwd, configType = "flat", flags = [] } = {}) { + const processedFlags = []; + flags.forEach(flag => { if (inactiveFlags.has(flag)) { - throw new Error(`The flag '${flag}' is inactive: ${inactiveFlags.get(flag)}`); + const { description, replacedBy } = inactiveFlags.get(flag); + + if (typeof replacedBy === "undefined") { + throw new Error(`The flag '${flag}' is inactive: ${description}`); + } + + if (typeof replacedBy === "string") { + processedFlags.push(replacedBy); + } + + globalThis.process?.emitWarning?.( + `The flag '${flag}' is inactive: ${description}`, + `ESLintInactiveFlag_${flag}` + ); + + return; } if (!activeFlags.has(flag)) { throw new Error(`Unknown flag '${flag}'.`); } + + processedFlags.push(flag); }); internalSlotsMap.set(this, { cwd: normalizeCwd(cwd), - flags, + flags: processedFlags, lastConfigArray: null, lastSourceCode: null, lastSuppressedMessages: [], diff --git a/lib/shared/flags.js b/lib/shared/flags.js index ba2ea2504106..b2bb9c158d68 100644 --- a/lib/shared/flags.js +++ b/lib/shared/flags.js @@ -14,12 +14,19 @@ const activeFlags = new Map([ ]); /** - * The set of flags that used to be active but no longer have an effect. - * @type {Map} + * The set of flags that used to be active. + * + * `replacedBy` can be either: + * - An active flag (string) that enables the same feature. + * - `null` if the feature is now enabled by default. + * - Omitted if the feature has been abandoned. + * @type {Map} */ const inactiveFlags = new Map([ - ["test_only_old", "Used only for testing."], - ["unstable_ts_config", "This flag is no longer required to enable TypeScript configuration files."] + ["test_only_replaced", { description: "Used only for testing flags that have been replaced by other flags.", replacedBy: "test_only" }], + ["test_only_enabled_by_default", { description: "Used only for testing flags whose features have been enabled by default.", replacedBy: null }], + ["test_only_abandoned", { description: "Used only for testing flags whose features have been abandoned." }], + ["unstable_ts_config", { description: "This flag is no longer required to enable TypeScript configuration files.", replacedBy: null }] ]); module.exports = { diff --git a/tests/lib/cli.js b/tests/lib/cli.js index 34d303c8d86b..d9c9130c37a3 100644 --- a/tests/lib/cli.js +++ b/tests/lib/cli.js @@ -1907,14 +1907,21 @@ describe("cli", () => { describe("--flag option", () => { - it("should throw an error when an inactive flag is used", async () => { + let processStub; + + beforeEach(() => { + sinon.restore(); + processStub = sinon.stub(process, "emitWarning").withArgs(sinon.match.any, sinon.match(/^ESLintInactiveFlag_/u)).returns(); + }); + + it("should throw an error when an inactive flag whose feature has been abandoned is used", async () => { const configPath = getFixturePath("eslint.config.js"); const filePath = getFixturePath("passing.js"); - const input = `--flag test_only_old --config ${configPath} ${filePath}`; + const input = `--flag test_only_abandoned --config ${configPath} ${filePath}`; await stdAssert.rejects(async () => { await cli.execute(input, null, true); - }, /The flag 'test_only_old' is inactive: Used only for testing\./u); + }, /The flag 'test_only_abandoned' is inactive: Used only for testing flags whose features have been abandoned\./u); }); it("should error out when an unknown flag is used", async () => { @@ -1927,6 +1934,42 @@ describe("cli", () => { }, /Unknown flag 'test_only_oldx'\./u); }); + it("should emit a warning and not error out when an inactive flag that has been replaced by another flag is used", async () => { + const configPath = getFixturePath("eslint.config.js"); + const filePath = getFixturePath("passing.js"); + const input = `--flag test_only_replaced --config ${configPath} ${filePath}`; + const exitCode = await cli.execute(input, null, true); + + assert.strictEqual(processStub.callCount, 1, "calls `process.emitWarning()` for flags once"); + assert.deepStrictEqual( + processStub.getCall(0).args, + [ + "The flag 'test_only_replaced' is inactive: Used only for testing flags that have been replaced by other flags.", + "ESLintInactiveFlag_test_only_replaced" + ] + ); + sinon.assert.notCalled(log.error); + assert.strictEqual(exitCode, 0); + }); + + it("should emit a warning and not error out when an inactive flag whose feature is enabled by default is used", async () => { + const configPath = getFixturePath("eslint.config.js"); + const filePath = getFixturePath("passing.js"); + const input = `--flag test_only_enabled_by_default --config ${configPath} ${filePath}`; + const exitCode = await cli.execute(input, null, true); + + assert.strictEqual(processStub.callCount, 1, "calls `process.emitWarning()` for flags once"); + assert.deepStrictEqual( + processStub.getCall(0).args, + [ + "The flag 'test_only_enabled_by_default' is inactive: Used only for testing flags whose features have been enabled by default.", + "ESLintInactiveFlag_test_only_enabled_by_default" + ] + ); + sinon.assert.notCalled(log.error); + assert.strictEqual(exitCode, 0); + }); + it("should not error when a valid flag is used", async () => { const configPath = getFixturePath("eslint.config.js"); const filePath = getFixturePath("passing.js"); diff --git a/tests/lib/eslint/eslint.js b/tests/lib/eslint/eslint.js index 2bcccc7424f2..0d82e8f9144f 100644 --- a/tests/lib/eslint/eslint.js +++ b/tests/lib/eslint/eslint.js @@ -335,15 +335,6 @@ describe("ESLint", () => { processStub.restore(); }); - - it("should throw an error if the flag 'unstable_ts_config' is used", () => { - assert.throws( - () => new ESLint({ - flags: [...flags, "unstable_ts_config"] - }), - { message: "The flag 'unstable_ts_config' is inactive: This flag is no longer required to enable TypeScript configuration files." } - ); - }); }); describe("hasFlag", () => { @@ -351,17 +342,60 @@ describe("ESLint", () => { /** @type {InstanceType} */ let eslint; + let processStub; + + beforeEach(() => { + sinon.restore(); + processStub = sinon.stub(process, "emitWarning").withArgs(sinon.match.any, sinon.match(/^ESLintInactiveFlag_/u)).returns(); + }); + it("should return true if the flag is present and active", () => { eslint = new ESLint({ cwd: getFixturePath(), flags: ["test_only"] }); assert.strictEqual(eslint.hasFlag("test_only"), true); }); - it("should throw an error if the flag is inactive", () => { + it("should return true for the replacement flag if an inactive flag that has been replaced is used", () => { + eslint = new ESLint({ cwd: getFixturePath(), flags: ["test_only_replaced"] }); + + assert.strictEqual(eslint.hasFlag("test_only"), true); + assert.strictEqual(processStub.callCount, 1, "calls `process.emitWarning()` for flags once"); + assert.deepStrictEqual( + processStub.getCall(0).args, + [ + "The flag 'test_only_replaced' is inactive: Used only for testing flags that have been replaced by other flags.", + "ESLintInactiveFlag_test_only_replaced" + ] + ); + }); + + it("should return false if an inactive flag whose feature is enabled by default is used", () => { + eslint = new ESLint({ cwd: getFixturePath(), flags: ["test_only_enabled_by_default"] }); + + assert.strictEqual(eslint.hasFlag("test_only_enabled_by_default"), false); + assert.strictEqual(processStub.callCount, 1, "calls `process.emitWarning()` for flags once"); + assert.deepStrictEqual( + processStub.getCall(0).args, + [ + "The flag 'test_only_enabled_by_default' is inactive: Used only for testing flags whose features have been enabled by default.", + "ESLintInactiveFlag_test_only_enabled_by_default" + ] + ); + }); + + it("should throw an error if an inactive flag whose feature has been abandoned is used", () => { + + assert.throws(() => { + eslint = new ESLint({ cwd: getFixturePath(), flags: ["test_only_abandoned"] }); + }, /The flag 'test_only_abandoned' is inactive: Used only for testing flags whose features have been abandoned/u); + + }); + + it("should throw an error if the flag is unknown", () => { assert.throws(() => { - eslint = new ESLint({ cwd: getFixturePath(), flags: ["test_only_old"] }); - }, /The flag 'test_only_old' is inactive/u); + eslint = new ESLint({ cwd: getFixturePath(), flags: ["foo_bar"] }); + }, /Unknown flag 'foo_bar'/u); }); @@ -370,6 +404,23 @@ describe("ESLint", () => { assert.strictEqual(eslint.hasFlag("x_feature"), false); }); + + // TODO: Remove in ESLint v10 when the flag is removed + it("should not throw an error if the flag 'unstable_ts_config' is used", () => { + eslint = new ESLint({ + flags: [...flags, "unstable_ts_config"] + }); + + assert.strictEqual(eslint.hasFlag("unstable_ts_config"), false); + assert.strictEqual(processStub.callCount, 1, "calls `process.emitWarning()` for flags once"); + assert.deepStrictEqual( + processStub.getCall(0).args, + [ + "The flag 'unstable_ts_config' is inactive: This flag is no longer required to enable TypeScript configuration files.", + "ESLintInactiveFlag_unstable_ts_config" + ] + ); + }); }); describe("lintText()", () => { diff --git a/tests/lib/linter/linter.js b/tests/lib/linter/linter.js index a112a6089305..c929100d5d9d 100644 --- a/tests/lib/linter/linter.js +++ b/tests/lib/linter/linter.js @@ -8035,6 +8035,20 @@ describe("Linter with FlatConfigArray", () => { describe("hasFlag()", () => { + let processStub; + + beforeEach(() => { + + // in the browser test, `process.emitWarning` is not defined + if (typeof process !== "undefined" && typeof process.emitWarning !== "undefined") { + processStub = sinon.stub(process, "emitWarning").withArgs(sinon.match.any, sinon.match(/^ESLintInactiveFlag_/u)).returns(); + } + }); + + afterEach(() => { + sinon.restore(); + }); + it("should return true if an active flag is present", () => { assert.strictEqual( new Linter({ configType: "flat", flags: ["test_only"] }).hasFlag("test_only"), @@ -8042,11 +8056,47 @@ describe("Linter with FlatConfigArray", () => { ); }); - it("should throw an error if an inactive flag is present", () => { + it("should return true for the replacement flag if an inactive flag that has been replaced is used", () => { + assert.strictEqual( + new Linter({ configType: "flat", flags: ["test_only_replaced"] }).hasFlag("test_only"), + true + ); + + if (processStub) { + assert.strictEqual(processStub.callCount, 1, "calls `process.emitWarning()` for flags once"); + assert.deepStrictEqual( + processStub.getCall(0).args, + [ + "The flag 'test_only_replaced' is inactive: Used only for testing flags that have been replaced by other flags.", + "ESLintInactiveFlag_test_only_replaced" + ] + ); + } + }); + + it("should return false if an inactive flag whose feature is enabled by default is used", () => { + assert.strictEqual( + new Linter({ configType: "flat", flags: ["test_only_enabled_by_default"] }).hasFlag("test_only_enabled_by_default"), + false + ); + + if (processStub) { + assert.strictEqual(processStub.callCount, 1, "calls `process.emitWarning()` for flags once"); + assert.deepStrictEqual( + processStub.getCall(0).args, + [ + "The flag 'test_only_enabled_by_default' is inactive: Used only for testing flags whose features have been enabled by default.", + "ESLintInactiveFlag_test_only_enabled_by_default" + ] + ); + } + }); + + it("should throw an error if an inactive flag whose feature has been abandoned is used", () => { assert.throws(() => { // eslint-disable-next-line no-new -- needed for test - new Linter({ configType: "flat", flags: ["test_only_old"] }); - }, /The flag 'test_only_old' is inactive: Used only for testing/u); + new Linter({ configType: "flat", flags: ["test_only_abandoned"] }); + }, /The flag 'test_only_abandoned' is inactive: Used only for testing flags whose features have been abandoned/u); }); it("should throw an error if an unknown flag is present", () => { From 05fc5a4467ab91fc88f585c34f56e23bc5afd247 Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Sun, 2 Feb 2025 16:08:53 +0100 Subject: [PATCH 2/3] generate flag inactivity reason message --- docs/src/_data/flags.js | 25 +++++++++++++++----- docs/src/pages/flags.md | 3 ++- lib/linter/linter.js | 15 ++++++------ lib/shared/flags.js | 47 +++++++++++++++++++++++++++++++------- tests/lib/cli.js | 6 ++--- tests/lib/eslint/eslint.js | 8 +++---- tests/lib/linter/linter.js | 6 ++--- 7 files changed, 78 insertions(+), 32 deletions(-) diff --git a/docs/src/_data/flags.js b/docs/src/_data/flags.js index 63761d870490..ec697b7088e4 100644 --- a/docs/src/_data/flags.js +++ b/docs/src/_data/flags.js @@ -11,11 +11,11 @@ /** * Determines whether the flag is used for test purposes only. - * @param {string} flag The flag to check. + * @param {string} name The flag name to check. * @returns {boolean} `true` if the flag is used for test purposes only. */ -function isTestOnlyFlag(flag) { - return flag.startsWith("test_only"); +function isTestOnlyFlag(name) { + return name.startsWith("test_only"); } //----------------------------------------------------------------------------- @@ -24,10 +24,23 @@ function isTestOnlyFlag(flag) { module.exports = function() { - const { activeFlags, inactiveFlags } = require("../../../lib/shared/flags"); + const { activeFlags, inactiveFlags, getInactivityReasonMessage } = require("../../../lib/shared/flags"); return { - active: Object.fromEntries([...activeFlags].filter(([name]) => !isTestOnlyFlag(name))), - inactive: Object.fromEntries([...inactiveFlags].filter(([name]) => !isTestOnlyFlag(name))) + active: Object.fromEntries( + [...activeFlags] + .filter(([name]) => !isTestOnlyFlag(name)) + ), + inactive: Object.fromEntries( + [...inactiveFlags] + .filter(([name]) => !isTestOnlyFlag(name)) + .map(([name, inactiveFlagData]) => [ + name, + { + ...inactiveFlagData, + inactivityReason: getInactivityReasonMessage(inactiveFlagData) + } + ]) + ) }; }; diff --git a/docs/src/pages/flags.md b/docs/src/pages/flags.md index 8f40add1e907..feb23fc1d090 100644 --- a/docs/src/pages/flags.md +++ b/docs/src/pages/flags.md @@ -59,11 +59,12 @@ The following flags were once used but are no longer active. Flag Description + Inactivity Reason {%- for name, data in flags.inactive -%} - {{name}}{{data.description}} + {{name}}{{data.description}}{{data.inactivityReason}} {%- endfor -%} diff --git a/lib/linter/linter.js b/lib/linter/linter.js index 1582941657d8..a06d08b85f83 100644 --- a/lib/linter/linter.js +++ b/lib/linter/linter.js @@ -43,7 +43,7 @@ const { assertIsRuleSeverity } = require("../config/flat-config-schema"); const { normalizeSeverityToString, normalizeSeverityToNumber } = require("../shared/severity"); const { deepMergeArrays } = require("../shared/deep-merge-arrays"); const jslang = require("../languages/js"); -const { activeFlags, inactiveFlags } = require("../shared/flags"); +const { activeFlags, inactiveFlags, getInactivityReasonMessage } = require("../shared/flags"); const debug = require("debug")("eslint:linter"); const MAX_AUTOFIX_PASSES = 10; const DEFAULT_PARSER_NAME = "espree"; @@ -1330,18 +1330,19 @@ class Linter { flags.forEach(flag => { if (inactiveFlags.has(flag)) { - const { description, replacedBy } = inactiveFlags.get(flag); + const inactiveFlagData = inactiveFlags.get(flag); + const inactivityReason = getInactivityReasonMessage(inactiveFlagData); - if (typeof replacedBy === "undefined") { - throw new Error(`The flag '${flag}' is inactive: ${description}`); + if (typeof inactiveFlagData.replacedBy === "undefined") { + throw new Error(`The flag '${flag}' is inactive: ${inactivityReason}`); } - if (typeof replacedBy === "string") { - processedFlags.push(replacedBy); + if (typeof inactiveFlagData.replacedBy === "string") { + processedFlags.push(inactiveFlagData.replacedBy); } globalThis.process?.emitWarning?.( - `The flag '${flag}' is inactive: ${description}`, + `The flag '${flag}' is inactive: ${inactivityReason}`, `ESLintInactiveFlag_${flag}` ); diff --git a/lib/shared/flags.js b/lib/shared/flags.js index b2bb9c158d68..7a232d2b1539 100644 --- a/lib/shared/flags.js +++ b/lib/shared/flags.js @@ -4,6 +4,23 @@ "use strict"; +//------------------------------------------------------------------------------ +// Typedefs +//------------------------------------------------------------------------------ + +/** + * @typedef {Object} InactiveFlagData + * @property {string} description Flag description + * @property {string | null} [replacedBy] Can be either: + * - An active flag (string) that enables the same feature. + * - `null` if the feature is now enabled by default. + * - Omitted if the feature has been abandoned. + */ + +//----------------------------------------------------------------------------- +// Exports +//----------------------------------------------------------------------------- + /** * The set of flags that change ESLint behavior with a description. * @type {Map} @@ -15,21 +32,35 @@ const activeFlags = new Map([ /** * The set of flags that used to be active. - * - * `replacedBy` can be either: - * - An active flag (string) that enables the same feature. - * - `null` if the feature is now enabled by default. - * - Omitted if the feature has been abandoned. - * @type {Map} + * @type {Map} */ const inactiveFlags = new Map([ ["test_only_replaced", { description: "Used only for testing flags that have been replaced by other flags.", replacedBy: "test_only" }], ["test_only_enabled_by_default", { description: "Used only for testing flags whose features have been enabled by default.", replacedBy: null }], ["test_only_abandoned", { description: "Used only for testing flags whose features have been abandoned." }], - ["unstable_ts_config", { description: "This flag is no longer required to enable TypeScript configuration files.", replacedBy: null }] + ["unstable_ts_config", { description: "Enable TypeScript configuration files.", replacedBy: null }] ]); +/** + * Creates a message that describes the reason the flag is inactive. + * @param {InactiveFlagData} inactiveFlagData Data for the inactive flag. + * @returns {string} Message describing the reason the flag is inactive. + */ +function getInactivityReasonMessage({ replacedBy }) { + if (typeof replacedBy === "undefined") { + return "This feature has been abandoned."; + } + + if (typeof replacedBy === "string") { + return `This flag has been renamed '${replacedBy}' to reflect its stabilization. Please use '${replacedBy}' instead.`; + } + + // null + return "This feature is now enabled by default."; +} + module.exports = { activeFlags, - inactiveFlags + inactiveFlags, + getInactivityReasonMessage }; diff --git a/tests/lib/cli.js b/tests/lib/cli.js index d9c9130c37a3..a509428b9381 100644 --- a/tests/lib/cli.js +++ b/tests/lib/cli.js @@ -1921,7 +1921,7 @@ describe("cli", () => { await stdAssert.rejects(async () => { await cli.execute(input, null, true); - }, /The flag 'test_only_abandoned' is inactive: Used only for testing flags whose features have been abandoned\./u); + }, /The flag 'test_only_abandoned' is inactive: This feature has been abandoned\./u); }); it("should error out when an unknown flag is used", async () => { @@ -1944,7 +1944,7 @@ describe("cli", () => { assert.deepStrictEqual( processStub.getCall(0).args, [ - "The flag 'test_only_replaced' is inactive: Used only for testing flags that have been replaced by other flags.", + "The flag 'test_only_replaced' is inactive: This flag has been renamed 'test_only' to reflect its stabilization. Please use 'test_only' instead.", "ESLintInactiveFlag_test_only_replaced" ] ); @@ -1962,7 +1962,7 @@ describe("cli", () => { assert.deepStrictEqual( processStub.getCall(0).args, [ - "The flag 'test_only_enabled_by_default' is inactive: Used only for testing flags whose features have been enabled by default.", + "The flag 'test_only_enabled_by_default' is inactive: This feature is now enabled by default.", "ESLintInactiveFlag_test_only_enabled_by_default" ] ); diff --git a/tests/lib/eslint/eslint.js b/tests/lib/eslint/eslint.js index 0d82e8f9144f..15a37b86b2de 100644 --- a/tests/lib/eslint/eslint.js +++ b/tests/lib/eslint/eslint.js @@ -363,7 +363,7 @@ describe("ESLint", () => { assert.deepStrictEqual( processStub.getCall(0).args, [ - "The flag 'test_only_replaced' is inactive: Used only for testing flags that have been replaced by other flags.", + "The flag 'test_only_replaced' is inactive: This flag has been renamed 'test_only' to reflect its stabilization. Please use 'test_only' instead.", "ESLintInactiveFlag_test_only_replaced" ] ); @@ -377,7 +377,7 @@ describe("ESLint", () => { assert.deepStrictEqual( processStub.getCall(0).args, [ - "The flag 'test_only_enabled_by_default' is inactive: Used only for testing flags whose features have been enabled by default.", + "The flag 'test_only_enabled_by_default' is inactive: This feature is now enabled by default.", "ESLintInactiveFlag_test_only_enabled_by_default" ] ); @@ -387,7 +387,7 @@ describe("ESLint", () => { assert.throws(() => { eslint = new ESLint({ cwd: getFixturePath(), flags: ["test_only_abandoned"] }); - }, /The flag 'test_only_abandoned' is inactive: Used only for testing flags whose features have been abandoned/u); + }, /The flag 'test_only_abandoned' is inactive: This feature has been abandoned/u); }); @@ -416,7 +416,7 @@ describe("ESLint", () => { assert.deepStrictEqual( processStub.getCall(0).args, [ - "The flag 'unstable_ts_config' is inactive: This flag is no longer required to enable TypeScript configuration files.", + "The flag 'unstable_ts_config' is inactive: This feature is now enabled by default.", "ESLintInactiveFlag_unstable_ts_config" ] ); diff --git a/tests/lib/linter/linter.js b/tests/lib/linter/linter.js index c929100d5d9d..e14a5af1ce2c 100644 --- a/tests/lib/linter/linter.js +++ b/tests/lib/linter/linter.js @@ -8067,7 +8067,7 @@ describe("Linter with FlatConfigArray", () => { assert.deepStrictEqual( processStub.getCall(0).args, [ - "The flag 'test_only_replaced' is inactive: Used only for testing flags that have been replaced by other flags.", + "The flag 'test_only_replaced' is inactive: This flag has been renamed 'test_only' to reflect its stabilization. Please use 'test_only' instead.", "ESLintInactiveFlag_test_only_replaced" ] ); @@ -8085,7 +8085,7 @@ describe("Linter with FlatConfigArray", () => { assert.deepStrictEqual( processStub.getCall(0).args, [ - "The flag 'test_only_enabled_by_default' is inactive: Used only for testing flags whose features have been enabled by default.", + "The flag 'test_only_enabled_by_default' is inactive: This feature is now enabled by default.", "ESLintInactiveFlag_test_only_enabled_by_default" ] ); @@ -8096,7 +8096,7 @@ describe("Linter with FlatConfigArray", () => { assert.throws(() => { // eslint-disable-next-line no-new -- needed for test new Linter({ configType: "flat", flags: ["test_only_abandoned"] }); - }, /The flag 'test_only_abandoned' is inactive: Used only for testing flags whose features have been abandoned/u); + }, /The flag 'test_only_abandoned' is inactive: This feature has been abandoned/u); }); it("should throw an error if an unknown flag is present", () => { From 3c6d2cd1d22cafdda27e7055d52c0f66135c3d96 Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Mon, 3 Feb 2025 18:56:14 +0100 Subject: [PATCH 3/3] add comment Co-authored-by: Nicholas C. Zakas --- lib/linter/linter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/linter/linter.js b/lib/linter/linter.js index a06d08b85f83..6db9c13b706a 100644 --- a/lib/linter/linter.js +++ b/lib/linter/linter.js @@ -1337,6 +1337,7 @@ class Linter { throw new Error(`The flag '${flag}' is inactive: ${inactivityReason}`); } + // if there's a replacement, enable it instead of original if (typeof inactiveFlagData.replacedBy === "string") { processedFlags.push(inactiveFlagData.replacedBy); } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy