Skip to content

perf(noEmptyBlockStatements): short circuit to avoid traversing descendants for comments#9329

Merged
dyc3 merged 1 commit intomainfrom
dyc3/perf-no-empty-block-statements
Mar 4, 2026
Merged

perf(noEmptyBlockStatements): short circuit to avoid traversing descendants for comments#9329
dyc3 merged 1 commit intomainfrom
dyc3/perf-no-empty-block-statements

Conversation

@dyc3
Copy link
Contributor

@dyc3 dyc3 commented Mar 4, 2026

Summary

It turns out the compiler wasn't optimizing this rule so that it would short circuit automatically. This manually short circuits the logic to avoid scanning of descendants for comments if the block is already known to be not empty.

Found this when stress testing on https://github.com/elastic/kibana Originally, the rule was taking 6s total to execute, but now it takes 124ms.

Test Plan

CI should remain green

Docs

@changeset-bot
Copy link

changeset-bot bot commented Mar 4, 2026

🦋 Changeset detected

Latest commit: 6e4ae14

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-win32-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/wasm-web Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/backend-jsonrpc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added A-Linter Area: linter L-JavaScript Language: JavaScript and super languages labels Mar 4, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 813acc45-49ac-4c21-838b-301cb92c0616

📥 Commits

Reviewing files that changed from the base of the PR and between 3adec68 and 6e4ae14.

📒 Files selected for processing (2)
  • .changeset/nine-sides-wish.md
  • crates/biome_js_analyze/src/lint/suspicious/no_empty_block_statements.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • .changeset/nine-sides-wish.md

Walkthrough

Refactors the noEmptyBlockStatements lint: replaces composed boolean logic with early-return guard checks (empty block, constructor with TS parameter properties/private, and presence of comments), and uses idiomatic is_empty() for directive/statement/case checks. Adds a changeset entry for @biomejs/biome noting improved performance and smarter short-circuiting of the rule.

Suggested reviewers

  • ematipico
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title directly describes the main change: optimising the noEmptyBlockStatements rule through short-circuiting to avoid unnecessary descendant traversal.
Description check ✅ Passed The description clearly explains the motivation (compiler not auto-optimising), the specific change (manual short-circuiting), and provides performance impact evidence (6s to 124ms on real-world data).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dyc3/perf-no-empty-block-statements

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/suspicious/no_empty_block_statements.rs (1)

89-93: Micro-optimisation: swap the last two guards for cheaper short-circuiting.

On Line 89, descendant comment scanning can still happen before the constructor exemption on Line 92. Flipping those checks keeps behaviour identical and avoids an unnecessary tree walk for exempt constructors.

Suggested tweak
-        if query.syntax().has_comments_descendants() {
-            return None;
-        }
         if is_constructor_with_ts_param_props_or_private(query) {
             return None;
         }
+        if query.syntax().has_comments_descendants() {
+            return None;
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/biome_js_analyze/src/lint/suspicious/no_empty_block_statements.rs`
around lines 89 - 93, Swap the two early-return guards so the cheaper
constructor exemption runs before the expensive comment-descendant scan: check
is_constructor_with_ts_param_props_or_private(query) first and return None if
true, then call query.syntax().has_comments_descendants() and return None if
that is true; update the order where those two checks appear (the calls to
is_constructor_with_ts_param_props_or_private and has_comments_descendants) to
short-circuit the tree walk for exempt constructors.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/biome_js_analyze/src/lint/suspicious/no_empty_block_statements.rs`:
- Around line 89-93: Swap the two early-return guards so the cheaper constructor
exemption runs before the expensive comment-descendant scan: check
is_constructor_with_ts_param_props_or_private(query) first and return None if
true, then call query.syntax().has_comments_descendants() and return None if
that is true; update the order where those two checks appear (the calls to
is_constructor_with_ts_param_props_or_private and has_comments_descendants) to
short-circuit the tree walk for exempt constructors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2c144eba-c769-415e-ad9b-67babec5ed5d

📥 Commits

Reviewing files that changed from the base of the PR and between 95914f5 and 6793136.

📒 Files selected for processing (2)
  • .changeset/nine-sides-wish.md
  • crates/biome_js_analyze/src/lint/suspicious/no_empty_block_statements.rs

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 4, 2026

Merging this PR will not alter performance

✅ 58 untouched benchmarks
⏩ 156 skipped benchmarks1


Comparing dyc3/perf-no-empty-block-statements (6e4ae14) with main (ed3c753)

Open in CodSpeed

Footnotes

  1. 156 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.

@dyc3 dyc3 force-pushed the dyc3/perf-no-empty-block-statements branch from 6793136 to 3adec68 Compare March 4, 2026 16:55
@dyc3 dyc3 force-pushed the dyc3/perf-no-empty-block-statements branch from 3adec68 to 6e4ae14 Compare March 4, 2026 18:35
@dyc3 dyc3 requested review from a team March 4, 2026 18:35
@dyc3 dyc3 merged commit 855b451 into main Mar 4, 2026
18 checks passed
@dyc3 dyc3 deleted the dyc3/perf-no-empty-block-statements branch March 4, 2026 19:06
@github-actions github-actions bot mentioned this pull request Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Linter Area: linter L-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant