Skip to content

Commit 625758a

Browse files
kapobajzaKapobajza
andauthored
feat(linter/vitest): Implement padding-around-after-all-blocks rule (#21788)
Related to: #4656 ## Summary Implements the `vitest/padding-around-after-all-blocks` linter rule, which enforces a blank line of padding before `afterAll` blocks in test files. Ports the rule from [eslint-plugin-vitest](https://github.com/vitest-dev/eslint-plugin-vitest). ## AI disclosure I used Claude Code to help me with onboarding, since I am unfamiliar with the code. It explained to me how certain things like `run_on_jest_node`, `report_missing_padding_before_jest_block`, and other things work under the hood. I also used it to help me with generating additional test cases for this rule. And it also generated this PR description for me as well, based on the file changes. ## Description This rule helps keep test files readable by visually separating `afterAll` hooks from surrounding code. **Incorrect:** ```js const thing = 123; afterAll(() => {}); ``` **Correct:** ```js const thing = 123; afterAll(() => {}); ``` The rule: - Category: `style` - Plugin: `vitest` - Auto-fixable: yes (inserts the missing blank line) - Runs on Jest/Vitest nodes via `run_on_jest_node`, filters to `Hook` kind calls named `afterAll`, and delegates reporting to the shared `report_missing_padding_before_jest_block` helper. --------- Co-authored-by: Kapobajza <kapobajza@gmail.com>
1 parent 64a7c11 commit 625758a

11 files changed

Lines changed: 294 additions & 50 deletions

File tree

apps/oxlint/src-js/package/config.generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,7 @@ export interface DummyRuleMap {
12411241
"vitest/no-test-prefixes"?: DummyRule;
12421242
"vitest/no-test-return-statement"?: DummyRule;
12431243
"vitest/no-unneeded-async-expect-function"?: DummyRule;
1244+
"vitest/padding-around-after-all-blocks"?: DummyRule;
12441245
"vitest/prefer-called-exactly-once-with"?: DummyRule;
12451246
"vitest/prefer-called-once"?: DummyRule;
12461247
"vitest/prefer-called-times"?: DummyRule;

crates/oxc_linter/src/generated/rule_runner_impls.rs

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/oxc_linter/src/generated/rules_enum.rs

Lines changed: 48 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/oxc_linter/src/rules.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,7 @@ pub(crate) mod vitest {
768768
pub mod no_test_prefixes;
769769
pub mod no_test_return_statement;
770770
pub mod no_unneeded_async_expect_function;
771+
pub mod padding_around_after_all_blocks;
771772
pub mod prefer_called_exactly_once_with;
772773
pub mod prefer_called_once;
773774
pub mod prefer_called_times;

crates/oxc_linter/src/rules/jest/padding_around_after_all_blocks.rs

Lines changed: 4 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,21 @@
1-
use oxc_ast::AstKind;
21
use oxc_macros::declare_oxc_lint;
32

43
use crate::{
54
context::LintContext,
65
rule::Rule,
7-
utils::{
8-
JestGeneralFnKind, ParsedGeneralJestFnCall, PossibleJestNode, parse_general_jest_fn_call,
9-
report_missing_padding_before_jest_block,
10-
},
6+
rules::shared::padding_around_after_all_blocks::{DOCUMENTATION, run},
7+
utils::PossibleJestNode,
118
};
129

1310
#[derive(Debug, Default, Clone)]
1411
pub struct PaddingAroundAfterAllBlocks;
1512

1613
declare_oxc_lint!(
17-
/// ### What it does
18-
///
19-
/// This rule enforces a line of padding before and after 1 or more
20-
/// `afterAll` statements.
21-
///
22-
/// ### Why is this bad?
23-
///
24-
/// Inconsistent formatting of code can make the code more difficult to read
25-
/// and follow. This rule helps ensure that `afterAll` blocks are visually
26-
/// separated from the rest of the code, making them easier to identify while
27-
/// looking through test files.
28-
///
29-
/// ### Examples
30-
///
31-
/// Examples of **incorrect** code for this rule:
32-
/// ```js
33-
/// const thing = 123;
34-
/// afterAll(() => {});
35-
/// ```
36-
///
37-
/// Examples of **correct** code for this rule:
38-
/// ```js
39-
/// const thing = 123;
40-
///
41-
/// afterAll(() => {});
42-
/// ```
4314
PaddingAroundAfterAllBlocks,
4415
jest,
4516
style,
4617
fix,
18+
docs = DOCUMENTATION,
4719
version = "1.59.0",
4820
);
4921

@@ -53,24 +25,7 @@ impl Rule for PaddingAroundAfterAllBlocks {
5325
jest_node: &PossibleJestNode<'a, 'c>,
5426
ctx: &'c LintContext<'a>,
5527
) {
56-
let node = jest_node.node;
57-
let AstKind::CallExpression(call_expr) = node.kind() else {
58-
return;
59-
};
60-
let Some(jest_fn_call) = parse_general_jest_fn_call(call_expr, jest_node, ctx) else {
61-
return;
62-
};
63-
let ParsedGeneralJestFnCall { kind, name, .. } = &jest_fn_call;
64-
let Some(kind) = kind.to_general() else {
65-
return;
66-
};
67-
if kind != JestGeneralFnKind::Hook {
68-
return;
69-
}
70-
if name != "afterAll" {
71-
return;
72-
}
73-
report_missing_padding_before_jest_block(node, ctx, name);
28+
run(jest_node, ctx);
7429
}
7530
}
7631

crates/oxc_linter/src/rules/shared/jest_vitest/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub mod no_standalone_expect;
2020
pub mod no_test_prefixes;
2121
pub mod no_test_return_statement;
2222
pub mod no_unneeded_async_expect_function;
23+
pub mod padding_around_after_all_blocks;
2324
pub mod prefer_called_with;
2425
pub mod prefer_comparison_matcher;
2526
pub mod prefer_each;
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use oxc_ast::AstKind;
2+
3+
use crate::{
4+
context::LintContext,
5+
utils::{
6+
JestGeneralFnKind, ParsedGeneralJestFnCall, PossibleJestNode, parse_general_jest_fn_call,
7+
report_missing_padding_before_jest_block,
8+
},
9+
};
10+
11+
pub const DOCUMENTATION: &str = r"### What it does
12+
13+
This rule enforces a line of padding before and after 1 or more
14+
`afterAll` statements.
15+
16+
### Why is this bad?
17+
18+
Inconsistent formatting of code can make the code more difficult to read
19+
and follow. This rule helps ensure that `afterAll` blocks are visually
20+
separated from the rest of the code, making them easier to identify while
21+
looking through test files.
22+
23+
### Examples
24+
25+
Examples of **incorrect** code for this rule:
26+
```js
27+
const thing = 123;
28+
afterAll(() => {});
29+
```
30+
31+
Examples of **correct** code for this rule:
32+
```js
33+
const thing = 123;
34+
35+
afterAll(() => {});
36+
";
37+
38+
pub fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) {
39+
let node = possible_jest_node.node;
40+
let AstKind::CallExpression(call_expr) = node.kind() else {
41+
return;
42+
};
43+
let Some(jest_fn_call) = parse_general_jest_fn_call(call_expr, possible_jest_node, ctx) else {
44+
return;
45+
};
46+
let ParsedGeneralJestFnCall { kind, name, .. } = &jest_fn_call;
47+
let Some(kind) = kind.to_general() else {
48+
return;
49+
};
50+
if kind != JestGeneralFnKind::Hook {
51+
return;
52+
}
53+
if name != "afterAll" {
54+
return;
55+
}
56+
report_missing_padding_before_jest_block(node, ctx, name);
57+
}

0 commit comments

Comments
 (0)