From b4bd83acf54a8d1d24ceac3089b16f1e90f6a5ea Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 16 Sep 2021 10:34:05 -0700 Subject: [PATCH 1/3] Update: Suggest missing rule in flat config (fixes #14027) --- lib/config/rule-validator.js | 26 ++++++++++++++++------ tests/lib/config/flat-config-array.js | 32 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/lib/config/rule-validator.js b/lib/config/rule-validator.js index fe1aa863bfd..6f25f86b9c1 100644 --- a/lib/config/rule-validator.js +++ b/lib/config/rule-validator.js @@ -35,16 +35,28 @@ function findRuleDefinition(ruleId, config) { pluginName = ruleIdParts.join("/"); } - if (!config.plugins || !config.plugins[pluginName]) { - throw new TypeError(`Key "rules": Key "${ruleId}": Could not find plugin "${pluginName}".`); - } + if (config?.plugins) { - if (!config.plugins[pluginName].rules || !config.plugins[pluginName].rules[ruleName]) { - throw new TypeError(`Key "rules": Key "${ruleId}": Could not find "${ruleName}" in plugin "${pluginName}".`); - } + // first check for exact rule match + if (config.plugins?.[pluginName]?.rules?.[ruleName]) { + return config.plugins[pluginName].rules[ruleName]; + } - return config.plugins[pluginName].rules[ruleName]; + let errorMessage = `Key "rules": Key "${ruleId}": Could not find "${ruleName}" in plugin "${pluginName}".`; + + // otherwise, let's see if we can find the rule name elsewhere + for (const [otherPluginName, plugin] of Object.entries(config.plugins)) { + if (plugin?.rules?.[ruleName]) { + errorMessage += ` Did you mean "${otherPluginName}/${ruleName}"?`; + break; + } + } + + throw new TypeError(errorMessage); + + } + throw new TypeError(`Key "rules": Key "${ruleId}": Could not find plugin "${pluginName}".`); } /** diff --git a/tests/lib/config/flat-config-array.js b/tests/lib/config/flat-config-array.js index fd89f8d972c..e43e195ac41 100644 --- a/tests/lib/config/flat-config-array.js +++ b/tests/lib/config/flat-config-array.js @@ -56,6 +56,16 @@ const baseConfig = { } } } + }, + test1: { + rules: { + match: {} + } + }, + test2: { + rules: { + nomatch: {} + } } } }; @@ -1278,6 +1288,28 @@ describe("FlatConfigArray", () => { ], "Key \"rules\": Key \"foo\": Expected severity of \"off\", 0, \"warn\", 1, \"error\", or 2."); }); + it("should error when rule doesn't exist", async () => { + + await assertInvalidConfig([ + { + rules: { + foox: [1, "bar"] + } + } + ], /Key "rules": Key "foox": Could not find "foox" in plugin "@"./u); + }); + + it("should error and suggest alternative when rule doesn't exist", async () => { + + await assertInvalidConfig([ + { + rules: { + "test2/match": "error" + } + } + ], /Key "rules": Key "test2\/match": Could not find "match" in plugin "test2"\. Did you mean "test1\/match"\?/u); + }); + it("should error when rule options don't match schema", async () => { await assertInvalidConfig([ From a77fbe059cb26ef2dbf8b799427a32fa641f0ed6 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 16 Sep 2021 10:38:42 -0700 Subject: [PATCH 2/3] Switch to older syntax --- lib/config/rule-validator.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/config/rule-validator.js b/lib/config/rule-validator.js index 6f25f86b9c1..403f7a072a6 100644 --- a/lib/config/rule-validator.js +++ b/lib/config/rule-validator.js @@ -35,18 +35,20 @@ function findRuleDefinition(ruleId, config) { pluginName = ruleIdParts.join("/"); } - if (config?.plugins) { + if (config.plugins) { + + const plugin = config.plugins[pluginName]; // first check for exact rule match - if (config.plugins?.[pluginName]?.rules?.[ruleName]) { + if (plugin && plugin.rules && plugin.rules[ruleName]) { return config.plugins[pluginName].rules[ruleName]; } let errorMessage = `Key "rules": Key "${ruleId}": Could not find "${ruleName}" in plugin "${pluginName}".`; // otherwise, let's see if we can find the rule name elsewhere - for (const [otherPluginName, plugin] of Object.entries(config.plugins)) { - if (plugin?.rules?.[ruleName]) { + for (const [otherPluginName, otherPlugin] of Object.entries(config.plugins)) { + if (otherPlugin.rules && otherPlugin.rules[ruleName]) { errorMessage += ` Did you mean "${otherPluginName}/${ruleName}"?`; break; } From 2639f8ba70190ef46fe26bd7c8294f6e9dc6a01e Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Fri, 24 Sep 2021 10:48:08 -0700 Subject: [PATCH 3/3] Fix error messages --- lib/config/rule-validator.js | 15 +++++++++------ tests/lib/config/flat-config-array.js | 11 +++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/config/rule-validator.js b/lib/config/rule-validator.js index 403f7a072a6..527a56e1799 100644 --- a/lib/config/rule-validator.js +++ b/lib/config/rule-validator.js @@ -35,16 +35,20 @@ function findRuleDefinition(ruleId, config) { pluginName = ruleIdParts.join("/"); } - if (config.plugins) { + const errorMessageHeader = `Key "rules": Key "${ruleId}"`; + let errorMessage = `${errorMessageHeader}: Could not find plugin "${pluginName}".`; + + // if the plugin exists then we need to check if the rule exists + if (config.plugins && config.plugins[pluginName]) { const plugin = config.plugins[pluginName]; // first check for exact rule match - if (plugin && plugin.rules && plugin.rules[ruleName]) { + if (plugin.rules && plugin.rules[ruleName]) { return config.plugins[pluginName].rules[ruleName]; } - let errorMessage = `Key "rules": Key "${ruleId}": Could not find "${ruleName}" in plugin "${pluginName}".`; + errorMessage = `${errorMessageHeader}: Could not find "${ruleName}" in plugin "${pluginName}".`; // otherwise, let's see if we can find the rule name elsewhere for (const [otherPluginName, otherPlugin] of Object.entries(config.plugins)) { @@ -54,11 +58,10 @@ function findRuleDefinition(ruleId, config) { } } - throw new TypeError(errorMessage); - + // falls through to throw error } - throw new TypeError(`Key "rules": Key "${ruleId}": Could not find plugin "${pluginName}".`); + throw new TypeError(errorMessage); } /** diff --git a/tests/lib/config/flat-config-array.js b/tests/lib/config/flat-config-array.js index e43e195ac41..f6b099096e1 100644 --- a/tests/lib/config/flat-config-array.js +++ b/tests/lib/config/flat-config-array.js @@ -1310,6 +1310,17 @@ describe("FlatConfigArray", () => { ], /Key "rules": Key "test2\/match": Could not find "match" in plugin "test2"\. Did you mean "test1\/match"\?/u); }); + it("should error when plugin for rule doesn't exist", async () => { + + await assertInvalidConfig([ + { + rules: { + "doesnt-exist/match": "error" + } + } + ], /Key "rules": Key "doesnt-exist\/match": Could not find plugin "doesnt-exist"\./u); + }); + it("should error when rule options don't match schema", async () => { await assertInvalidConfig([