Repository: eslint/eslint
Pull request #15298 (2021-11-12 11:25:05)

feat: update class-methods-use-this for class static blocks
<!--
    Thank you for contributing!

    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

#### Prerequisites checklist

- [x] I have read the [contributing guidelines](https://github.com/eslint/eslint/blob/HEAD/CONTRIBUTING.md).

#### What is the purpose of this pull request? (put an "X" next to an item)

<!--
    The following template is intentionally not a markdown checkbox list for the reasons
    explained in https://github.com/eslint/eslint/pull/12848#issuecomment-580302888
-->

[ ] Documentation update
[ ] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/rule-proposal.md))
[x] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

Refs #15016, fixes `class-methods-use-this`.

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

#### What changes did you make? (Give an overview)

Updated the `class-methods-use-this` rule to account for class static blocks.

This only fixes false negatives where use of `this` in a class static block mistakenly counts as used `this` in the enclosing context:

```js
/* eslint class-methods-use-this: error */

class A {
    foo () { // false negative, this method does not use `this`.
        return class {
            static {
                this;
            }
        } 
    }
}
```

The rule still correctly does not require that class static blocks use `this`.

#### Is there anything you'd like reviewers to focus on?



Patch:
diff --git a/README.md b/README.md
index 1f6df4ce7..d5f156a74 100644
--- a/README.md
+++ b/README.md
@@ -206,6 +206,7 @@ This means:
 These folks keep the project moving and are resources for help.
 
 <!-- NOTE: This section is autogenerated. Do not manually edit.-->
+
 <!--teamstart-->
 
 ### Technical Steering Committee (TSC)
@@ -288,6 +289,7 @@ Nitin Kumar
 
 <!--teamend-->
 
+
 ## <a name="sponsors"></a>Sponsors
 
 The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://opencollective.com/eslint) to get your logo on our README and website.
diff --git a/docs/developer-guide/contributing/pull-requests.md b/docs/developer-guide/contributing/pull-requests.md
index 9c6f62fff..dde1c3144 100644
--- a/docs/developer-guide/contributing/pull-requests.md
+++ b/docs/developer-guide/contributing/pull-requests.md
@@ -64,7 +64,7 @@ The `tag` is one of the following:
 * `fix` - for a bug fix.
 * `feat` - either for a backwards-compatible enhancement or for a rule change that adds reported problems.
 * `fix!` - for a backwards-incompatible bug fix.
-* `feat!:` - for a backwards-incompatible enhancement or feature.
+* `feat!` - for a backwards-incompatible enhancement or feature.
 * `docs` - changes to documentation only.
 * `chore` - for changes that aren't user-facing.
 * `build` - changes to build process only.
diff --git a/docs/rules/block-scoped-var.md b/docs/rules/block-scoped-var.md
index 75c7db025..9c308feb2 100644
--- a/docs/rules/block-scoped-var.md
+++ b/docs/rules/block-scoped-var.md
@@ -41,6 +41,15 @@ function doFor() {
     }
     console.log(y);
 }
+
+class C {
+    static {
+        if (something) {
+            var build = true;
+        }
+        build = false;
+    }
+}
 ```
 
 Examples of **correct** code for this rule:
@@ -85,6 +94,15 @@ function doFor() {
         console.log(y);
     }
 }
+
+class C {
+    static {
+        var build = false;
+        if (something) {
+            build = true;
+        }
+    }
+}
 ```
 
 ## Further Reading
diff --git a/docs/rules/block-spacing.md b/docs/rules/block-spacing.md
index aef7c333c..04c7aeb61 100644
--- a/docs/rules/block-spacing.md
+++ b/docs/rules/block-spacing.md
@@ -23,6 +23,10 @@ if (foo) { bar = 0;}
 function baz() {let i = 0;
     return i;
 }
+
+class C {
+    static {this.bar = 0;}
+}
 ```
 
 Examples of **correct** code for this rule with the default `"always"` option:
@@ -32,6 +36,10 @@ Examples of **correct** code for this rule with the default `"always"` option:
 
 function foo() { return true; }
 if (foo) { bar = 0; }
+
+class C {
+    static { this.bar = 0; }
+}
 ```
 
 ### never
@@ -43,6 +51,10 @@ Examples of **incorrect** code for this rule with the `"never"` option:
 
 function foo() { return true; }
 if (foo) { bar = 0;}
+
+class C {
+    static { this.bar = 0; }
+}
 ```
 
 Examples of **correct** code for this rule with the `"never"` option:
@@ -52,6 +64,10 @@ Examples of **correct** code for this rule with the `"never"` option:
 
 function foo() {return true;}
 if (foo) {bar = 0;}
+
+class C {
+    static {this.bar = 0;}
+}
 ```
 
 ## When Not To Use It
