Skip to content

feat(lint): add nursery rule useImportsFirst#9272

Open
terror wants to merge 11 commits intobiomejs:mainfrom
terror:use-imports-first
Open

feat(lint): add nursery rule useImportsFirst#9272
terror wants to merge 11 commits intobiomejs:mainfrom
terror:use-imports-first

Conversation

@terror
Copy link

@terror terror commented Feb 28, 2026

Summary

Resolves #9265

This diff Implements the useImportsFirst lint rule, which enforces that all import statements appear before any non-import statements in a module. This corresponds to the ESLint import/first rule (see #9265). The rule iterates over the module item list and flags any JsImport that appears after a non-import item.

Test Plan

Snapshot tests in crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/:

  • invalid.js - imports after a const declaration (2 diagnostics)
  • invalid_mixed.js - imports interspersed with calls and exports (2 diagnostics)
  • valid.js - all imports grouped at the top (no diagnostics)
  • valid_with_export.js - single import before export and statement (no diagnostics)

Docs

Rule documentation is inline in the declare_lint_rule! macro and will be published automatically.

@changeset-bot
Copy link

changeset-bot bot commented Feb 28, 2026

🦋 Changeset detected

Latest commit: a784b75

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-Project Area: project A-Linter Area: linter L-JavaScript Language: JavaScript and super languages A-Diagnostic Area: diagnostocis labels Feb 28, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 28, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10f3274 and a784b75.

⛔ Files ignored due to path filters (3)
  • crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/invalid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/invalid_all_after.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/invalid_mixed.js.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (1)
  • crates/biome_js_analyze/src/lint/nursery/use_imports_first.rs

Walkthrough

Adds a new nursery lint rule UseImportsFirst (implements biome_analyze::Rule for Ast<JsModuleItemList) that flags import statements appearing after any non‑import module item. Implements rule logic, diagnostics, and options type UseImportsFirstOptions, re-exports the options module, and registers the rule. Adds a changeset and several test specs (valid and invalid cases) under crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/.

Suggested reviewers

  • dyc3
  • ematipico
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarises the main change: adding a new nursery lint rule named useImportsFirst.
Description check ✅ Passed The description is directly related to the changeset, explaining the rule's purpose and providing test plan details.
Linked Issues check ✅ Passed The PR successfully implements the useImportsFirst rule as specified in issue #9265, enforcing imports before non-import statements.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing the new rule: rule implementation, test files, options struct, and changeset documentation.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/valid.js (1)

1-5: Optional: add a directive-focused valid fixture.

Given the rule docs explicitly allow directives, a tiny valid_with_directive.js (e.g. "use strict"; then imports) would lock that behaviour in and guard regressions.

Based on learnings: Add tests for all code changes - lint rules need snapshot tests in tests/specs/{group}/{rule}/.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/valid.js` around
lines 1 - 5, Add a new valid fixture file (e.g., valid_with_directive.js) under
tests/specs/nursery/useImportsFirst/ that begins with a directive like "use
strict"; followed by the same import lines (import { foo } from "foo"; import {
bar } from "bar"; import { baz } from "baz"; const qux = 1;) and the same top
comment ("should not generate diagnostics") so the test suite captures that
directives are allowed by the useImportsFirst rule; ensure the file follows the
existing snapshot test pattern used in tests/specs/{group}/{rule}/ so it is
picked up by the rule tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/biome_rule_options/src/use_imports_first.rs`:
- Line 6: Add a rustdoc comment above the public struct UseImportsFirstOptions
explaining what this options type configures (options for the
"use-imports-first" rule/assist), what each field would control (if currently
empty, state that it has no configurable fields yet and is reserved for future
settings), and include example usage or default behavior; ensure the doc uses
standard /// rustdoc format placed immediately before the declaration of
UseImportsFirstOptions.

---

Nitpick comments:
In `@crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/valid.js`:
- Around line 1-5: Add a new valid fixture file (e.g., valid_with_directive.js)
under tests/specs/nursery/useImportsFirst/ that begins with a directive like
"use strict"; followed by the same import lines (import { foo } from "foo";
import { bar } from "bar"; import { baz } from "baz"; const qux = 1;) and the
same top comment ("should not generate diagnostics") so the test suite captures
that directives are allowed by the useImportsFirst rule; ensure the file follows
the existing snapshot test pattern used in tests/specs/{group}/{rule}/ so it is
picked up by the rule tests.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 412a08d and c6d9702.

⛔ Files ignored due to path filters (7)
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_diagnostics_categories/src/categories.rs is excluded by !**/categories.rs and included by **
  • crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/invalid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/invalid_mixed.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/valid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/valid_with_export.js.snap is excluded by !**/*.snap and included by **
  • packages/@biomejs/biome/configuration_schema.json is excluded by !**/configuration_schema.json and included by **
📒 Files selected for processing (7)
  • crates/biome_js_analyze/src/lint/nursery/use_imports_first.rs
  • crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/invalid.js
  • crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/invalid_mixed.js
  • crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/valid.js
  • crates/biome_js_analyze/tests/specs/nursery/useImportsFirst/valid_with_export.js
  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/use_imports_first.rs

@siketyan
Copy link
Member

  • Restore the PR template and fill it
  • Please add a changeset

Copy link
Contributor

@dyc3 dyc3 left a comment

Choose a reason for hiding this comment

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

Looks good, just a couple notes

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 28, 2026

Merging this PR will not alter performance

✅ 58 untouched benchmarks
⏩ 156 skipped benchmarks1


Comparing terror:use-imports-first (a784b75) with main (e43e730)2

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.

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

@github-actions github-actions bot added the A-CLI Area: CLI label Feb 28, 2026
Copy link
Contributor

@dyc3 dyc3 left a comment

Choose a reason for hiding this comment

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

Nice work!

Copy link
Member

@Netail Netail left a comment

Choose a reason for hiding this comment

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

Would also suggest adding a test with a directive at the beginning of a file

rule_category!(),
range,
markup! {
"This import should appear at the top of the module."
Copy link
Member

Choose a reason for hiding this comment

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

This message doesn't align with the rule pillars. The message must tell what's the error, not the solution. It should say something like "This import shouldn't be here" or something.

Copy link
Author

Choose a reason for hiding this comment

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

Just changed this up. I believe I now follow what 'what', 'why' and 'how' structure we're aiming for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CLI Area: CLI A-Diagnostic Area: diagnostocis A-Linter Area: linter A-Project Area: project L-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

📎 Implement rule to enforce all imports go at the top of the file

5 participants