Skip to content

Commit 1c173dc

Browse files
feat: add ignoreClassWithStaticInitBlock option to no-unused-vars (#18170)
* feat: add option to ignore SIB-classes * add docs and tests * add test * update docs
1 parent d961eeb commit 1c173dc

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

docs/src/rules/no-unused-vars.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,51 @@ var bar;
410410

411411
:::
412412

413+
### ignoreClassWithStaticInitBlock
414+
415+
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.
416+
417+
Examples of **incorrect** code for the `{ "ignoreClassWithStaticInitBlock": true }` option
418+
419+
::: incorrect
420+
421+
```js
422+
/*eslint no-unused-vars: ["error", { "ignoreClassWithStaticInitBlock": true }]*/
423+
424+
class Foo {
425+
static myProperty = "some string";
426+
static mymethod() {
427+
return "some string";
428+
}
429+
}
430+
431+
class Bar {
432+
static {
433+
let baz; // unused variable
434+
}
435+
}
436+
```
437+
438+
:::
439+
440+
Examples of **correct** code for the `{ "ignoreClassWithStaticInitBlock": true }` option
441+
442+
::: correct
443+
444+
```js
445+
/*eslint no-unused-vars: ["error", { "ignoreClassWithStaticInitBlock": true }]*/
446+
447+
class Foo {
448+
static {
449+
let bar = "some string";
450+
451+
console.log(bar);
452+
}
453+
}
454+
```
455+
456+
:::
457+
413458
## When Not To Use It
414459

415460
If you don't want to be notified about unused variables or function arguments, you can safely turn this rule off.

lib/rules/no-unused-vars.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ module.exports = {
7070
},
7171
destructuredArrayIgnorePattern: {
7272
type: "string"
73+
},
74+
ignoreClassWithStaticInitBlock: {
75+
type: "boolean"
7376
}
7477
},
7578
additionalProperties: false
@@ -92,7 +95,8 @@ module.exports = {
9295
vars: "all",
9396
args: "after-used",
9497
ignoreRestSiblings: false,
95-
caughtErrors: "all"
98+
caughtErrors: "all",
99+
ignoreClassWithStaticInitBlock: false
96100
};
97101

98102
const firstOption = context.options[0];
@@ -105,6 +109,7 @@ module.exports = {
105109
config.args = firstOption.args || config.args;
106110
config.ignoreRestSiblings = firstOption.ignoreRestSiblings || config.ignoreRestSiblings;
107111
config.caughtErrors = firstOption.caughtErrors || config.caughtErrors;
112+
config.ignoreClassWithStaticInitBlock = firstOption.ignoreClassWithStaticInitBlock || config.ignoreClassWithStaticInitBlock;
108113

109114
if (firstOption.varsIgnorePattern) {
110115
config.varsIgnorePattern = new RegExp(firstOption.varsIgnorePattern, "u");
@@ -613,6 +618,14 @@ module.exports = {
613618
continue;
614619
}
615620

621+
if (type === "ClassName") {
622+
const hasStaticBlock = def.node.body.body.some(node => node.type === "StaticBlock");
623+
624+
if (config.ignoreClassWithStaticInitBlock && hasStaticBlock) {
625+
continue;
626+
}
627+
}
628+
616629
// skip catch variables
617630
if (type === "CatchClause") {
618631
if (config.caughtErrors === "none") {

tests/lib/rules/no-unused-vars.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,23 @@ ruleTester.run("no-unused-vars", rule, {
445445
{
446446
code: "var a; a ??= 1;",
447447
languageOptions: { ecmaVersion: 2021 }
448+
},
449+
450+
// ignore class with static initialization block https://github.com/eslint/eslint/issues/17772
451+
{
452+
code: "class Foo { static {} }",
453+
options: [{ ignoreClassWithStaticInitBlock: true }],
454+
languageOptions: { ecmaVersion: 2022 }
455+
},
456+
{
457+
code: "class Foo { static {} }",
458+
options: [{ ignoreClassWithStaticInitBlock: true, varsIgnorePattern: "^_" }],
459+
languageOptions: { ecmaVersion: 2022 }
460+
},
461+
{
462+
code: "class Foo { static {} }",
463+
options: [{ ignoreClassWithStaticInitBlock: false, varsIgnorePattern: "^Foo" }],
464+
languageOptions: { ecmaVersion: 2022 }
448465
}
449466
],
450467
invalid: [
@@ -1557,6 +1574,43 @@ function foo1() {
15571574
c = foo1`,
15581575
languageOptions: { ecmaVersion: 2020 },
15591576
errors: [{ ...assignedError("c"), line: 10, column: 1 }]
1577+
},
1578+
1579+
// ignore class with static initialization block https://github.com/eslint/eslint/issues/17772
1580+
{
1581+
code: "class Foo { static {} }",
1582+
options: [{ ignoreClassWithStaticInitBlock: false }],
1583+
languageOptions: { ecmaVersion: 2022 },
1584+
errors: [{ ...definedError("Foo"), line: 1, column: 7 }]
1585+
},
1586+
{
1587+
code: "class Foo { static {} }",
1588+
languageOptions: { ecmaVersion: 2022 },
1589+
errors: [{ ...definedError("Foo"), line: 1, column: 7 }]
1590+
},
1591+
{
1592+
code: "class Foo { static { var bar; } }",
1593+
options: [{ ignoreClassWithStaticInitBlock: true }],
1594+
languageOptions: { ecmaVersion: 2022 },
1595+
errors: [{ ...definedError("bar"), line: 1, column: 26 }]
1596+
},
1597+
{
1598+
code: "class Foo {}",
1599+
options: [{ ignoreClassWithStaticInitBlock: true }],
1600+
languageOptions: { ecmaVersion: 2022 },
1601+
errors: [{ ...definedError("Foo"), line: 1, column: 7 }]
1602+
},
1603+
{
1604+
code: "class Foo { static bar; }",
1605+
options: [{ ignoreClassWithStaticInitBlock: true }],
1606+
languageOptions: { ecmaVersion: 2022 },
1607+
errors: [{ ...definedError("Foo"), line: 1, column: 7 }]
1608+
},
1609+
{
1610+
code: "class Foo { static bar() {} }",
1611+
options: [{ ignoreClassWithStaticInitBlock: true }],
1612+
languageOptions: { ecmaVersion: 2022 },
1613+
errors: [{ ...definedError("Foo"), line: 1, column: 7 }]
15601614
}
15611615
]
15621616
});

0 commit comments

Comments
 (0)