diff --git a/docs/rules/class-methods-use-this.md b/docs/rules/class-methods-use-this.md
index 9d3ca7f19..73efc9dba 100644
--- a/docs/rules/class-methods-use-this.md
+++ b/docs/rules/class-methods-use-this.md
@@ -83,6 +83,10 @@ class A {
     static foo() {
         // OK. static methods aren't expected to use this.
     }
+
+    static {
+        // OK. static blocks are exempt.
+    }
 }
 ```
 
diff --git a/docs/rules/keyword-spacing.md b/docs/rules/keyword-spacing.md
index 0cc952dc9..8ca673937 100644
--- a/docs/rules/keyword-spacing.md
+++ b/docs/rules/keyword-spacing.md
@@ -243,13 +243,14 @@ if(foo) {
 
 ### overrides
 
-Examples of **correct** code for this rule with the `{ "overrides": { "if": { "after": false }, "for": { "after": false }, "while": { "after": false } } }` option:
+Examples of **correct** code for this rule with the `{ "overrides": { "if": { "after": false }, "for": { "after": false }, "while": { "after": false }, "static": { "after": false } } }` option:
 
 ```js
 /*eslint keyword-spacing: ["error", { "overrides": {
   "if": { "after": false },
   "for": { "after": false },
-  "while": { "after": false }
+  "while": { "after": false },
+  "static": { "after": false }
 } }]*/
 
 if(foo) {
@@ -263,7 +264,13 @@ if(foo) {
 for(;;);
 
 while(true) {
-  //...
+    //...
+}
+
+class C {
+    static{
+        //...
+    }
 }
 ```
 
diff --git a/docs/rules/no-extra-semi.md b/docs/rules/no-extra-semi.md
index f4dd8e09c..a33a493c8 100644
--- a/docs/rules/no-extra-semi.md
+++ b/docs/rules/no-extra-semi.md
@@ -17,6 +17,17 @@ function foo() {
     // code
 };
 
+class C {
+    field;;
+
+    method() {
+        // code
+    };
+
+    static {
+        // code
+    };
+};
 ```
 
 Examples of **correct** code for this rule:
@@ -26,10 +37,25 @@ Examples of **correct** code for this rule:
 
 var x = 5;
 
-var foo = function() {
+function foo() {
+    // code
+}
+
+var bar = function() {
     // code
 };
 
+class C {
+    field;
+
+    method() {
+        // code
+    }
+
+    static {
+        // code
+    }
+}
 ```
 
 ## When Not To Use It
diff --git a/docs/rules/no-lone-blocks.md b/docs/rules/no-lone-blocks.md
index 8cb45d635..49fdda6f8 100644
--- a/docs/rules/no-lone-blocks.md
+++ b/docs/rules/no-lone-blocks.md
@@ -42,6 +42,14 @@ function bar() {
     aLabel: {
     }
 }
+
+class C {
+    static {
+        {
+            foo();
+        }
+    }
+}
 ```
 
 Examples of **correct** code for this rule with ES6 environment:
@@ -78,6 +86,18 @@ function bar() {
 
 aLabel: {
 }
+
+class C {
+    static {
+        lbl: {
+            if (something) {
+                break lbl;
+            }
+
+            foo();
+        }
+    }
+}
 ```
 
 Examples of **correct** code for this rule with ES6 environment and strict mode via `"parserOptions": { "sourceType": "module" }` in the ESLint configuration or `"use strict"` directive in the code:
diff --git a/docs/rules/semi.md b/docs/rules/semi.md
index 158cd7f53..cb8e6dd0d 100644
--- a/docs/rules/semi.md
+++ b/docs/rules/semi.md
@@ -172,6 +172,14 @@ Examples of additional **correct** code for this rule with the `"always", { "omi
 if (foo) { bar() }
 
 if (foo) { bar(); baz() }
+
+function f() { bar(); baz() }
+
+class C {
+    foo() { bar(); baz() }
+
+    static { bar(); baz() }
+}
 ```
 
 #### beforeStatementContinuationChars
diff --git a/docs/rules/space-before-blocks.md b/docs/rules/space-before-blocks.md
index 83e9b3d6a..35a4c16c3 100644
--- a/docs/rules/space-before-blocks.md
+++ b/docs/rules/space-before-blocks.md
@@ -63,6 +63,9 @@ if (a) {
     c();
 }
 
+class C {
+    static{} /*no error. this is checked by `keyword-spacing` rule.*/
+}
 
 function a() {}
 
diff --git a/lib/rules/block-scoped-var.js b/lib/rules/block-scoped-var.js
index 10125e61f..d98250b06 100644
--- a/lib/rules/block-scoped-var.js
+++ b/lib/rules/block-scoped-var.js
@@ -112,6 +112,8 @@ module.exports = {
             "SwitchStatement:exit": exitScope,
             CatchClause: enterScope,
             "CatchClause:exit": exitScope,
+            StaticBlock: enterScope,
+            "StaticBlock:exit": exitScope,
 
             // Finds and reports references which are outside of valid scope.
             VariableDeclaration: checkForVariables
diff --git a/lib/rules/block-spacing.js b/lib/rules/block-spacing.js
index 13cfbf0e2..990b441e3 100644
--- a/lib/rules/block-spacing.js
+++ b/lib/rules/block-spacing.js
@@ -40,7 +40,7 @@ module.exports = {
 
         /**
          * Gets the open brace token from a given node.
-         * @param {ASTNode} node A BlockStatement/SwitchStatement node to get.
+         * @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to get.
          * @returns {Token} The token of the open brace.
          */
         function getOpenBrace(node) {
@@ -50,6 +50,12 @@ module.exports = {
                 }
                 return sourceCode.getLastToken(node, 1);
             }
+
+            if (node.type === "StaticBlock") {
+                return sourceCode.getFirstToken(node, { skip: 1 }); // skip the `static` token
+            }
+
+            // "BlockStatement"
             return sourceCode.getFirstToken(node);
         }
 
@@ -72,8 +78,8 @@ module.exports = {
         }
 
         /**
-         * Reports invalid spacing style inside braces.
-         * @param {ASTNode} node A BlockStatement/SwitchStatement node to get.
+         * Checks and reports invalid spacing style inside braces.
+         * @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to check.
          * @returns {void}
          */
         function checkSpacingInsideBraces(node) {
@@ -157,6 +163,7 @@ module.exports = {
 
         return {
             BlockStatement: checkSpacingInsideBraces,
+            StaticBlock: checkSpacingInsideBraces,
             SwitchStatement: checkSpacingInsideBraces
         };
     }
diff --git a/lib/rules/class-methods-use-this.js b/lib/rules/class-methods-use-this.js
index 034ba3abc..beb742d93 100644
--- a/lib/rules/class-methods-use-this.js
+++ b/lib/rules/class-methods-use-this.js
@@ -161,8 +161,17 @@ module.exports = {
             /*
              * Class field value are implicit functions.
              */
-            "PropertyDefinition:exit": popContext,
             "PropertyDefinition > *.key:exit": pushContext,
+            "PropertyDefinition:exit": popContext,
+
+            /*
+             * Class static blocks are implicit functions. They aren't required to use `this`,
+             * but we have to push context so that it captures any use of `this` in the static block
+             * separately from enclosing contexts, because static blocks have their own `this` and it
+             * shouldn't count as used `this` in enclosing contexts.
+             */
+            StaticBlock: pushContext,
+            "StaticBlock:exit": popContext,
 
             ThisExpression: markThisUsed,
             Super: markThisUsed,
diff --git a/lib/rules/keyword-spacing.js b/lib/rules/keyword-spacing.js
index d860ae0f0..44222e1a4 100644
--- a/lib/rules/keyword-spacing.js
+++ b/lib/rules/keyword-spacing.js
@@ -590,6 +590,7 @@ module.exports = {
             ImportNamespaceSpecifier: checkSpacingForImportNamespaceSpecifier,
             MethodDefinition: checkSpacingForProperty,
             PropertyDefinition: checkSpacingForProperty,
+            StaticBlock: checkSpacingAroundFirstToken,
             Property: checkSpacingForProperty,
 
             // To avoid conflicts with `space-infix-ops`, e.g. `a > this.b`
diff --git a/lib/rules/no-extra-semi.js b/lib/rules/no-extra-semi.js
index 952869c3e..0e2bcaf07 100644
--- a/lib/rules/no-extra-semi.js
+++ b/lib/rules/no-extra-semi.js
@@ -116,7 +116,7 @@ module.exports = {
              * @param {Node} node A MethodDefinition node of the start point.
              * @returns {void}
              */
-            "MethodDefinition, PropertyDefinition"(node) {
+            "MethodDefinition, PropertyDefinition, StaticBlock"(node) {
                 checkForPartOfClassBody(sourceCode.getTokenAfter(node));
             }
         };
diff --git a/lib/rules/no-lone-blocks.js b/lib/rules/no-lone-blocks.js
index 5f74cd83c..33d4706a9 100644
--- a/lib/rules/no-lone-blocks.js
+++ b/lib/rules/no-lone-blocks.js
@@ -39,7 +39,9 @@ module.exports = {
          * @returns {void}
          */
         function report(node) {
-            const messageId = node.parent.type === "BlockStatement" ? "redundantNestedBlock" : "redundantBlock";
+            const messageId = node.parent.type === "BlockStatement" || node.parent.type === "StaticBlock"
+                ? "redundantNestedBlock"
+                : "redundantBlock";
 
             context.report({
                 node,
@@ -54,6 +56,7 @@ module.exports = {
          */
         function isLoneBlock(node) {
             return node.parent.type === "BlockStatement" ||
+                node.parent.type === "StaticBlock" ||
                 node.parent.type === "Program" ||
 
                 // Don't report blocks in switch cases if the block is the only statement of the case.
@@ -99,7 +102,10 @@ module.exports = {
                         loneBlocks.pop();
                         report(node);
                     } else if (
-                        node.parent.type === "BlockStatement" &&
+                        (
+                            node.parent.type === "BlockStatement" ||
+                            node.parent.type === "StaticBlock"
+                        ) &&
                         node.parent.body.length === 1
                     ) {
                         report(node);
diff --git a/lib/rules/semi.js b/lib/rules/semi.js
index 4124a8c50..c29029ced 100644
--- a/lib/rules/semi.js
+++ b/lib/rules/semi.js
@@ -306,22 +306,31 @@ module.exports = {
         }
 
         /**
-         * Checks a node to see if it's in a one-liner block statement.
+         * Checks a node to see if it's the last item in a one-liner block.
+         * Block is any `BlockStatement` or `StaticBlock` node. Block is a one-liner if its
+         * braces (and consequently everything between them) are on the same line.
          * @param {ASTNode} node The node to check.
-         * @returns {boolean} whether the node is in a one-liner block statement.
+         * @returns {boolean} whether the node is the last item in a one-liner block.
          */
-        function isOneLinerBlock(node) {
+        function isLastInOneLinerBlock(node) {
             const parent = node.parent;
             const nextToken = sourceCode.getTokenAfter(node);
 
             if (!nextToken || nextToken.value !== "}") {
                 return false;
             }
-            return (
-                !!parent &&
-                parent.type === "BlockStatement" &&
-                parent.loc.start.line === parent.loc.end.line
-            );
+
+            if (parent.type === "BlockStatement") {
+                return parent.loc.start.line === parent.loc.end.line;
+            }
+
+            if (parent.type === "StaticBlock") {
+                const openingBrace = sourceCode.getFirstToken(parent, { skip: 1 }); // skip the `static` token
+
+                return openingBrace.loc.start.line === parent.loc.end.line;
+            }
+
+            return false;
         }
 
         /**
@@ -343,7 +352,7 @@ module.exports = {
                     report(node);
                 }
             } else {
-                const oneLinerBlock = (exceptOneLine && isOneLinerBlock(node));
+                const oneLinerBlock = (exceptOneLine && isLastInOneLinerBlock(node));
 
                 if (isSemi && oneLinerBlock) {
                     report(node, true);


Test patch:
diff --git a/tests/lib/rules/block-scoped-var.js b/tests/lib/rules/block-scoped-var.js
index 596c3ba1c..f401332b1 100644
--- a/tests/lib/rules/block-scoped-var.js
+++ b/tests/lib/rules/block-scoped-var.js
@@ -110,7 +110,15 @@ ruleTester.run("block-scoped-var", rule, {
 
         // https://github.com/eslint/eslint/issues/2967
         "(function () { foo(); })(); function foo() {}",
-        { code: "(function () { foo(); })(); function foo() {}", parserOptions: { ecmaVersion: 6, sourceType: "module" } }
+        { code: "(function () { foo(); })(); function foo() {}", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+
+        { code: "class C { static { var foo; foo; } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo; var foo; } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { if (bar) { foo; } var foo; } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "var foo; class C { static { foo; } } ", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo; } } var foo;", parserOptions: { ecmaVersion: 2022 } },
+        { code: "var foo; class C { static {} [foo]; } ", parserOptions: { ecmaVersion: 2022 } },
+        { code: "foo; class C { static {} } var foo; ", parserOptions: { ecmaVersion: 2022 } }
     ],
     invalid: [
         { code: "function f(){ x; { var x; } }", errors: [{ messageId: "outOfScope", data: { name: "x" }, type: "Identifier" }] },
@@ -165,6 +173,11 @@ ruleTester.run("block-scoped-var", rule, {
                 { messageId: "outOfScope", data: { name: "i" }, type: "Identifier" },
                 { messageId: "outOfScope", data: { name: "i" }, type: "Identifier" }
             ]
+        },
+        {
+            code: "class C { static { if (bar) { var foo; } foo; } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "outOfScope", data: { name: "foo" }, type: "Identifier" }]
         }
     ]
 });
diff --git a/tests/lib/rules/block-spacing.js b/tests/lib/rules/block-spacing.js
index a80d07cc7..0dfef7ed6 100644
--- a/tests/lib/rules/block-spacing.js
+++ b/tests/lib/rules/block-spacing.js
@@ -42,6 +42,9 @@ ruleTester.run("block-spacing", rule, {
         { code: "(() => { bar(); });", parserOptions: { ecmaVersion: 6 } },
         "if (a) { /* comment */ foo(); /* comment */ }",
         "if (a) { //comment\n foo(); }",
+        { code: "class C { static {} }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo; } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { /* comment */foo;/* comment */ } }", parserOptions: { ecmaVersion: 2022 } },
 
         // never
         { code: "{foo();}", options: ["never"] },
@@ -62,7 +65,13 @@ ruleTester.run("block-spacing", rule, {
         { code: "(function() {bar();});", options: ["never"] },
         { code: "(() => {bar();});", options: ["never"], parserOptions: { ecmaVersion: 6 } },
         { code: "if (a) {/* comment */ foo(); /* comment */}", options: ["never"] },
-        { code: "if (a) { //comment\n foo();}", options: ["never"] }
+        { code: "if (a) { //comment\n foo();}", options: ["never"] },
+        { code: "class C { static { } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static {foo;} }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static {/* comment */ foo; /* comment */} }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { // line comment is allowed\n foo;\n} }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static {\nfoo;\n} }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { \n foo; \n } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } }
     ],
 
     invalid: [
@@ -292,6 +301,170 @@ ruleTester.run("block-spacing", rule, {
             ]
         },
 
+        // class static blocks
+        {
+            code: "class C { static {foo; } }",
+            output: "class C { static { foo; } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "missing",
+                    data: {
+                        location: "after",
+                        token: "{"
+                    },
+                    line: 1,
+                    column: 18,
+                    endLine: 1,
+                    endColumn: 19
+                }
+            ]
+        },
+        {
+            code: "class C { static { foo;} }",
+            output: "class C { static { foo; } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "missing",
+                    data: {
+                        location: "before",
+                        token: "}"
+                    },
+                    line: 1,
+                    column: 24,
+                    endLine: 1,
+                    endColumn: 25
+                }
+            ]
+        },
+        {
+            code: "class C { static {foo;} }",
+            output: "class C { static { foo; } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "missing",
+                    data: {
+                        location: "after",
+                        token: "{"
+                    },
+                    line: 1,
+                    column: 18,
+                    endLine: 1,
+                    endColumn: 19
+                },
+                {
+                    type: "StaticBlock",
+                    messageId: "missing",
+                    data: {
+                        location: "before",
+                        token: "}"
+                    },
+                    line: 1,
+                    column: 23,
+                    endLine: 1,
+                    endColumn: 24
+                }
+            ]
+        },
+        {
+            code: "class C { static {/* comment */} }",
+            output: "class C { static { /* comment */ } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "missing",
+                    data: {
+                        location: "after",
+                        token: "{"
+                    },
+                    line: 1,
+                    column: 18,
+                    endLine: 1,
+                    endColumn: 19
+                },
+                {
+                    type: "StaticBlock",
+                    messageId: "missing",
+                    data: {
+                        location: "before",
+                        token: "}"
+                    },
+                    line: 1,
+                    column: 32,
+                    endLine: 1,
+                    endColumn: 33
+                }
+            ]
+        },
+        {
+            code: "class C { static {/* comment 1 */ foo; /* comment 2 */} }",
+            output: "class C { static { /* comment 1 */ foo; /* comment 2 */ } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "missing",
+                    data: {
+                        location: "after",
+                        token: "{"
+                    },
+                    line: 1,
+                    column: 18,
+                    endLine: 1,
+                    endColumn: 19
+                },
+                {
+                    type: "StaticBlock",
+                    messageId: "missing",
+                    data: {
+                        location: "before",
+                        token: "}"
+                    },
+                    line: 1,
+                    column: 55,
+                    endLine: 1,
+                    endColumn: 56
+                }
+            ]
+        },
+        {
+            code: "class C {\n static {foo()\nbar()} }",
+            output: "class C {\n static { foo()\nbar() } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "missing",
+                    data: {
+                        location: "after",
+                        token: "{"
+                    },
+                    line: 2,
+                    column: 9,
+                    endLine: 2,
+                    endColumn: 10
+                },
+                {
+                    type: "StaticBlock",
+                    messageId: "missing",
+                    data: {
+                        location: "before",
+                        token: "}"
+                    },
+                    line: 3,
+                    column: 6,
+                    endLine: 3,
+                    endColumn: 7
+                }
+            ]
+        },
+
         //----------------------------------------------------------------------
         // never
         {
@@ -817,6 +990,176 @@ ruleTester.run("block-spacing", rule, {
                     endColumn: 21
                 }
             ]
+        },
+
+        // class static blocks
+        {
+            code: "class C { static { foo;} }",
+            output: "class C { static {foo;} }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "extra",
+                    data: {
+                        location: "after",
+                        token: "{"
+                    },
+                    line: 1,
+                    column: 19,
+                    endLine: 1,
+                    endColumn: 20
+                }
+            ]
+        },
+        {
+            code: "class C { static {foo; } }",
+            output: "class C { static {foo;} }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "extra",
+                    data: {
+                        location: "before",
+                        token: "}"
+                    },
+                    line: 1,
+                    column: 23,
+                    endLine: 1,
+                    endColumn: 24
+                }
+            ]
+        },
+        {
+            code: "class C { static { foo; } }",
+            output: "class C { static {foo;} }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "extra",
+                    data: {
+                        location: "after",
+                        token: "{"
+                    },
+                    line: 1,
+                    column: 19,
+                    endLine: 1,
+                    endColumn: 20
+                },
+                {
+                    type: "StaticBlock",
+                    messageId: "extra",
+                    data: {
+                        location: "before",
+                        token: "}"
+                    },
+                    line: 1,
+                    column: 24,
+                    endLine: 1,
+                    endColumn: 25
+                }
+            ]
+        },
+        {
+            code: "class C { static { /* comment */ } }",
+            output: "class C { static {/* comment */} }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "extra",
+                    data: {
+                        location: "after",
+                        token: "{"
+                    },
+                    line: 1,
+                    column: 19,
+                    endLine: 1,
+                    endColumn: 20
+                },
+                {
+                    type: "StaticBlock",
+                    messageId: "extra",
+                    data: {
+                        location: "before",
+                        token: "}"
+                    },
+                    line: 1,
+                    column: 33,
+                    endLine: 1,
+                    endColumn: 34
+                }
+            ]
+        },
+        {
+            code: "class C { static { /* comment 1 */ foo; /* comment 2 */ } }",
+            output: "class C { static {/* comment 1 */ foo; /* comment 2 */} }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "extra",
+                    data: {
+                        location: "after",
+                        token: "{"
+                    },
+                    line: 1,
+                    column: 19,
+                    endLine: 1,
+                    endColumn: 20
+                },
+                {
+                    type: "StaticBlock",
+                    messageId: "extra",
+                    data: {
+                        location: "before",
+                        token: "}"
+                    },
+                    line: 1,
+                    column: 56,
+                    endLine: 1,
+                    endColumn: 57
+                }
+            ]
+        },
+        {
+            code: "class C { static\n{   foo()\nbar()  } }",
+            output: "class C { static\n{foo()\nbar()} }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    type: "StaticBlock",
+                    messageId: "extra",
+                    data: {
+                        location: "after",
+                        token: "{"
+                    },
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 5
+                },
+                {
+                    type: "StaticBlock",
+                    messageId: "extra",
+                    data: {
+                        location: "before",
+                        token: "}"
+                    },
+                    line: 3,
+                    column: 6,
+                    endLine: 3,
+                    endColumn: 8
+                }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/class-methods-use-this.js b/tests/lib/rules/class-methods-use-this.js
index 95c1a6f64..eeb122f75 100644
--- a/tests/lib/rules/class-methods-use-this.js
+++ b/tests/lib/rules/class-methods-use-this.js
@@ -41,7 +41,8 @@ ruleTester.run("class-methods-use-this", rule, {
         { code: "class A { #bar() {} }", options: [{ exceptMethods: ["#bar"] }], parserOptions: { ecmaVersion: 2022 } },
         { code: "class A { foo = function () {} }", options: [{ enforceForClassFields: false }], parserOptions: { ecmaVersion: 2022 } },
         { code: "class A { foo = () => {} }", options: [{ enforceForClassFields: false }], parserOptions: { ecmaVersion: 2022 } },
-        { code: "class A { foo() { return class { [this.foo] = 1 }; } }", parserOptions: { ecmaVersion: 2022 } }
+        { code: "class A { foo() { return class { [this.foo] = 1 }; } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class A { static {} }", parserOptions: { ecmaVersion: 2022 } }
     ],
     invalid: [
         {
@@ -203,6 +204,13 @@ ruleTester.run("class-methods-use-this", rule, {
             errors: [
                 { messageId: "missingThis", data: { name: "method 'foo'" }, column: 11, endColumn: 15 }
             ]
+        },
+        {
+            code: "class A { foo () { return class { static { this; } } } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                { messageId: "missingThis", data: { name: "method 'foo'" }, column: 11, endColumn: 15 }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/keyword-spacing.js b/tests/lib/rules/keyword-spacing.js
index 05e58d7e1..35c8a06e4 100644
--- a/tests/lib/rules/keyword-spacing.js
+++ b/tests/lib/rules/keyword-spacing.js
@@ -978,6 +978,11 @@ ruleTester.run("keyword-spacing", rule, {
         { code: "class A { a;static[b]; }", options: [NEITHER], parserOptions: { ecmaVersion: 2022 } },
         { code: "class A { a; static #b; }", parserOptions: { ecmaVersion: 2022 } },
         { code: "class A { a;static#b; }", options: [NEITHER], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class A { a() {} static {} }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class A { a() {}static{} }", options: [NEITHER], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class A { a() {} static {} }", options: [override("static", BOTH)], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class A { a() {}static{} }", options: [override("static", NEITHER)], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class A { a() {}\nstatic\n{} }", options: [NEITHER], parserOptions: { ecmaVersion: 2022 } },
 
         // not conflict with `generator-star-spacing`
         { code: "class A { static* [a]() {} }", parserOptions: { ecmaVersion: 6 } },
@@ -986,6 +991,10 @@ ruleTester.run("keyword-spacing", rule, {
         // not conflict with `semi-spacing`
         { code: "class A { ;static a() {} }", parserOptions: { ecmaVersion: 6 } },
         { code: "class A { ; static a() {} }", options: [NEITHER], parserOptions: { ecmaVersion: 6 } },
+        { code: "class A { ;static a; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class A { ; static a ; }", options: [NEITHER], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class A { ;static {} }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class A { ; static{} }", options: [NEITHER], parserOptions: { ecmaVersion: 2022 } },
 
         //----------------------------------------------------------------------
         // super
@@ -3043,6 +3052,59 @@ ruleTester.run("keyword-spacing", rule, {
             parserOptions: { ecmaVersion: 2022 },
             errors: unexpectedAfter("static")
         },
+        {
+            code: "class A { a() {}static{} }",
+            output: "class A { a() {} static {} }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: expectedBeforeAndAfter("static")
+        },
+        {
+            code: "class A { a() {}static{} }",
+            output: "class A { a() {} static {} }",
+            options: [override("static", BOTH)],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: expectedBeforeAndAfter("static")
+        },
+        {
+            code: "class A {  a() {}static {} }",
+            output: "class A {  a() {} static {} }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: expectedBefore("static")
+        },
+        {
+            code: "class A {  a() {} static{} }",
+            output: "class A {  a() {} static {} }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: expectedAfter("static")
+        },
+        {
+            code: "class A { a() {} static {} }",
+            output: "class A { a() {}static{} }",
+            options: [NEITHER],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: unexpectedBeforeAndAfter("static")
+        },
+        {
+            code: "class A { a() {} static {} }",
+            output: "class A { a() {}static{} }",
+            options: [override("static", NEITHER)],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: unexpectedBeforeAndAfter("static")
+        },
+        {
+            code: "class A { a() {} static{} }",
+            output: "class A { a() {}static{} }",
+            options: [NEITHER],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: unexpectedBefore("static")
+        },
+        {
+            code: "class A { a() {}static {} }",
+            output: "class A { a() {}static{} }",
+            options: [NEITHER],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: unexpectedAfter("static")
+        },
 
         //----------------------------------------------------------------------
         // super
diff --git a/tests/lib/rules/no-extra-semi.js b/tests/lib/rules/no-extra-semi.js
index 838925e8c..4f19fb722 100644
--- a/tests/lib/rules/no-extra-semi.js
+++ b/tests/lib/rules/no-extra-semi.js
@@ -40,6 +40,7 @@ ruleTester.run("no-extra-semi", rule, {
         { code: "class A { } a;", parserOptions: { ecmaVersion: 6 } },
         { code: "class A { field; }", parserOptions: { ecmaVersion: 2022 } },
         { code: "class A { field = 0; }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class A { static { foo; } }", parserOptions: { ecmaVersion: 2022 } },
 
         // modules
         { code: "export const x = 42;", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
@@ -112,6 +113,18 @@ ruleTester.run("no-extra-semi", rule, {
             output: "with(foo){}",
             errors: [{ messageId: "unexpected", type: "EmptyStatement" }]
         },
+        {
+            code: "class A { static { ; } }",
+            output: "class A { static {  } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "unexpected", type: "EmptyStatement", column: 20 }]
+        },
+        {
+            code: "class A { static { a;; } }",
+            output: "class A { static { a; } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "unexpected", type: "EmptyStatement", column: 22 }]
+        },
 
         // Class body.
         {
@@ -165,6 +178,18 @@ ruleTester.run("no-extra-semi", rule, {
             output: "class A { field; }",
             parserOptions: { ecmaVersion: 2022 },
             errors: [{ messageId: "unexpected", type: "Punctuator", column: 17 }]
+        },
+        {
+            code: "class A { static {}; }",
+            output: "class A { static {} }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "unexpected", type: "Punctuator", column: 20 }]
+        },
+        {
+            code: "class A { static { a; }; foo(){} }",
+            output: "class A { static { a; } foo(){} }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "unexpected", type: "Punctuator", column: 24 }]
         }
     ]
 });
diff --git a/tests/lib/rules/no-lone-blocks.js b/tests/lib/rules/no-lone-blocks.js
index d9ea851d4..ab81caf8e 100644
--- a/tests/lib/rules/no-lone-blocks.js
+++ b/tests/lib/rules/no-lone-blocks.js
@@ -57,7 +57,16 @@ ruleTester.run("no-lone-blocks", rule, {
             }
           }
         `,
-        { code: "function foo() { { const x = 4 } const x = 3 }", parserOptions: { ecmaVersion: 6 } }
+        { code: "function foo() { { const x = 4 } const x = 3 }", parserOptions: { ecmaVersion: 6 } },
+
+        { code: "class C { static {} }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo; } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { if (foo) { block; } } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { lbl: { block; } } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { { let block; } something; } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { something; { const block = 1; } } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { { function block(){} } something; } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { something; { class block {}  } } }", parserOptions: { ecmaVersion: 2022 } }
     ],
     invalid: [
         {
@@ -235,6 +244,202 @@ ruleTester.run("no-lone-blocks", rule, {
                 type: "BlockStatement",
                 line: 3
             }]
+        },
+        {
+            code: `
+              class C {
+                static {
+                  if (foo) {
+                    {
+                        let block;
+                    }
+                  }
+                }
+              }
+            `,
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "redundantNestedBlock",
+                type: "BlockStatement",
+                line: 5
+            }]
+        },
+        {
+            code: `
+              class C {
+                static {
+                  if (foo) {
+                    {
+                        block;
+                    }
+                    something;
+                  }
+                }
+              }
+            `,
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "redundantNestedBlock",
+                type: "BlockStatement",
+                line: 5
+            }]
+        },
+        {
+            code: `
+              class C {
+                static {
+                  {
+                    block;
+                  }
+                }
+              }
+            `,
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "redundantNestedBlock",
+                type: "BlockStatement",
+                line: 4
+            }]
+        },
+        {
+            code: `
+              class C {
+                static {
+                  {
+                    let block;
+                  }
+                }
+              }
+            `,
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "redundantNestedBlock",
+                type: "BlockStatement",
+                line: 4
+            }]
+        },
+        {
+            code: `
+              class C {
+                static {
+                  {
+                    const block = 1;
+                  }
+                }
+              }
+            `,
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "redundantNestedBlock",
+                type: "BlockStatement",
+                line: 4
+            }]
+        },
+        {
+            code: `
+              class C {
+                static {
+                  {
+                    function block() {}
+                  }
+                }
+              }
+            `,
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "redundantNestedBlock",
+                type: "BlockStatement",
+                line: 4
+            }]
+        },
+        {
+            code: `
+              class C {
+                static {
+                  {
+                    class block {}
+                  }
+                }
+              }
+            `,
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "redundantNestedBlock",
+                type: "BlockStatement",
+                line: 4
+            }]
+        },
+        {
+            code: `
+              class C {
+                static {
+                  {
+                    var block;
+                  }
+                  something;
+                }
+              }
+            `,
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "redundantNestedBlock",
+                type: "BlockStatement",
+                line: 4
+            }]
+        },
+        {
+            code: `
+              class C {
+                static {
+                  something;
+                  {
+                    var block;
+                  }
+                }
+              }
+            `,
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "redundantNestedBlock",
+                type: "BlockStatement",
+                line: 5
+            }]
+        },
+        {
+            code: `
+              class C {
+                static {
+                  {
+                    block;
+                  }
+                  something;
+                }
+              }
+            `,
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "redundantNestedBlock",
+                type: "BlockStatement",
+                line: 4
+            }]
+        },
+        {
+            code: `
+              class C {
+                static {
+                  something;
+                  {
+                    block;
+                  }
+                }
+              }
+            `,
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "redundantNestedBlock",
+                type: "BlockStatement",
+                line: 5
+            }]
         }
     ]
 });
diff --git a/tests/lib/rules/semi-spacing.js b/tests/lib/rules/semi-spacing.js
index c9cccddd5..ffd67854a 100644
--- a/tests/lib/rules/semi-spacing.js
+++ b/tests/lib/rules/semi-spacing.js
@@ -483,6 +483,19 @@ ruleTester.run("semi-spacing", rule, {
                     endColumn: 16
                 }
             ]
+        },
+        {
+            code: "class C { foo;static {}}",
+            output: "class C { foo; static {}}",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "missingWhitespaceAfter",
+                type: "PropertyDefinition",
+                line: 1,
+                column: 14,
+                endLine: 1,
+                endColumn: 15
+            }]
         }
     ]
 });
diff --git a/tests/lib/rules/semi.js b/tests/lib/rules/semi.js
index bc00079d8..d87382182 100644
--- a/tests/lib/rules/semi.js
+++ b/tests/lib/rules/semi.js
@@ -48,14 +48,73 @@ ruleTester.run("semi", rule, {
         { code: "for (let thing of {}) {\n  console.log(thing);\n}", parserOptions: { ecmaVersion: 6 } },
         { code: "do{}while(true)", options: ["never"] },
         { code: "do{}while(true);", options: ["always"] },
+        { code: "class C { static {} }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static {} }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo(); } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo(); } }", options: ["always"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo(); bar(); } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo(); bar(); baz();} }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo() } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo()\nbar() } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo()\nbar()\nbaz() } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo(); bar() } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo();\n (a) } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo()\n ;(a) } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo();\n [a] } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo()\n ;[a] } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo();\n +a } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo()\n ;+a } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo();\n -a } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo()\n ;-a } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo();\n /a/ } }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C { static { foo()\n ;/a/} }", options: ["never"], parserOptions: { ecmaVersion: 2022 } },
+        {
+            code: "class C { static { foo();\n (a) } }",
+            options: ["never", { beforeStatementContinuationChars: "never" }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static { do ; while (foo)\n (a)} }",
+            options: ["never", { beforeStatementContinuationChars: "never" }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "class C { static { do ; while (foo)\n ;(a)} }",
+            options: ["never", { beforeStatementContinuationChars: "always" }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
 
+        // omitLastInOneLineBlock: true
         { code: "if (foo) { bar() }", options: ["always", { omitLastInOneLineBlock: true }] },
         { code: "if (foo) { bar(); baz() }", options: ["always", { omitLastInOneLineBlock: true }] },
+        { code: "if (foo)\n{ bar(); baz() }", options: ["always", { omitLastInOneLineBlock: true }] },
+        { code: "if (foo) {\n bar(); baz(); }", options: ["always", { omitLastInOneLineBlock: true }] },
+        { code: "if (foo) { bar(); baz(); \n}", options: ["always", { omitLastInOneLineBlock: true }] },
+        { code: "function foo() { bar(); baz() }", options: ["always", { omitLastInOneLineBlock: true }] },
+        { code: "function foo()\n{ bar(); baz() }", options: ["always", { omitLastInOneLineBlock: true }] },
+        { code: "function foo(){\n bar(); baz(); }", options: ["always", { omitLastInOneLineBlock: true }] },
+        { code: "function foo(){ bar(); baz(); \n}", options: ["always", { omitLastInOneLineBlock: true }] },
+        { code: "() => { bar(); baz() };", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "() =>\n { bar(); baz() };", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "() => {\n bar(); baz(); };", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "() => { bar(); baz(); \n};", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const obj = { method() { bar(); baz() } };", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const obj = { method()\n { bar(); baz() } };", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const obj = { method() {\n bar(); baz(); } };", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const obj = { method() { bar(); baz(); \n} };", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "class C {\n method() { bar(); baz() } \n}", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "class C {\n method()\n { bar(); baz() } \n}", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "class C {\n method() {\n bar(); baz(); } \n}", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "class C {\n method() { bar(); baz(); \n} \n}", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "class C {\n static { bar(); baz() } \n}", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C {\n static\n { bar(); baz() } \n}", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C {\n static {\n bar(); baz(); } \n}", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 2022 } },
+        { code: "class C {\n static { bar(); baz(); \n} \n}", options: ["always", { omitLastInOneLineBlock: true }], parserOptions: { ecmaVersion: 2022 } },
 
-
-        // method definitions don't have a semicolon.
+        // method definitions and static blocks don't have a semicolon.
         { code: "class A { a() {} b() {} }", parserOptions: { ecmaVersion: 6 } },
         { code: "var A = class { a() {} b() {} };", parserOptions: { ecmaVersion: 6 } },
+        { code: "class A { static {} }", parserOptions: { ecmaVersion: 2022 } },
 
         { code: "import theDefault, { named1, named2 } from 'src/mylib';", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "import theDefault, { named1, named2 } from 'src/mylib'", options: ["never"], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
@@ -311,6 +370,11 @@ ruleTester.run("semi", rule, {
             options: ["never"],
             parserOptions: { ecmaVersion: 2022 }
         },
+        {
+            code: "class C { static {}; }", // no-extra-semi reports it
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 }
+        },
         {
             code: "class C { a=b;\n*foo() {} }",
             options: ["never"],
@@ -990,7 +1054,158 @@ ruleTester.run("semi", rule, {
                 endColumn: 17
             }]
         },
+        {
+            code: "class C { static { foo() } }",
+            output: "class C { static { foo(); } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "missingSemi",
+                type: "ExpressionStatement",
+                line: 1,
+                column: 25,
+                endLine: 1,
+                endColumn: 26
+            }]
+        },
+        {
+            code: "class C { static { foo() } }",
+            output: "class C { static { foo(); } }",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "missingSemi",
+                type: "ExpressionStatement",
+                line: 1,
+                column: 25,
+                endLine: 1,
+                endColumn: 26
+            }]
+        },
+        {
+            code: "class C { static { foo(); bar() } }",
+            output: "class C { static { foo(); bar(); } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "missingSemi",
+                type: "ExpressionStatement",
+                line: 1,
+                column: 32,
+                endLine: 1,
+                endColumn: 33
+            }]
+        },
+        {
+            code: "class C { static { foo()\nbar(); } }",
+            output: "class C { static { foo();\nbar(); } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "missingSemi",
+                type: "ExpressionStatement",
+                line: 1,
+                column: 25,
+                endLine: 2,
+                endColumn: 1
+            }]
+        },
+        {
+            code: "class C { static { foo(); bar()\nbaz(); } }",
+            output: "class C { static { foo(); bar();\nbaz(); } }",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "missingSemi",
+                type: "ExpressionStatement",
+                line: 1,
+                column: 32,
+                endLine: 2,
+                endColumn: 1
+            }]
+        },
+        {
+            code: "class C { static { foo(); } }",
+            output: "class C { static { foo() } }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "extraSemi",
+                type: "ExpressionStatement",
+                line: 1,
+                column: 25,
+                endLine: 1,
+                endColumn: 26
+            }]
+        },
+        {
+            code: "class C { static { foo();\nbar() } }",
+            output: "class C { static { foo()\nbar() } }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "extraSemi",
+                type: "ExpressionStatement",
+                line: 1,
+                column: 25,
+                endLine: 1,
+                endColumn: 26
+            }]
+        },
+        {
+            code: "class C { static { foo()\nbar(); } }",
+            output: "class C { static { foo()\nbar() } }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "extraSemi",
+                type: "ExpressionStatement",
+                line: 2,
+                column: 6,
+                endLine: 2,
+                endColumn: 7
+            }]
+        },
+        {
+            code: "class C { static { foo()\nbar();\nbaz() } }",
+            output: "class C { static { foo()\nbar()\nbaz() } }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "extraSemi",
+                type: "ExpressionStatement",
+                line: 2,
+                column: 6,
+                endLine: 2,
+                endColumn: 7
+            }]
+        },
+        {
+            code: "class C { static { do ; while (foo)\n (a)} }",
+            output: "class C { static { do ; while (foo);\n (a)} }",
+            options: ["never", { beforeStatementContinuationChars: "always" }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "missingSemi",
+                type: "DoWhileStatement",
+                line: 1,
+                column: 36,
+                endLine: 2,
+                endColumn: 1
+            }]
+        },
+        {
+            code: "class C { static { do ; while (foo)\n ;(a)} }",
+            output: "class C { static { do ; while (foo)\n (a)} }",
+            options: ["never", { beforeStatementContinuationChars: "never" }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "extraSemi",
+                type: "DoWhileStatement",
+                line: 2,
+                column: 2,
+                endLine: 2,
+                endColumn: 3
+            }]
+        },
 
