From a24fc82605832756c273df79124cc3b28bea20f1 Mon Sep 17 00:00:00 2001 From: Tanuj Kanti Date: Tue, 5 Mar 2024 21:43:04 +0530 Subject: [PATCH 1/4] feat: add option to ignore SIB-classes --- lib/rules/no-unused-vars.js | 15 ++++++++++++++- tests/lib/rules/no-unused-vars.js | 27 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/rules/no-unused-vars.js b/lib/rules/no-unused-vars.js index 74a664089ed..aab7a43552c 100644 --- a/lib/rules/no-unused-vars.js +++ b/lib/rules/no-unused-vars.js @@ -70,6 +70,9 @@ module.exports = { }, destructuredArrayIgnorePattern: { type: "string" + }, + ignoreClassWithStaticInitBlock: { + type: "boolean" } }, additionalProperties: false @@ -92,7 +95,8 @@ module.exports = { vars: "all", args: "after-used", ignoreRestSiblings: false, - caughtErrors: "all" + caughtErrors: "all", + ignoreClassWithStaticInitBlock: false }; const firstOption = context.options[0]; @@ -105,6 +109,7 @@ module.exports = { config.args = firstOption.args || config.args; config.ignoreRestSiblings = firstOption.ignoreRestSiblings || config.ignoreRestSiblings; config.caughtErrors = firstOption.caughtErrors || config.caughtErrors; + config.ignoreClassWithStaticInitBlock = firstOption.ignoreClassWithStaticInitBlock || config.ignoreClassWithStaticInitBlock; if (firstOption.varsIgnorePattern) { config.varsIgnorePattern = new RegExp(firstOption.varsIgnorePattern, "u"); @@ -613,6 +618,14 @@ module.exports = { continue; } + if (type === "ClassName") { + const hasStaticBlock = def.node.body.body.filter(node => node.type === "StaticBlock"); + + if (config.ignoreClassWithStaticInitBlock && hasStaticBlock) { + continue; + } + } + // skip catch variables if (type === "CatchClause") { if (config.caughtErrors === "none") { diff --git a/tests/lib/rules/no-unused-vars.js b/tests/lib/rules/no-unused-vars.js index 0d8e7c33b89..2fea115fb99 100644 --- a/tests/lib/rules/no-unused-vars.js +++ b/tests/lib/rules/no-unused-vars.js @@ -445,6 +445,21 @@ ruleTester.run("no-unused-vars", rule, { { code: "var a; a ??= 1;", languageOptions: { ecmaVersion: 2021 } + }, + { + code: "class Foo { static {} }", + options: [{ ignoreClassWithStaticInitBlock: true }], + languageOptions: { ecmaVersion: 2022 } + }, + { + code: "class Foo { static {} }", + options: [{ ignoreClassWithStaticInitBlock: true, varsIgnorePattern: "^_" }], + languageOptions: { ecmaVersion: 2022 } + }, + { + code: "class Foo { static {} }", + options: [{ ignoreClassWithStaticInitBlock: false, varsIgnorePattern: "^Foo" }], + languageOptions: { ecmaVersion: 2022 } } ], invalid: [ @@ -1557,6 +1572,18 @@ function foo1() { c = foo1`, languageOptions: { ecmaVersion: 2020 }, errors: [{ ...assignedError("c"), line: 10, column: 1 }] + }, + { + code: "class Foo { static {} }", + options: [{ ignoreClassWithStaticInitBlock: false }], + languageOptions: { ecmaVersion: 2022 }, + errors: [{ ...definedError("Foo"), line: 1, column: 7 }] + }, + { + code: "class Foo { static { var bar; } }", + options: [{ ignoreClassWithStaticInitBlock: true }], + languageOptions: { ecmaVersion: 2022 }, + errors: [{ ...definedError("bar"), line: 1, column: 26 }] } ] }); From 6b9558adeff6f790e630c67d35d2768e795529f0 Mon Sep 17 00:00:00 2001 From: Tanuj Kanti Date: Wed, 6 Mar 2024 17:12:59 +0530 Subject: [PATCH 2/4] add docs and tests --- docs/src/rules/no-unused-vars.md | 45 +++++++++++++++++++++++++++++++ lib/rules/no-unused-vars.js | 2 +- tests/lib/rules/no-unused-vars.js | 20 ++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/docs/src/rules/no-unused-vars.md b/docs/src/rules/no-unused-vars.md index d924f02d657..0d6d6c9e03a 100644 --- a/docs/src/rules/no-unused-vars.md +++ b/docs/src/rules/no-unused-vars.md @@ -410,6 +410,51 @@ var bar; ::: +### ignoreClassWithStaticInitBlock + +The `ignoreClassWithStaticInitBlock` option is a boolean (default: `false`). Static initialization blocks or Static blocks was introduced in ES2022. Static blocks lets us to initialize static variables and execute code during the evaluation of defined class. It means that one don't need to create an instance of class to run the code written inside the static block. This option ignore the classes with static initialization block when sets to `true`. + +Examples of **incorrect** code for the `{ "ignoreClassWithStaticInitBlock": true }` option + +::: incorrect + +```js +/*eslint no-unused-vars: ["error", { "ignoreClassWithStaticInitBlock": true }]*/ + +class Foo { + static myProperty = "some string"; + static mymethod() { + return "some string"; + } +} + +class Bar { + static { + let baz; // unused variable + } +} +``` + +::: + +Examples of **correct** code for the `{ "ignoreClassWithStaticInitBlock": true }` option + +::: correct + +```js +/*eslint no-unused-vars: ["error", { "ignoreClassWithStaticInitBlock": true }]*/ + +class Foo { + static { + let bar = "some string"; + + console.log(bar); + } +} +``` + +::: + ## When Not To Use It If you don't want to be notified about unused variables or function arguments, you can safely turn this rule off. diff --git a/lib/rules/no-unused-vars.js b/lib/rules/no-unused-vars.js index aab7a43552c..90b76e6f2d1 100644 --- a/lib/rules/no-unused-vars.js +++ b/lib/rules/no-unused-vars.js @@ -619,7 +619,7 @@ module.exports = { } if (type === "ClassName") { - const hasStaticBlock = def.node.body.body.filter(node => node.type === "StaticBlock"); + const hasStaticBlock = def.node.body.body.some(node => node.type === "StaticBlock"); if (config.ignoreClassWithStaticInitBlock && hasStaticBlock) { continue; diff --git a/tests/lib/rules/no-unused-vars.js b/tests/lib/rules/no-unused-vars.js index 2fea115fb99..43489c2c019 100644 --- a/tests/lib/rules/no-unused-vars.js +++ b/tests/lib/rules/no-unused-vars.js @@ -446,6 +446,8 @@ ruleTester.run("no-unused-vars", rule, { code: "var a; a ??= 1;", languageOptions: { ecmaVersion: 2021 } }, + + // ignore class with static initialization block https://github.com/eslint/eslint/issues/17772 { code: "class Foo { static {} }", options: [{ ignoreClassWithStaticInitBlock: true }], @@ -1573,17 +1575,35 @@ c = foo1`, languageOptions: { ecmaVersion: 2020 }, errors: [{ ...assignedError("c"), line: 10, column: 1 }] }, + + // ignore class with static initialization block https://github.com/eslint/eslint/issues/17772 { code: "class Foo { static {} }", options: [{ ignoreClassWithStaticInitBlock: false }], languageOptions: { ecmaVersion: 2022 }, errors: [{ ...definedError("Foo"), line: 1, column: 7 }] }, + { + code: "class Foo { static {} }", + languageOptions: { ecmaVersion: 2022 }, + errors: [{ ...definedError("Foo"), line: 1, column: 7 }] + }, { code: "class Foo { static { var bar; } }", options: [{ ignoreClassWithStaticInitBlock: true }], languageOptions: { ecmaVersion: 2022 }, errors: [{ ...definedError("bar"), line: 1, column: 26 }] + }, + { + code: "class Foo {}", + options: [{ ignoreClassWithStaticInitBlock: true }], + languageOptions: { ecmaVersion: 2022 }, + errors: [{ ...definedError("Foo"), line: 1, column: 7 }] + }, + { + code: "class Foo { static bar }", + languageOptions: { ecmaVersion: 2022 }, + errors: [{ ...definedError("Foo"), line: 1, column: 7 }] } ] }); From bc4a880565362a244dd9630bfcd4203200d4e823 Mon Sep 17 00:00:00 2001 From: Tanuj Kanti Date: Wed, 6 Mar 2024 17:18:23 +0530 Subject: [PATCH 3/4] add test --- tests/lib/rules/no-unused-vars.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/lib/rules/no-unused-vars.js b/tests/lib/rules/no-unused-vars.js index 43489c2c019..de85050248f 100644 --- a/tests/lib/rules/no-unused-vars.js +++ b/tests/lib/rules/no-unused-vars.js @@ -1601,7 +1601,14 @@ c = foo1`, errors: [{ ...definedError("Foo"), line: 1, column: 7 }] }, { - code: "class Foo { static bar }", + code: "class Foo { static bar; }", + options: [{ ignoreClassWithStaticInitBlock: true }], + languageOptions: { ecmaVersion: 2022 }, + errors: [{ ...definedError("Foo"), line: 1, column: 7 }] + }, + { + code: "class Foo { static bar() {} }", + options: [{ ignoreClassWithStaticInitBlock: true }], languageOptions: { ecmaVersion: 2022 }, errors: [{ ...definedError("Foo"), line: 1, column: 7 }] } From 63839c6d1a8700887dd62ecd8daa1088a2bbc7c6 Mon Sep 17 00:00:00 2001 From: Tanuj Kanti Date: Thu, 7 Mar 2024 10:51:50 +0530 Subject: [PATCH 4/4] update docs --- docs/src/rules/no-unused-vars.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/rules/no-unused-vars.md b/docs/src/rules/no-unused-vars.md index 0d6d6c9e03a..cc361e955e4 100644 --- a/docs/src/rules/no-unused-vars.md +++ b/docs/src/rules/no-unused-vars.md @@ -412,7 +412,7 @@ var bar; ### ignoreClassWithStaticInitBlock -The `ignoreClassWithStaticInitBlock` option is a boolean (default: `false`). Static initialization blocks or Static blocks was introduced in ES2022. Static blocks lets us to initialize static variables and execute code during the evaluation of defined class. It means that one don't need to create an instance of class to run the code written inside the static block. This option ignore the classes with static initialization block when sets to `true`. +The `ignoreClassWithStaticInitBlock` option is a boolean (default: `false`). Static initialization blocks allow you to initialize static variables and execute code during the evaluation of a class definition, meaning the static block code is executed without creating a new instance of the class. When set to `true`, this option ignores classes containing static initialization blocks. Examples of **incorrect** code for the `{ "ignoreClassWithStaticInitBlock": true }` option