Skip to content

Commit 479a4cb

Browse files
authored
fix: update semi-style for class static blocks (#15309)
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
1 parent ddd01dc commit 479a4cb

File tree

3 files changed

+282
-2
lines changed

3 files changed

+282
-2
lines changed

docs/rules/semi-style.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ for (
3232
) {
3333
foo()
3434
}
35+
36+
class C {
37+
static {
38+
foo()
39+
;bar()
40+
}
41+
}
3542
```
3643

3744
Examples of **correct** code for this rule with `"last"` option:
@@ -49,6 +56,13 @@ for (
4956
) {
5057
foo()
5158
}
59+
60+
class C {
61+
static {
62+
foo();
63+
bar()
64+
}
65+
}
5266
```
5367

5468
Examples of **incorrect** code for this rule with `"first"` option:
@@ -66,6 +80,13 @@ for (
6680
) {
6781
foo()
6882
}
83+
84+
class C {
85+
static {
86+
foo();
87+
bar()
88+
}
89+
}
6990
```
7091

7192
Examples of **correct** code for this rule with `"first"` option:
@@ -83,6 +104,13 @@ for (
83104
) {
84105
foo()
85106
}
107+
108+
class C {
109+
static {
110+
foo()
111+
;bar()
112+
}
113+
}
86114
```
87115

88116
## When Not To Use It

lib/rules/semi-style.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,21 @@ const SELECTOR = [
2525

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

36-
if (t === "BlockStatement" || t === "Program" || t === "ClassBody") {
37+
if (
38+
t === "BlockStatement" ||
39+
t === "StaticBlock" ||
40+
t === "Program" ||
41+
t === "ClassBody"
42+
) {
3743
return node.body;
3844
}
3945
if (t === "SwitchCase") {

tests/lib/rules/semi-style.js

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,202 @@ ruleTester.run("semi-style", rule, {
127127
while (a)
128128
`,
129129
options: ["last"]
130+
},
131+
132+
// Class static blocks
133+
{
134+
code: `
135+
class C {
136+
static {}
137+
}
138+
`,
139+
options: ["last"],
140+
parserOptions: { ecmaVersion: 2022 }
141+
},
142+
{
143+
code: `
144+
class C {
145+
static {
146+
foo
147+
}
148+
}
149+
`,
150+
options: ["last"],
151+
parserOptions: { ecmaVersion: 2022 }
152+
},
153+
{
154+
code: `
155+
class C {
156+
static {
157+
foo
158+
bar
159+
}
160+
}
161+
`,
162+
options: ["last"],
163+
parserOptions: { ecmaVersion: 2022 }
164+
},
165+
{
166+
code: `
167+
class C {
168+
static {
169+
;
170+
}
171+
}
172+
`,
173+
options: ["last"],
174+
parserOptions: { ecmaVersion: 2022 }
175+
},
176+
{
177+
code: `
178+
class C {
179+
static {
180+
foo;
181+
}
182+
}
183+
`,
184+
options: ["last"],
185+
parserOptions: { ecmaVersion: 2022 }
186+
},
187+
{
188+
code: `
189+
class C {
190+
static {
191+
foo;
192+
bar;
193+
}
194+
}
195+
`,
196+
options: ["last"],
197+
parserOptions: { ecmaVersion: 2022 }
198+
},
199+
{
200+
code: `
201+
class C {
202+
static {
203+
foo;
204+
bar;
205+
baz;
206+
}
207+
}
208+
`,
209+
options: ["last"],
210+
parserOptions: { ecmaVersion: 2022 }
211+
},
212+
{
213+
code: `
214+
class C {
215+
static {}
216+
}
217+
`,
218+
options: ["first"],
219+
parserOptions: { ecmaVersion: 2022 }
220+
},
221+
{
222+
code: `
223+
class C {
224+
static {
225+
foo
226+
}
227+
}
228+
`,
229+
options: ["first"],
230+
parserOptions: { ecmaVersion: 2022 }
231+
},
232+
{
233+
code: `
234+
class C {
235+
static {
236+
foo
237+
bar
238+
}
239+
}
240+
`,
241+
options: ["first"],
242+
parserOptions: { ecmaVersion: 2022 }
243+
},
244+
{
245+
code: `
246+
class C {
247+
static {
248+
;
249+
}
250+
}
251+
`,
252+
options: ["first"],
253+
parserOptions: { ecmaVersion: 2022 }
254+
},
255+
{
256+
code: `
257+
class C {
258+
static {
259+
;foo
260+
}
261+
}
262+
`,
263+
options: ["first"],
264+
parserOptions: { ecmaVersion: 2022 }
265+
},
266+
{
267+
code: `
268+
class C {
269+
static {
270+
foo;
271+
}
272+
}
273+
`,
274+
options: ["first"],
275+
parserOptions: { ecmaVersion: 2022 }
276+
},
277+
{
278+
code: `
279+
class C {
280+
static {
281+
foo
282+
;bar
283+
}
284+
}
285+
`,
286+
options: ["first"],
287+
parserOptions: { ecmaVersion: 2022 }
288+
},
289+
{
290+
code: `
291+
class C {
292+
static {
293+
foo
294+
;bar;
295+
}
296+
}
297+
`,
298+
options: ["first"],
299+
parserOptions: { ecmaVersion: 2022 }
300+
},
301+
{
302+
code: `
303+
class C {
304+
static {
305+
foo
306+
;bar
307+
;baz
308+
}
309+
}
310+
`,
311+
options: ["first"],
312+
parserOptions: { ecmaVersion: 2022 }
313+
},
314+
{
315+
code: `
316+
class C {
317+
static {
318+
foo
319+
;bar
320+
;baz;
321+
}
322+
}
323+
`,
324+
options: ["first"],
325+
parserOptions: { ecmaVersion: 2022 }
130326
}
131327
],
132328
invalid: [
@@ -414,6 +610,56 @@ ruleTester.run("semi-style", rule, {
414610
pos: "the beginning of the next line"
415611
}
416612
}]
613+
},
614+
615+
// Class static blocks
616+
{
617+
code: "class C { static { foo\n; } }",
618+
output: "class C { static { foo;\n} }",
619+
options: ["last"],
620+
parserOptions: { ecmaVersion: 2022 },
621+
errors: [{
622+
messageId: "expectedSemiColon",
623+
data: {
624+
pos: "the end of the previous line"
625+
}
626+
}]
627+
},
628+
{
629+
code: "class C { static { foo\n ;bar } }",
630+
output: "class C { static { foo;\nbar } }",
631+
options: ["last"],
632+
parserOptions: { ecmaVersion: 2022 },
633+
errors: [{
634+
messageId: "expectedSemiColon",
635+
data: {
636+
pos: "the end of the previous line"
637+
}
638+
}]
639+
},
640+
{
641+
code: "class C { static { foo;\nbar\n ; } }",
642+
output: "class C { static { foo;\nbar;\n} }",
643+
options: ["last"],
644+
parserOptions: { ecmaVersion: 2022 },
645+
errors: [{
646+
messageId: "expectedSemiColon",
647+
data: {
648+
pos: "the end of the previous line"
649+
}
650+
}]
651+
},
652+
{
653+
code: "class C { static { foo;\nbar } }",
654+
output: "class C { static { foo\n;bar } }",
655+
options: ["first"],
656+
parserOptions: { ecmaVersion: 2022 },
657+
errors: [{
658+
messageId: "expectedSemiColon",
659+
data: {
660+
pos: "the beginning of the next line"
661+
}
662+
}]
417663
}
418664
]
419665
});

0 commit comments

Comments
 (0)