+        // omitLastInOneLineBlock: true
         {
             code: "if (foo) { bar()\n }",
             output: "if (foo) { bar();\n }",
@@ -1039,6 +1254,158 @@ ruleTester.run("semi", rule, {
                 endColumn: 18
             }]
         },
+        {
+            code: "function foo() { bar(); baz(); }",
+            output: "function foo() { bar(); baz() }",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            errors: [{
+                messageId: "extraSemi",
+                line: 1,
+                column: 30,
+                endLine: 1,
+                endColumn: 31
+            }]
+        },
+        {
+            code: "function foo()\n{ bar(); baz(); }",
+            output: "function foo()\n{ bar(); baz() }",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            errors: [{
+                messageId: "extraSemi",
+                line: 2,
+                column: 15,
+                endLine: 2,
+                endColumn: 16
+            }]
+        },
+        {
+            code: "function foo() {\n bar(); baz() }",
+            output: "function foo() {\n bar(); baz(); }",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            errors: [{
+                messageId: "missingSemi",
+                line: 2,
+                column: 14,
+                endLine: 2,
+                endColumn: 15
+            }]
+        },
+        {
+            code: "function foo() { bar(); baz() \n}",
+            output: "function foo() { bar(); baz(); \n}",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            errors: [{
+                messageId: "missingSemi",
+                line: 1,
+                column: 30,
+                endLine: 1,
+                endColumn: 31
+            }]
+        },
+        {
+            code: "class C {\nfoo() { bar(); baz(); }\n}",
+            output: "class C {\nfoo() { bar(); baz() }\n}",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "extraSemi",
+                line: 2,
+                column: 21,
+                endLine: 2,
+                endColumn: 22
+            }]
+        },
+        {
+            code: "class C {\nfoo() \n{ bar(); baz(); }\n}",
+            output: "class C {\nfoo() \n{ bar(); baz() }\n}",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "extraSemi",
+                line: 3,
+                column: 15,
+                endLine: 3,
+                endColumn: 16
+            }]
+        },
+        {
+            code: "class C {\nfoo() {\n bar(); baz() }\n}",
+            output: "class C {\nfoo() {\n bar(); baz(); }\n}",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "missingSemi",
+                line: 3,
+                column: 14,
+                endLine: 3,
+                endColumn: 15
+            }]
+        },
+        {
+            code: "class C {\nfoo() { bar(); baz() \n}\n}",
+            output: "class C {\nfoo() { bar(); baz(); \n}\n}",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "missingSemi",
+                line: 2,
+                column: 21,
+                endLine: 2,
+                endColumn: 22
+            }]
+        },
+        {
+            code: "class C {\nstatic { bar(); baz(); }\n}",
+            output: "class C {\nstatic { bar(); baz() }\n}",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "extraSemi",
+                line: 2,
+                column: 22,
+                endLine: 2,
+                endColumn: 23
+            }]
+        },
+        {
+            code: "class C {\nstatic \n{ bar(); baz(); }\n}",
+            output: "class C {\nstatic \n{ bar(); baz() }\n}",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "extraSemi",
+                line: 3,
+                column: 15,
+                endLine: 3,
+                endColumn: 16
+            }]
+        },
+        {
+            code: "class C {\nstatic {\n bar(); baz() }\n}",
+            output: "class C {\nstatic {\n bar(); baz(); }\n}",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "missingSemi",
+                line: 3,
+                column: 14,
+                endLine: 3,
+                endColumn: 15
+            }]
+        },
+        {
+            code: "class C {\nfoo() { bar(); baz() \n}\n}",
+            output: "class C {\nfoo() { bar(); baz(); \n}\n}",
+            options: ["always", { omitLastInOneLineBlock: true }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{
+                messageId: "missingSemi",
+                line: 2,
+                column: 21,
+                endLine: 2,
+                endColumn: 22
+            }]
+        },
 
 
         // exports, "always"
diff --git a/tests/lib/rules/space-before-blocks.js b/tests/lib/rules/space-before-blocks.js
index 79961dd4d..49af96116 100644
--- a/tests/lib/rules/space-before-blocks.js
+++ b/tests/lib/rules/space-before-blocks.js
@@ -202,7 +202,19 @@ ruleTester.run("space-before-blocks", rule, {
         { code: "switch(x) { case (9):{ break; } }", options: alwaysArgs },
         { code: "switch(x){ case (9): { break; } }", options: neverArgs },
         { code: "switch(x) { default:{ break; } }", options: alwaysArgs },
-        { code: "switch(x){ default: { break; } }", options: neverArgs }
+        { code: "switch(x){ default: { break; } }", options: neverArgs },
+
+        // not conflict with `keyword-spacing`
+        {
+            code: "(class{ static{} })",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "(class { static {} })",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 }
+        }
     ],
     invalid: [
         {