Skip to content

feat(linter/jest): implement padding-around-after-all-blocks#21034

Merged
camc314 merged 5 commits intooxc-project:mainfrom
Sapphire1004:feat/my-first-issue
Apr 5, 2026
Merged

feat(linter/jest): implement padding-around-after-all-blocks#21034
camc314 merged 5 commits intooxc-project:mainfrom
Sapphire1004:feat/my-first-issue

Conversation

@Sapphire1004
Copy link
Copy Markdown
Contributor

Summary

  • Implement jest/padding-around-after-all-blocks rule
  • Enforces padding lines before afterAll blocks in test files
  • Includes auto-fix support

Part of #492.

@Sapphire1004 Sapphire1004 requested a review from camc314 as a code owner April 4, 2026 06:39
@github-actions github-actions Bot added A-linter Area - Linter C-enhancement Category - New feature or request labels Apr 4, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 5, 2026

Merging this PR will not alter performance

✅ 4 untouched benchmarks
⏩ 47 skipped benchmarks1


Comparing Sapphire1004:feat/my-first-issue (a2fcdbf) with main (9ee1fb2)2

Open in CodSpeed

Footnotes

  1. 47 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (1550561) during the generation of this report, so 9ee1fb2 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Copy link
Copy Markdown
Contributor

@camc314 camc314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank yoU!

@camc314 camc314 requested a review from Copilot April 5, 2026 12:52
@camc314 camc314 changed the title feat(linter): implement jest/padding-around-after-all-blocks feat(linter/jest): implement padding-around-after-all-blocks Apr 5, 2026
@camc314 camc314 self-assigned this Apr 5, 2026
@camc314 camc314 merged commit 39c8f2c into oxc-project:main Apr 5, 2026
27 of 28 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements the eslint-plugin-jest rule jest/padding-around-after-all-blocks in oxc_linter, sharing padding-detection logic via a new Jest utility and updating rule registration/generated plumbing.

Changes:

  • Added PaddingAroundAfterAllBlocks rule with autofix and snapshot coverage.
  • Extracted common “missing padding before Jest block” logic into utils/jest/padding_around_block.rs and reused it in padding_around_test_blocks.
  • Registered the new rule in rules.rs and updated generated rule enums/runners.

Reviewed changes

Copilot reviewed 6 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
crates/oxc_linter/src/utils/jest/padding_around_block.rs New shared helper to diagnose/autofix missing blank lines before Jest blocks (with comment-aware heuristics).
crates/oxc_linter/src/utils/jest.rs Re-exports the new helper and wires the module into the Jest utils namespace.
crates/oxc_linter/src/rules/jest/padding_around_test_blocks.rs Refactors existing rule to use the shared padding helper.
crates/oxc_linter/src/rules/jest/padding_around_after_all_blocks.rs New rule implementation + tests for afterAll padding enforcement.
crates/oxc_linter/src/snapshots/jest_padding_around_after_all_blocks.snap Snapshot for the new rule’s diagnostics.
crates/oxc_linter/src/rules.rs Adds the new Jest rule module to the rule tree.
crates/oxc_linter/src/generated/rules_enum.rs Generated enum/registry updates to include the new rule.
crates/oxc_linter/src/generated/rule_runner_impls.rs Generated runner impl for the new rule.

Comment on lines +19 to +26
/// This rule enforces a line of padding before and after 1 or more
/// `afterAll` statements.
///
/// ### Why is this bad?
///
/// Inconsistent formatting of code can make the code more difficult to read
/// and follow. This rule helps ensure that `afterAll` blocks are visually
/// separated from the rest of the code, making them easier to identify while
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rule docs say it enforces padding “before and after” afterAll statements, but the implementation only checks for missing padding before the afterAll call. Either update the implementation to also enforce padding after the afterAll block, or adjust the documentation to match the current behavior.

