Skip to content

Conversation

Conaclos
Copy link
Member

Summary

Fix #7289

Test Plan

I added a test

Docs

No change.

Copy link

changeset-bot bot commented Aug 24, 2025

🦋 Changeset detected

Latest commit: 2a464f4

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

Copy link
Contributor

coderabbitai bot commented Aug 24, 2025

Walkthrough

The PR updates the useImportType lint to support the inlineType style by inlining per‑specifier type qualifiers and removing a top‑level type token for named imports. It adds an early path returning AddTypeQualifiers for named imports when style is inlineType, changes a file‑extension check from a bytes comparison to a string comparison, and updates/adds tests under crates/biome_js_analyze/tests/specs/style/useImportType/. A changeset entry for a patch release was added.

Assessment against linked issues

Objective Addressed Explanation
Enforce inlineType: flag import type { T } and fix to import { type T } (#7289)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Switch from bytes-based extension check to string-based extension check (crates/biome_js_analyze/src/lint/style/use_import_type.rs) Adjusts internal file‑extension handling; unrelated to the inlineType behavioural objective in #7289.

Suggested reviewers

  • siketyan
  • ematipico
  • arendjr
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch conaclos/7289-useImportType-inlineType

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added A-Linter Area: linter L-JavaScript Language: JavaScript and super languages labels Aug 24, 2025
@Conaclos Conaclos requested review from a team August 24, 2025 15:54
coderabbitai[bot]

This comment was marked as resolved.

Copy link

codspeed-hq bot commented Aug 24, 2025

CodSpeed Performance Report

Merging #7316 will not alter performance

Comparing conaclos/7289-useImportType-inlineType (2a464f4) with main (7638e84)

Summary

✅ 133 untouched benchmarks

@Conaclos Conaclos force-pushed the conaclos/7289-useImportType-inlineType branch from 50bb8be to 49a1c52 Compare August 24, 2025 16:11
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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
crates/biome_js_analyze/src/lint/style/use_import_type.rs (2)

180-184: Bug: guard now disables the rule in far too many files.

is_none_or(|ext| ext != "cts") returns true for “no extension” and for any non-cts extension, so the rule bails out whenever import attributes are present in almost all cases. The intended behaviour (per prior discussion) is to bail only when the extension is explicitly present and not cts, leaving “no extension” paths unaffected.

Switch to is_some_and so “no extension” no longer short-circuits the rule.

Apply this diff:

-        if import_clause.attribute().is_some()
-            && ctx.file_path().extension().is_none_or(|extension| extension != "cts")
-            && !matches!(ctx.root(), AnyJsRoot::JsScript(_))
-        {
+        if import_clause.attribute().is_some()
+            && ctx.file_path()
+                .extension()
+                .is_some_and(|extension| extension != "cts")
+            && !matches!(ctx.root(), AnyJsRoot::JsScript(_))
+        {
             return None;
         }

756-771: Fixer can silently no-op when a specifier has no leading trivia.

specifier.syntax().first_leading_trivia()? may be None (e.g. import type {A} from "mod";). The ? then aborts the whole action, so no fix is produced. Also, moving the specifier’s leading trivia onto the newly inserted type token risks mangling comments.

Prefer a simpler, safer insertion that doesn’t depend on existing trivia.

Apply this diff:

-                for specifier in specifiers {
-                    let new_specifier = specifier
-                        .clone()
-                        .with_leading_trivia_pieces([])?
-                        .with_type_token(Some(
-                            make::token(T![type])
-                                .with_leading_trivia_pieces(
-                                    specifier.syntax().first_leading_trivia()?.pieces(),
-                                )
-                                .with_trailing_trivia([(TriviaPieceKind::Whitespace, " ")]),
-                        ));
-                    mutation.replace_node(specifier.clone(), new_specifier);
-                }
+                for specifier in specifiers {
+                    let new_specifier = specifier.clone().with_type_token(Some(
+                        make::token(T![type])
+                            .with_trailing_trivia([(TriviaPieceKind::Whitespace, " ")]),
+                    ));
+                    mutation.replace_node(specifier.clone(), new_specifier);
+                }

If you want to preserve comments strictly before the identifier (e.g. /* id */ A), keep them attached to the specifier (not the type token). The formatter will normalise spacing between type and the identifier.

🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/style/use_import_type.rs (1)

413-421: Tighter diagnostic span for clarity.

When suggesting “Use import { type } instead of import type”, anchor the diagnostic to the actual type keyword, not the whole clause. This improves UX in editors.

Apply this diff:

-                if import_clause.type_token().is_some() {
-                    RuleDiagnostic::new(
-                        rule_category!(),
-                        import_clause.range(),
-                        markup! {
-                            "Use "<Emphasis>"import { type }"</Emphasis>" instead of "<Emphasis>"import type"</Emphasis>"."
-                        },
-                    )
-                } else {
+                if let Some(type_kw) = import_clause.type_token() {
+                    RuleDiagnostic::new(
+                        rule_category!(),
+                        type_kw.text_trimmed_range(),
+                        markup! {
+                            "Use "<Emphasis>"import { type }"</Emphasis>" instead of "<Emphasis>"import type"</Emphasis>"."
+                        },
+                    )
+                } else {

Optional follow-up: consider updating the trailing note (below Line 453) to mention both forms remove types at emit time, to avoid confusing users on the inline path.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between aa41691 and 49a1c52.

⛔ Files ignored due to path filters (2)
  • crates/biome_js_analyze/tests/specs/style/useImportType/invalid-inline-type.ts.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/style/useImportType/valid-inline-type.ts.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (4)
  • .changeset/chatty-ravens-agree.md (1 hunks)
  • crates/biome_js_analyze/src/lint/style/use_import_type.rs (4 hunks)
  • crates/biome_js_analyze/tests/specs/style/useImportType/invalid-inline-type.ts (1 hunks)
  • crates/biome_js_analyze/tests/specs/style/useImportType/valid-inline-type.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • .changeset/chatty-ravens-agree.md
  • crates/biome_js_analyze/tests/specs/style/useImportType/invalid-inline-type.ts
🧰 Additional context used
📓 Path-based instructions (4)
crates/biome_*_{syntax,parser,formatter,analyze,factory,semantic}/**

📄 CodeRabbit inference engine (CLAUDE.md)

Maintain the per-language crate structure: biome_{lang}_{syntax,parser,formatter,analyze,factory,semantic}

Files:

  • crates/biome_js_analyze/tests/specs/style/useImportType/valid-inline-type.ts
  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
crates/biome_*/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place core crates under /crates/biome_*/

Files:

  • crates/biome_js_analyze/tests/specs/style/useImportType/valid-inline-type.ts
  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
**/tests/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place test files under a tests/ directory in each crate

Files:

  • crates/biome_js_analyze/tests/specs/style/useImportType/valid-inline-type.ts
**/*.{rs,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Format Rust and TOML files before committing (use just f/just format).

Files:

  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:50:12.090Z
Learning: Applies to crates/biome_js_type_info/src/**/*.rs : Represent links between types using TypeReference (not Arc) to avoid cross-module retention and recursive structures; store type data in linear vectors
📚 Learning: 2025-08-11T11:50:12.090Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:50:12.090Z
Learning: Applies to crates/biome_js_type_info/src/**/*.rs : Use TypeData::Unknown for unimplemented inference and TypeData::UnknownKeyword for the explicit TypeScript unknown keyword; treat them semantically the same but keep them distinct for measurement

Applied to files:

  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
📚 Learning: 2025-08-11T11:50:12.090Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:50:12.090Z
Learning: Applies to crates/biome_js_type_info/src/**/*.rs : Represent links between types using TypeReference (not Arc) to avoid cross-module retention and recursive structures; store type data in linear vectors

Applied to files:

  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
📚 Learning: 2025-08-17T08:56:30.831Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-08-17T08:56:30.831Z
Learning: Applies to crates/biome_analyze/crates/biome_js_analyze/lib/src/lint/nursery/*.rs : For new JavaScript lint rules generated by `just new-js-lintrule`, implement the rule in the generated file under `biome_js_analyze/lib/src/lint/nursery/`

Applied to files:

  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Specify category and severity using #[diagnostic(...)] on the type or derive them from fields

Applied to files:

  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/style/use_import_type.rs (2)
crates/biome_js_syntax/src/import_ext.rs (2)
  • import_clause (169-171)
  • named_specifiers (78-94)
crates/biome_service/src/workspace.rs (1)
  • markup (1130-1132)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: Test Node.js API
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Bench (biome_module_graph)
  • GitHub Check: Bench (biome_graphql_parser)
  • GitHub Check: Bench (biome_html_formatter)
  • GitHub Check: Bench (biome_graphql_formatter)
  • GitHub Check: Bench (biome_json_analyze)
  • GitHub Check: Bench (biome_css_analyze)
  • GitHub Check: Bench (biome_html_parser)
  • GitHub Check: Bench (biome_json_formatter)
  • GitHub Check: Bench (biome_css_formatter)
  • GitHub Check: Bench (biome_css_parser)
  • GitHub Check: Bench (biome_json_parser)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: autofix
🔇 Additional comments (3)
crates/biome_js_analyze/tests/specs/style/useImportType/valid-inline-type.ts (1)

9-11: Good edge-case coverage.

Adding import type {} from "mod"; under a “valid” test is sensible and protects the fixer from trying to inline when there are no specifiers. Nice one.

crates/biome_js_analyze/src/lint/style/use_import_type.rs (2)

287-304: Early inlining path looks correct.

Short-circuiting for Style::InlineType when a top-level type exists keeps the logic simple and makes the fixer’s intent obvious. Good call.


308-309: Minor: good reuse of type_token.

Passing type_token.is_some() avoids recomputing; tidy.

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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/biome_js_analyze/src/lint/style/use_import_type.rs (1)

764-775: Handle specifiers without leading trivia; current code can noop the fix.

specifier.syntax().first_leading_trivia()? can be absent (e.g. import type {A} without spaces). The ? will abort the whole action, so no fix is applied. Use a best-effort approach: steal trivia when present; otherwise, just insert type with no extra leading trivia.

Suggested change:

-                    let new_specifier = specifier
-                        .clone()
-                        .with_leading_trivia_pieces([])?
-                        .with_type_token(Some(
-                            make::token(T![type])
-                                .with_leading_trivia_pieces(
-                                    specifier.syntax().first_leading_trivia()?.pieces(),
-                                )
-                                .with_trailing_trivia([(TriviaPieceKind::Whitespace, " ")]),
-                        ));
+                    let mut type_tok = make::token(T![type])
+                        .with_trailing_trivia([(TriviaPieceKind::Whitespace, " ")]);
+                    if let Some(trivia) = specifier.syntax().first_leading_trivia() {
+                        type_tok = type_tok.with_leading_trivia_pieces(trivia.pieces());
+                    }
+                    let new_specifier = specifier
+                        .clone()
+                        // Drop the specifier's original leading trivia so it becomes owned by `type`
+                        .with_leading_trivia_pieces([])?
+                        .with_type_token(Some(type_tok));

Would you like me to add a test case for import type {A} (no spaces) to ensure this path is covered?

♻️ Duplicate comments (1)
crates/biome_js_analyze/src/lint/style/use_import_type.rs (1)

180-184: Good fix for the short-circuit; watch MSRV for Option::is_none_or.

This addresses the earlier early-return bug. However, Option::is_none_or may be newer than your MSRV. Using map_or keeps MSRV friction-free.

Proposed MSRV-safe tweak:

-                .is_none_or(|extension| extension != "cts")
+                .map_or(true, |extension| extension != "cts")
🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/style/use_import_type.rs (1)

290-307: InlineType fast path: avoid bailing when any specifier node is Err.

collect::<Result<Vec<_>, _>>().ok()? drops the whole signal if any specifier fails to cast. Prefer skipping the bad node(s) as other paths in this rule already do.

-                    let specifiers = clause
-                        .named_specifiers()
-                        .ok()?
-                        .specifiers()
-                        .iter()
-                        .collect::<Result<Vec<_>, _>>()
-                        .ok()?;
+                    let specifiers: Vec<_> = clause
+                        .named_specifiers()
+                        .ok()?
+                        .specifiers()
+                        .iter()
+                        .filter_map(Result::ok)
+                        .collect();
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 49a1c52 and 2a464f4.

📒 Files selected for processing (1)
  • crates/biome_js_analyze/src/lint/style/use_import_type.rs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{rs,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Format Rust and TOML files before committing (use just f/just format).

Files:

  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
crates/biome_*_{syntax,parser,formatter,analyze,factory,semantic}/**

📄 CodeRabbit inference engine (CLAUDE.md)

Maintain the per-language crate structure: biome_{lang}_{syntax,parser,formatter,analyze,factory,semantic}

Files:

  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
crates/biome_*/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place core crates under /crates/biome_*/

Files:

  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
🧠 Learnings (3)
📚 Learning: 2025-08-11T11:50:12.090Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:50:12.090Z
Learning: Applies to crates/biome_js_type_info/src/**/*.rs : Use TypeData::Unknown for unimplemented inference and TypeData::UnknownKeyword for the explicit TypeScript unknown keyword; treat them semantically the same but keep them distinct for measurement

Applied to files:

  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
📚 Learning: 2025-08-11T11:50:12.090Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:50:12.090Z
Learning: Applies to crates/biome_js_type_info/src/**/*.rs : Represent links between types using TypeReference (not Arc) to avoid cross-module retention and recursive structures; store type data in linear vectors

Applied to files:

  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
📚 Learning: 2025-08-11T11:46:05.836Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-08-11T11:46:05.836Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Specify category and severity using #[diagnostic(...)] on the type or derive them from fields

Applied to files:

  • crates/biome_js_analyze/src/lint/style/use_import_type.rs
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/style/use_import_type.rs (1)
crates/biome_js_syntax/src/import_ext.rs (2)
  • import_clause (169-171)
  • named_specifiers (78-94)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (25)
  • GitHub Check: Documentation
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Check Dependencies
  • GitHub Check: End-to-end tests
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Test Node.js API
  • GitHub Check: Bench (biome_graphql_formatter)
  • GitHub Check: Bench (biome_module_graph)
  • GitHub Check: Bench (biome_html_formatter)
  • GitHub Check: Bench (biome_graphql_parser)
  • GitHub Check: Bench (biome_json_analyze)
  • GitHub Check: Bench (biome_html_parser)
  • GitHub Check: Bench (biome_package)
  • GitHub Check: Bench (biome_json_parser)
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Bench (biome_json_formatter)
  • GitHub Check: Bench (biome_css_analyze)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_css_formatter)
  • GitHub Check: Bench (biome_css_parser)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: autofix
🔇 Additional comments (3)
crates/biome_js_analyze/src/lint/style/use_import_type.rs (3)

311-312: Minor readability win.

Reusing the local type_token is tidy and avoids duplicate lookups. LGTM.


415-435: Clearer diagnostic when converting import type → import { type }.

Nice touch: the message now points precisely at the preferred inline form.


759-763: Necessary removal of the clause-level type before inlining.

This prevents producing import { type A } with a stray top-level type. All good.

@Conaclos Conaclos merged commit f9636d5 into main Aug 24, 2025
30 checks passed
@Conaclos Conaclos deleted the conaclos/7289-useImportType-inlineType branch August 24, 2025 16:48
@github-actions github-actions bot mentioned this pull request Aug 24, 2025
ematipico pushed a commit that referenced this pull request Aug 26, 2025
SkyBird233 pushed a commit to SkyBird233/biomejs that referenced this pull request Aug 28, 2025
SkyBird233 pushed a commit to SkyBird233/biomejs that referenced this pull request Aug 28, 2025
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.

💅 useImportType: expected error with inlineType but got none

2 participants