From a98f1a55faa1871a5369bee5b8989a725bb9e17e Mon Sep 17 00:00:00 2001 From: Joe Hildebrand Date: Wed, 28 Feb 2024 21:05:44 -0700 Subject: [PATCH] Allow filtering of unused rules, so only matching rules are checked. --- docs/rules/no-unused-rules.md | 20 ++++++++++++++++++++ src/rules/no-unused-rules.ts | 19 ++++++++++++++++++- test/rules/no-unused-rules.test.js | 16 ++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/docs/rules/no-unused-rules.md b/docs/rules/no-unused-rules.md index 779ee4d..9c4e2ac 100644 --- a/docs/rules/no-unused-rules.md +++ b/docs/rules/no-unused-rules.md @@ -18,6 +18,13 @@ foo = "1" // Good. Default entry point. bar = "2" // Bad. Not referenced. ``` +```peg.js +// eslint @peggyjs/no-unused-rules: ["error", {filter: "^_"}] +foo = "foo" // Good. +bar = "bar" // Doesn't match the filter +_boo = "boo" // Bad. Not referenced, and matches the filter. +``` + :+1: Examples of **correct** code for this rule: ```peg.js @@ -27,6 +34,19 @@ foo = bar / baz bar = "2" ``` +```peg.js +// eslint @peggyjs/no-unused-rules: ["error", {filter: "^_"}] +foo = _boo +bar = "bar" // Doesn't match the filter +_boo = "boo" +``` + +### Options + +The first option can be an object with the key "filter". The filter is treated +as a regular expression; only rules that match this expression will cause +errors if they are unused. + ## 🔎 Implementation - [Rule source](../../src/rules/no-unused-rules.ts) diff --git a/src/rules/no-unused-rules.ts b/src/rules/no-unused-rules.ts index e912898..41cffca 100644 --- a/src/rules/no-unused-rules.ts +++ b/src/rules/no-unused-rules.ts @@ -14,13 +14,26 @@ const rule: Rule.RuleModule = { unused: "Rule '{{ name }}' is never used.", unusedImport: "Library import '{{ name }}' is never used.", }, - schema: [], + schema: [ + { + type: "object", + properties: { + filter: { + type: "string", + }, + }, + additionalProperties: false, + }, + ], }, create(context: Rule.RuleContext): Rule.RuleListener { const imports = new Map(); const rules = new Map(); const refs = new Set(); const importRefs = new Set(); + const filter = context.options[0]?.filter; + const match = filter ? new RegExp(filter) : undefined; + return makeListener({ import_binding(node: visitor.AST.ImportBinding): void { imports.set(node.binding.id.value, node.binding.id); @@ -52,7 +65,11 @@ const rule: Rule.RuleModule = { rules.delete(name); imports.delete(name); } + for (const [name, r] of rules) { + if (match && !match.test(name)) { + continue; + } context.report({ node: n(r), messageId: "unused", diff --git a/test/rules/no-unused-rules.test.js b/test/rules/no-unused-rules.test.js index 41a7026..d36e1b6 100644 --- a/test/rules/no-unused-rules.test.js +++ b/test/rules/no-unused-rules.test.js @@ -40,6 +40,13 @@ foo = bar`, import {"foo" as bar} from 'bar' foo = bar`, }, + { + options: [{ filter: "^_" }], + code: ` +foo = _bar +baz = "boo" +_bar = "bar"`, + }, ], invalid: [ { @@ -76,5 +83,14 @@ foo = bar`, foo = "1"`, errors: [{ messageId: "unusedImport" }], }, + { + options: [{ filter: "^_" }], + code: ` +foo = _bar +baz = "boo" +_bar = "bar" +_boo = "boo"`, + errors: [{ messageId: "unused" }], + }, ], });