Skip to content

Commit

Permalink
fix: update semi-style for class static blocks (#15309)
Browse files Browse the repository at this point in the history
Fixes false positive in the `semi-style` rule: the last statement in a class static block should be allowed to have its semicolon on the same line when the option is `first`.

Refs #15016
  • Loading branch information
mdjermanovic committed Nov 21, 2021
1 parent ddd01dc commit 479a4cb
Show file tree
Hide file tree
Showing 3 changed files with 282 additions and 2 deletions.
28 changes: 28 additions & 0 deletions docs/rules/semi-style.md
Expand Up @@ -32,6 +32,13 @@ for (
) {
foo()
}

class C {
static {
foo()
;bar()
}
}
```

Examples of **correct** code for this rule with `"last"` option:
Expand All @@ -49,6 +56,13 @@ for (
) {
foo()
}

class C {
static {
foo();
bar()
}
}
```

Examples of **incorrect** code for this rule with `"first"` option:
Expand All @@ -66,6 +80,13 @@ for (
) {
foo()
}

class C {
static {
foo();
bar()
}
}
```

Examples of **correct** code for this rule with `"first"` option:
Expand All @@ -83,6 +104,13 @@ for (
) {
foo()
}

class C {
static {
foo()
;bar()
}
}
```

## When Not To Use It
Expand Down
10 changes: 8 additions & 2 deletions lib/rules/semi-style.js
Expand Up @@ -25,15 +25,21 @@ const SELECTOR = [

/**
* Get the child node list of a given node.
* This returns `Program#body`, `BlockStatement#body`, or `SwitchCase#consequent`.
* This returns `BlockStatement#body`, `StaticBlock#body`, `Program#body`,
* `ClassBody#body`, or `SwitchCase#consequent`.
* This is used to check whether a node is the first/last child.
* @param {Node} node A node to get child node list.
* @returns {Node[]|null} The child node list.
*/
function getChildren(node) {
const t = node.type;

if (t === "BlockStatement" || t === "Program" || t === "ClassBody") {
if (
t === "BlockStatement" ||
t === "StaticBlock" ||
t === "Program" ||
t === "ClassBody"
) {
return node.body;
}
if (t === "SwitchCase") {
Expand Down
246 changes: 246 additions & 0 deletions tests/lib/rules/semi-style.js
Expand Up @@ -127,6 +127,202 @@ ruleTester.run("semi-style", rule, {
while (a)
`,
options: ["last"]
},

// Class static blocks
{
code: `
class C {
static {}
}
`,
options: ["last"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo
}
}
`,
options: ["last"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo
bar
}
}
`,
options: ["last"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
;
}
}
`,
options: ["last"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo;
}
}
`,
options: ["last"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo;
bar;
}
}
`,
options: ["last"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo;
bar;
baz;
}
}
`,
options: ["last"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {}
}
`,
options: ["first"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo
}
}
`,
options: ["first"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo
bar
}
}
`,
options: ["first"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
;
}
}
`,
options: ["first"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
;foo
}
}
`,
options: ["first"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo;
}
}
`,
options: ["first"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo
;bar
}
}
`,
options: ["first"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo
;bar;
}
}
`,
options: ["first"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo
;bar
;baz
}
}
`,
options: ["first"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: `
class C {
static {
foo
;bar
;baz;
}
}
`,
options: ["first"],
parserOptions: { ecmaVersion: 2022 }
}
],
invalid: [
Expand Down Expand Up @@ -414,6 +610,56 @@ ruleTester.run("semi-style", rule, {
pos: "the beginning of the next line"
}
}]
},

// Class static blocks
{
code: "class C { static { foo\n; } }",
output: "class C { static { foo;\n} }",
options: ["last"],
parserOptions: { ecmaVersion: 2022 },
errors: [{
messageId: "expectedSemiColon",
data: {
pos: "the end of the previous line"
}
}]
},
{
code: "class C { static { foo\n ;bar } }",
output: "class C { static { foo;\nbar } }",
options: ["last"],
parserOptions: { ecmaVersion: 2022 },
errors: [{
messageId: "expectedSemiColon",
data: {
pos: "the end of the previous line"
}
}]
},
{
code: "class C { static { foo;\nbar\n ; } }",
output: "class C { static { foo;\nbar;\n} }",
options: ["last"],
parserOptions: { ecmaVersion: 2022 },
errors: [{
messageId: "expectedSemiColon",
data: {
pos: "the end of the previous line"
}
}]
},
{
code: "class C { static { foo;\nbar } }",
output: "class C { static { foo\n;bar } }",
options: ["first"],
parserOptions: { ecmaVersion: 2022 },
errors: [{
messageId: "expectedSemiColon",
data: {
pos: "the beginning of the next line"
}
}]
}
]
});

0 comments on commit 479a4cb

Please sign in to comment.