Suggested change
/// This rule enforces a line of padding before and after 1 or more
/// `afterAll` statements.
///
/// ### Why is this bad?
///
/// Inconsistent formatting of code can make the code more difficult to read
/// and follow. This rule helps ensure that `afterAll` blocks are visually
/// separated from the rest of the code, making them easier to identify while
/// This rule enforces a line of padding before 1 or more `afterAll`
/// statements.
///
/// ### Why is this bad?
///
/// Inconsistent formatting of code can make the code more difficult to read
/// and follow. This rule helps ensure that `afterAll` blocks are visually
/// separated from preceding code, making them easier to identify while

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +50
let mut comments_range = ctx.comments_range(prev_statement_span.end..node.span().start);
let mut span_between_start = prev_statement_span.end;
let mut span_between_end = node.span().start;
if let Some(last_comment_span) = comments_range.next_back().map(|comment| comment.span) {
let space_after_last_comment =
ctx.source_range(Span::new(last_comment_span.end, node.span().start));
let space_before_last_comment =
ctx.source_range(Span::new(prev_statement_span.end, last_comment_span.start));
if space_after_last_comment.matches('\n').count() > 1
|| space_before_last_comment.matches('\n').count() == 0
{
span_between_start = last_comment_span.end;
} else {
span_between_end = last_comment_span.start;
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

report_missing_padding_before_jest_block only looks at the last comment between the previous statement and the Jest block when deciding where to measure/insert padding. With multiple leading comments (e.g. const x=1;\n// c1\n// c2\nafterAll(...)), this can incorrectly treat the extra comment newlines as “padding” and skip reporting/fixing the missing blank line before the comment group. Consider treating a contiguous group of comments as attached to the Jest block (walk backwards across adjacent comments with no blank line between them) and then enforce padding before the first comment in that group.

Suggested change
let mut comments_range = ctx.comments_range(prev_statement_span.end..node.span().start);
let mut span_between_start = prev_statement_span.end;
let mut span_between_end = node.span().start;
if let Some(last_comment_span) = comments_range.next_back().map(|comment| comment.span) {
let space_after_last_comment =
ctx.source_range(Span::new(last_comment_span.end, node.span().start));
let space_before_last_comment =
ctx.source_range(Span::new(prev_statement_span.end, last_comment_span.start));
if space_after_last_comment.matches('\n').count() > 1
|| space_before_last_comment.matches('\n').count() == 0
{
span_between_start = last_comment_span.end;
} else {
span_between_end = last_comment_span.start;
let comment_spans: Vec<Span> =
ctx.comments_range(prev_statement_span.end..node.span().start).map(|comment| comment.span).collect();
let mut span_between_start = prev_statement_span.end;
let mut span_between_end = node.span().start;
if let Some(&last_comment_span) = comment_spans.last() {
let mut first_comment_in_group = last_comment_span;
for &comment_span in comment_spans.iter().rev().skip(1) {
let space_between_comments =
ctx.source_range(Span::new(comment_span.end, first_comment_in_group.start));
if space_between_comments.matches('\n').count() == 1 {
first_comment_in_group = comment_span;
} else {
break;
}
}
let space_after_comment_group =
ctx.source_range(Span::new(last_comment_span.end, node.span().start));
let space_before_comment_group =
ctx.source_range(Span::new(prev_statement_span.end, first_comment_in_group.start));
if space_after_comment_group.matches('\n').count() > 1
|| space_before_comment_group.matches('\n').count() == 0
{
span_between_start = last_comment_span.end;
} else {
span_between_end = first_comment_in_group.start;

Copilot uses AI. Check for mistakes.

fn padding_around_jest_block_diagnostic(span: Span, name: &str) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("Missing padding before {name} block"))
.with_help(format!("Make sure there is an empty new line before the {name} block"))
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Diagnostic help text says “empty new line”, which is unidiomatic and a bit unclear for users. Consider changing it to “blank line” or “empty line”.

Suggested change
.with_help(format!("Make sure there is an empty new line before the {name} block"))
.with_help(format!("Make sure there is a blank line before the {name} block"))

Copilot uses AI. Check for mistakes.
leaysgur pushed a commit that referenced this pull request Apr 7, 2026
# Oxlint
### 💥 BREAKING CHANGES

- 22ce6af oxlint/lsp: [**BREAKING**] Show/fix safe suggestions by
default (#19816) (Sysix)

### 🚀 Features

- 7a7b7b8 oxlint/lsp: Add source.fixAllDangerous.oxc code action kind
(#20526) (bab)
- 9cfe57e linter/unicorn: Implement prefer-import-meta-properties rule
(#20662) (Irfan - ئىرفان)
- 1edb391 linter/eslint: Implement `no-restricted-exports` rule (#20592)
(Nicolas Le Cam)
- 0f12bcd linter/react: Implement `hook-use-state` rule (#20986) (Khaled
Labeb)
- 1513a9f oxlint/lsp: Show note field for lsp diagnostic (#20983)
(Sysix)
- 7fdf722 linter/unicorn: Implement `no-useless-iterator-to-array` rule
(#20945) (Mikhail Baev)
- 39c8f2c linter/jest: Implement padding-around-after-all-blocks
(#21034) (Sapphire)
- ac39e51 linter/eslint-vitest-plugin: Prefer importing vitest globals
(#20960) (Said Atrahouch)
- 0b84de1 oxlint: Support allow option for prefer-promise-reject-errors
(#20934) (camc314)
- 23db851 linter/consistent-return: Move rule from nursery to suspicious
(#20920) (camc314)
- 9a27e32 linter/no-unnecessary-type-conversion: Move rule from nursery
to suspicious (#20919) (camc314)
- 1ca7b58 linter/dot-notation: Move rule from nursery to style (#20918)
(camc314)
- 73ba81a linter/consistent-type-exports: Move rule from nursery to
style (#20917) (camc314)
- b9199b1 linter/unicorn: Implement switch-case-break-position (#20872)
(Mikhail Baev)
- 3435ff8 linter: Implements `prefer-snapshot-hint` rule in Jest and
Vitest (#20870) (Said Atrahouch)
- 98510d2 linter: Implement react/prefer-function-component (#19652)
(Connor Shea)
- 871f9d9 linter: Implement no-useless-assignment (#15466) (Zhaoting
Zhou)
- 0f01fbd linter: Implement eslint/object-shorthand (#17688) (yue)

### 🐛 Bug Fixes

- dd2df87 npm: Export package.json for oxlint and oxfmt (#20784) (kazuya
kawaguchi)
- 9bc77dd linter/no-unused-private-class-members: False positive with
await expr (#21067) (camc314)
- 60a57cd linter/const-comparisons: Detect equality contradictions
(#21065) (camc314)
- 2bb2be2 linter/no-array-index-key: False positive when index is passed
as function argument (#21012) (bab)
- 6492953 linter/no-this-in-sfc: Only flag `this` used as member
expression object (#20961) (bab)
- 9446dcc oxlint/lsp: Skip `node_modules` in oxlint config walker
(#21004) (copilot-swe-agent)
- af89923 linter/no-namespace: Support glob pattern matching against
basename (#21031) (bab)
- 64a1a7e oxlint: Don't search for nested config outside base config
(#21051) (Sysix)
- 3b953bc linter/button-has-type: Ignore `document.createElement` calls
(#21008) (Said Atrahouch)
- 8c36070 linter/unicorn: Add support for `Array.from()` for
`prefer-set-size` rule (#21016) (Mikhail Baev)
- c1a48f0 linter: Detect vitest import from vite-plus/test (#20976)
(Said Atrahouch)
- 5c32fd1 lsp: Prevent corrupted autofix output from overlapping text
edits (#19793) (Peter Wagenet)
- ca79960 linter/no-array-index-key: Move span to `key` property
(#20947) (camc314)
- 2098274 linter: Add suggestion for `jest/prefer-equality-matcher`
(#20925) (eryue0220)
- 6eb77ec linter: Allow default-import barrels in import/named (#20757)
(Bazyli Brzóska)
- 9c218ef linter/eslint-vitest-plugin: Remove pending fix status for
require-local-test-context-for-concurrent-snapshot (#20890) (Said
Atrahouch)

### ⚡ Performance

- fb52383 napi/parser, linter/plugins: Clear buffers and source texts
earlier (#21025) (overlookmotel)
- 3b7dec4 napi/parser, linter/plugins: Use `utf8Slice` for decoding
UTF-8 strings (#21022) (overlookmotel)
- 012c924 napi/parser, linter/plugins: Speed up decoding strings in raw
transfer (#21021) (overlookmotel)
- 55e1e9b napi/parser, linter/plugins: Initialize vars as 0 (#21020)
(overlookmotel)
- c25ef02 napi/parser, linter/plugins: Simplify branch condition in
`deserializeStr` (#21019) (overlookmotel)
- 9f494c3 napi/parser, linter/plugins: Raw transfer use
`String.fromCharCode` in string decoding (#21018) (overlookmotel)
- 0503a78 napi/parser, linter/plugins: Faster deserialization of `raw`
fields (#20923) (overlookmotel)
- a24f75e napi/parser: Optimize string deserialization for non-ASCII
sources (#20834) (Joshua Tuddenham)

### 📚 Documentation

- af72b80 oxlint: Fix typo for --tsconfig (#20889) (leaysgur)
- 70c53b1 linter: Highlight that tsconfig is not respected in type aware
linting (#20884) (camc314)
# Oxfmt
### 🚀 Features

- 35cf6e8 oxfmt: Add node version hint for ts config import failures
(#21046) (camc314)

### 🐛 Bug Fixes

- dd2df87 npm: Export package.json for oxlint and oxfmt (#20784) (kazuya
kawaguchi)
- 9d45511 oxfmt: Propagate file write errors instead of panicking
(#20997) (leaysgur)
- 139ddd9 formatter: Handle leading comment after array elision (#20987)
(leaysgur)
- 4216380 oxfmt: Support `.editorconfig` `tab_width` fallback (#20988)
(leaysgur)
- d10df39 formatter: Resolve pending space in fits measurer before
expanded-mode early exit (#20954) (Dunqing)
- f9ef1bd formatter: Avoid breaking after `=>` when arrow body has JSDoc
type cast (#20857) (bab)

Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter C-enhancement Category - New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants