From 3f3ba342499c942acd02192dbfab243923fc21f7 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sat, 17 Sep 2022 16:50:52 +0900 Subject: [PATCH 01/11] feat: add `no-empty-static-block` --- lib/rules/no-empty-static-block.js | 55 ++++++++++++++++++++++++ tests/lib/rules/no-empty-static-block.js | 52 ++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 lib/rules/no-empty-static-block.js create mode 100644 tests/lib/rules/no-empty-static-block.js diff --git a/lib/rules/no-empty-static-block.js b/lib/rules/no-empty-static-block.js new file mode 100644 index 00000000000..3b8b60c38ae --- /dev/null +++ b/lib/rules/no-empty-static-block.js @@ -0,0 +1,55 @@ +/** + * @fileoverview Rule to disallow empty static blocks. + * @author Sosuke Suzuki + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("./utils/ast-utils"); + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +/** @type {import('../shared/types').Rule} */ +module.exports = { + meta: { + type: "suggestion", + + docs: { + description: "Disallows empty static blocks", + recommended: false, + url: "https://eslint.org/docs/rules/no-empty-static-block" + }, + + schema: [], + + messages: { + unexpected: "Unexpected empty static block." + } + }, + + create(context) { + const sourceCode = context.getSourceCode(); + + return { + StaticBlock(node) { + const innerComments = sourceCode.getTokens(node, { + includeComments: true, + filter: astUtils.isCommentToken + }); + + if (node.body.length === 0 && innerComments.length === 0) { + context.report({ + node, + loc: node.loc, + messageId: "unexpected" + }); + } + } + }; + } +}; diff --git a/tests/lib/rules/no-empty-static-block.js b/tests/lib/rules/no-empty-static-block.js new file mode 100644 index 00000000000..af3766a5e02 --- /dev/null +++ b/tests/lib/rules/no-empty-static-block.js @@ -0,0 +1,52 @@ +/** + * @fileoverview Tests for no-empty-static-block rule. + * @author Sosuke Suzuki + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/no-empty-static-block"), + { RuleTester } = require("../../../lib/rule-tester"); + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); + +ruleTester.run("no-empty-static-block", rule, { + valid: [ + { + code: "class Foo { static { bar(); } }", + parserOptions: { ecmaVersion: 2022 } + }, + { + code: "class Foo { static { /* comments */ } }", + parserOptions: { ecmaVersion: 2022 } + }, + { + code: "class Foo { static {\n// comment\n} }", + parserOptions: { ecmaVersion: 2022 } + } + ], + invalid: [ + { + code: "class Foo { static {} }", + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "class Foo { static { } }", + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "unexpected" }] + }, + { + code: "class Foo { static { \n\n } }", + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "unexpected" }] + } + ] +}); From b043a11dc1fcd5eca344a748e5a42dc7adf66699 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sat, 17 Sep 2022 17:11:35 +0900 Subject: [PATCH 02/11] docs: add docs for `no-empty-static-block` --- docs/src/rules/no-empty-static-block.md | 59 +++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 docs/src/rules/no-empty-static-block.md diff --git a/docs/src/rules/no-empty-static-block.md b/docs/src/rules/no-empty-static-block.md new file mode 100644 index 00000000000..17447690621 --- /dev/null +++ b/docs/src/rules/no-empty-static-block.md @@ -0,0 +1,59 @@ +--- +title: no-empty-static-block +layout: doc +rule_type: suggestion +related_rules: +- no-empty +- no-empty-function +- https://github.com/tc39/proposal-class-static-block +--- + +Empty static blocks, while not technically errors, usually occur due to refactoring that wasn't completed. They can cause confusion when reading code. + +## Rule Details + +This rule disallows empty static blocks. This rule ignores static blocks which contain a comment. + +Examples of **incorrect** code for this rule: + +::: incorrect + +```js +/*eslint no-empty-static-block: "error"*/ + +class Foo { + static {} +} +``` + +::: + +Examples of **correct** code for this rule: + +:::correct + +```js +/*eslint no-empty-static-block: "error"*/ + +class Foo { + static { + bar(); + } +} + +class Foo { + static { + // comment + } +} +``` + +::: + +## Options + +Nothing. + +## When Not To Use It + +This rule should not be used in environments prior to ES2022. From 7e6e4123d70dc6467a4f7ce154f17cb783922fa9 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sat, 17 Sep 2022 17:29:31 +0900 Subject: [PATCH 03/11] chore: add `no-empty-static-block` --- lib/rules/index.js | 1 + tools/rule-types.json | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/rules/index.js b/lib/rules/index.js index 565648c09e8..f729887d068 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -123,6 +123,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({ "no-empty-character-class": () => require("./no-empty-character-class"), "no-empty-function": () => require("./no-empty-function"), "no-empty-pattern": () => require("./no-empty-pattern"), + "no-empty-static-block": () => require("./no-empty-static-block"), "no-eq-null": () => require("./no-eq-null"), "no-eval": () => require("./no-eval"), "no-ex-assign": () => require("./no-ex-assign"), diff --git a/tools/rule-types.json b/tools/rule-types.json index 9867d6b2f33..ed6a8123d21 100644 --- a/tools/rule-types.json +++ b/tools/rule-types.json @@ -110,6 +110,7 @@ "no-empty-character-class": "problem", "no-empty-function": "suggestion", "no-empty-pattern": "problem", + "no-empty-static-block": "suggestion", "no-eq-null": "suggestion", "no-eval": "suggestion", "no-ex-assign": "problem", From 14f6e6a232d7689c27ad0020d280bfffb5f2e843 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sun, 18 Sep 2022 00:51:24 +0900 Subject: [PATCH 04/11] test: add tests for multiple static blocks --- tests/lib/rules/no-empty-static-block.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/lib/rules/no-empty-static-block.js b/tests/lib/rules/no-empty-static-block.js index af3766a5e02..1a63f454d2c 100644 --- a/tests/lib/rules/no-empty-static-block.js +++ b/tests/lib/rules/no-empty-static-block.js @@ -30,6 +30,10 @@ ruleTester.run("no-empty-static-block", rule, { { code: "class Foo { static {\n// comment\n} }", parserOptions: { ecmaVersion: 2022 } + }, + { + code: "class Foo { static { bar(); } static { bar(); } }", + parserOptions: { ecmaVersion: 2022 } } ], invalid: [ @@ -47,6 +51,11 @@ ruleTester.run("no-empty-static-block", rule, { code: "class Foo { static { \n\n } }", parserOptions: { ecmaVersion: 2022 }, errors: [{ messageId: "unexpected" }] + }, + { + code: "class Foo { static { bar(); } static {} }", + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "unexpected" }] } ] }); From 690f40d801f64acef395b05cfec14f14921e4d5f Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sun, 18 Sep 2022 01:11:41 +0900 Subject: [PATCH 05/11] Add `further_reading` --- docs/src/_data/further_reading_links.json | 7 +++++++ docs/src/rules/no-empty-static-block.md | 1 + 2 files changed, 8 insertions(+) diff --git a/docs/src/_data/further_reading_links.json b/docs/src/_data/further_reading_links.json index dc81f7f1640..333cb8e48a3 100644 --- a/docs/src/_data/further_reading_links.json +++ b/docs/src/_data/further_reading_links.json @@ -698,5 +698,12 @@ "logo": "https://eslint.org/apple-touch-icon.png", "title": "Interesting bugs caught by no-constant-binary-expression - ESLint - Pluggable JavaScript Linter", "description": "A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease." + }, + "https://github.com/tc39/proposal-class-static-block": { + "domain": "github.com", + "url": "https://github.com/tc39/proposal-class-static-block", + "logo": "https://github.com/fluidicon.png", + "title": "GitHub - tc39/proposal-class-static-block: ECMAScript class static initialization blocks", + "description": "ECMAScript class static initialization blocks. Contribute to tc39/proposal-class-static-block development by creating an account on GitHub." } } \ No newline at end of file diff --git a/docs/src/rules/no-empty-static-block.md b/docs/src/rules/no-empty-static-block.md index 17447690621..e6a9e3ce5f4 100644 --- a/docs/src/rules/no-empty-static-block.md +++ b/docs/src/rules/no-empty-static-block.md @@ -5,6 +5,7 @@ rule_type: suggestion related_rules: - no-empty - no-empty-function +further_reading: - https://github.com/tc39/proposal-class-static-block --- From 27d1256548f973858e1b70fb1f12777d8741df04 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Tue, 20 Sep 2022 18:23:59 +0900 Subject: [PATCH 06/11] test: specify `ecmaVersion` at `RuleTester` --- tests/lib/rules/no-empty-static-block.js | 28 ++++++------------------ 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/tests/lib/rules/no-empty-static-block.js b/tests/lib/rules/no-empty-static-block.js index 1a63f454d2c..7e7176cc5cf 100644 --- a/tests/lib/rules/no-empty-static-block.js +++ b/tests/lib/rules/no-empty-static-block.js @@ -15,46 +15,32 @@ const rule = require("../../../lib/rules/no-empty-static-block"), // Tests //------------------------------------------------------------------------------ -const ruleTester = new RuleTester(); +const ruleTester = new RuleTester({ + parserOptions: { ecmaVersion: 2022 } +}); ruleTester.run("no-empty-static-block", rule, { valid: [ - { - code: "class Foo { static { bar(); } }", - parserOptions: { ecmaVersion: 2022 } - }, - { - code: "class Foo { static { /* comments */ } }", - parserOptions: { ecmaVersion: 2022 } - }, - { - code: "class Foo { static {\n// comment\n} }", - parserOptions: { ecmaVersion: 2022 } - }, - { - code: "class Foo { static { bar(); } static { bar(); } }", - parserOptions: { ecmaVersion: 2022 } - } + "class Foo { static { bar(); } }", + "class Foo { static { /* comments */ } }", + "class Foo { static {\n// comment\n} }", + "class Foo { static { bar(); } static { bar(); } }" ], invalid: [ { code: "class Foo { static {} }", - parserOptions: { ecmaVersion: 2022 }, errors: [{ messageId: "unexpected" }] }, { code: "class Foo { static { } }", - parserOptions: { ecmaVersion: 2022 }, errors: [{ messageId: "unexpected" }] }, { code: "class Foo { static { \n\n } }", - parserOptions: { ecmaVersion: 2022 }, errors: [{ messageId: "unexpected" }] }, { code: "class Foo { static { bar(); } static {} }", - parserOptions: { ecmaVersion: 2022 }, errors: [{ messageId: "unexpected" }] } ] From d3fc888a24fed648d847258a0d3a552e3f8730ef Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Mon, 31 Oct 2022 09:08:26 +0900 Subject: [PATCH 07/11] docs: remove options section --- docs/src/rules/no-empty-static-block.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/src/rules/no-empty-static-block.md b/docs/src/rules/no-empty-static-block.md index e6a9e3ce5f4..283a4e21b77 100644 --- a/docs/src/rules/no-empty-static-block.md +++ b/docs/src/rules/no-empty-static-block.md @@ -51,10 +51,6 @@ class Foo { ::: -## Options - -Nothing. - ## When Not To Use It This rule should not be used in environments prior to ES2022. From ff1432917e11e79f000fe85cd5e2b4bacbdf8b9d Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Mon, 31 Oct 2022 09:09:34 +0900 Subject: [PATCH 08/11] fix: `disallows` -> `disallow` --- lib/rules/no-empty-static-block.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rules/no-empty-static-block.js b/lib/rules/no-empty-static-block.js index 3b8b60c38ae..9e7cd3d4b52 100644 --- a/lib/rules/no-empty-static-block.js +++ b/lib/rules/no-empty-static-block.js @@ -20,7 +20,7 @@ module.exports = { type: "suggestion", docs: { - description: "Disallows empty static blocks", + description: "Disallow empty static blocks", recommended: false, url: "https://eslint.org/docs/rules/no-empty-static-block" }, From 59435232aac305614c7ae2d48801f80c8647a94a Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Mon, 31 Oct 2022 09:10:08 +0900 Subject: [PATCH 09/11] fix: remove `loc` parameters --- lib/rules/no-empty-static-block.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/rules/no-empty-static-block.js b/lib/rules/no-empty-static-block.js index 9e7cd3d4b52..ed5c24de618 100644 --- a/lib/rules/no-empty-static-block.js +++ b/lib/rules/no-empty-static-block.js @@ -45,7 +45,6 @@ module.exports = { if (node.body.length === 0 && innerComments.length === 0) { context.report({ node, - loc: node.loc, messageId: "unexpected" }); } From c697d952001eb1de7a0ffcbb00ee8f420582d275 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Mon, 31 Oct 2022 09:56:41 +0900 Subject: [PATCH 10/11] feat: ignore comment that isn't inside block --- lib/rules/no-empty-static-block.js | 13 ++++--------- tests/lib/rules/no-empty-static-block.js | 4 ++++ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/rules/no-empty-static-block.js b/lib/rules/no-empty-static-block.js index ed5c24de618..dd154797e9f 100644 --- a/lib/rules/no-empty-static-block.js +++ b/lib/rules/no-empty-static-block.js @@ -4,12 +4,6 @@ */ "use strict"; -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const astUtils = require("./utils/ast-utils"); - //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -37,10 +31,11 @@ module.exports = { return { StaticBlock(node) { - const innerComments = sourceCode.getTokens(node, { - includeComments: true, - filter: astUtils.isCommentToken + const [blockOpenToken] = sourceCode.getFirstTokens(node, { + filter: token => token.type === "Punctuator" && token.value === "{" }); + const innerComments = + sourceCode.getCommentsInside(node).filter(commentToken => blockOpenToken.range[1] < commentToken.range[0]); if (node.body.length === 0 && innerComments.length === 0) { context.report({ diff --git a/tests/lib/rules/no-empty-static-block.js b/tests/lib/rules/no-empty-static-block.js index 7e7176cc5cf..592c840ff3d 100644 --- a/tests/lib/rules/no-empty-static-block.js +++ b/tests/lib/rules/no-empty-static-block.js @@ -42,6 +42,10 @@ ruleTester.run("no-empty-static-block", rule, { { code: "class Foo { static { bar(); } static {} }", errors: [{ messageId: "unexpected" }] + }, + { + code: "class Foo { static // comment\n {} }", + errors: [{ messageId: "unexpected" }] } ] }); From 8f26be514380d4507baf70c83ddb7682c0846e23 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sat, 5 Nov 2022 03:47:22 +0900 Subject: [PATCH 11/11] fix: address review --- lib/rules/no-empty-static-block.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/rules/no-empty-static-block.js b/lib/rules/no-empty-static-block.js index dd154797e9f..ab710628824 100644 --- a/lib/rules/no-empty-static-block.js +++ b/lib/rules/no-empty-static-block.js @@ -31,17 +31,15 @@ module.exports = { return { StaticBlock(node) { - const [blockOpenToken] = sourceCode.getFirstTokens(node, { - filter: token => token.type === "Punctuator" && token.value === "{" - }); - const innerComments = - sourceCode.getCommentsInside(node).filter(commentToken => blockOpenToken.range[1] < commentToken.range[0]); - - if (node.body.length === 0 && innerComments.length === 0) { - context.report({ - node, - messageId: "unexpected" - }); + if (node.body.length === 0) { + const closingBrace = sourceCode.getLastToken(node); + + if (sourceCode.getCommentsBefore(closingBrace).length === 0) { + context.report({ + node, + messageId: "unexpected" + }); + } } } };