Conversation
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
…9216) Co-authored-by: Frederick Stempfle <[email protected]> Co-authored-by: Emanuele Stoppa <[email protected]>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Emanuele Stoppa <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…9320) Co-authored-by: Jorge Alexander Taberoa Jimenez <[email protected]> Co-authored-by: Carson McManus <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Merging this PR will not alter performance
Comparing Footnotes
|
WalkthroughThis pull request comprises a collection of improvements across multiple Biome subsystems. It feature-gates CLI-related parsing ( Possibly related PRs
Suggested reviewers
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 20
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/biome_cli/src/execute/migrate/eslint_to_biome.rs (1)
139-157:⚠️ Potential issue | 🟡 MinorInclude
CoveredByRulein the summary maths as well.The new bucket is rendered later on, but it is still excluded from the headline coverage percentage and from the unsupported-rule breakdown header. That means
migrate eslintnow under-reports coverage and the category counts stop adding up once a rule lands here.Suggested fix
- let formatter_covers_count = self + let formatter_covers_count = self .unsupported .iter() .filter(|(_, reason)| { matches!( reason, UnsupportedRuleReason::FormatterCovers | UnsupportedRuleReason::FormatterOption(_) ) }) .count(); + let covered_by_rule_count = self + .unsupported + .iter() + .filter(|(_, reason)| matches!(reason, UnsupportedRuleReason::CoveredByRule(_))) + .count(); let directly_covered_count = self.migrated.len(); let inspired_count = self.inspired.len(); let nursery_count = self.nursery.len(); let total_migratable_count = directly_covered_count + inspired_count + nursery_count; - let total_covered_count = total_migratable_count + formatter_covers_count; + let total_covered_count = + total_migratable_count + formatter_covers_count + covered_by_rule_count;- &markup! { "Unsupported rules ("{stylistic.len()}" incompatible with formatter, "{formatter_covers.len()}" made obsolete by the formatter, "{formatter_option.len()}" covered by a formatter option, "{known_source_not_implemented.len()}" not yet implemented, "{unknown_source.len()}" unknown source):" }, + &markup! { "Unsupported rules ("{stylistic.len()}" incompatible with formatter, "{formatter_covers.len()}" made obsolete by the formatter, "{formatter_option.len()}" covered by a formatter option, "{known_source_not_implemented.len()}" not yet implemented, "{unknown_source.len()}" unknown source, "{covered_by_rule.len()}" covered by another rule):" },Also applies to: 252-255, 321-335
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_cli/src/execute/migrate/eslint_to_biome.rs` around lines 139 - 157, The summary math omits the new CoveredByRule bucket; update the counts to include it by adding filtering for UnsupportedRuleReason::CoveredByRule(...) where appropriate (e.g., alongside FormatterCovers in the formatter_covers_count filter or as its own covered_by_rule_count), then include that count when computing total_migratable_count / total_covered_count and total_covered_percent (variables: formatter_covers_count, total_migratable_count, total_covered_count, total_covered_percent); also propagate the same inclusion into the unsupported-rule breakdown header logic referenced around the other affected blocks so the headline percentage and breakdown sums include CoveredByRule.
🧹 Nitpick comments (11)
.claude/skills/biome-developer/SKILL.md (1)
299-299: Tiny punctuation tidy-up for readability.Consider adding a comma after “Astro” in “if a bug was reported for Astro, but the fix applies broadly…”. It reads a touch cleaner in this long sentence.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.claude/skills/biome-developer/SKILL.md at line 299, Edit the sentence shown in the diff (the guidance line beginning "Do NOT scope comments to the specific trigger that prompted the change. For example, if a bug was reported for Astro but the fix applies broadly, do NOT write `// Fix for Astro embedding`.") and insert a comma after "Astro" so it reads "if a bug was reported for Astro, but the fix applies broadly…"; update the surrounding punctuation as needed to keep the sentence grammatical and preserve the existing phrase `// Fix for Astro embedding`..claude/skills/changeset/SKILL.md (1)
28-28: Clarify the “do not append” instruction to avoid mixed signals.At the moment, this can read as “never put description below the front matter”, but a valid changeset does need description text below once package/change-type front matter is filled in. A tiny reword would reduce contributor confusion.
Based on learnings: create
.changeset/*.mdfiles with proper front matter and write concise end-user-facing descriptions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.claude/skills/changeset/SKILL.md at line 28, Update the ambiguous sentence "Do not simply append to the changeset description below the existing content" to a clear directive: instruct contributors to populate the YAML front matter in .changeset/*.md files and then place a single concise end-user-facing description below that front matter (do not duplicate or append to any existing description block). Reference the terms "front matter" and "description" in the change so reviewers can find and replace the offending line, and ensure the new wording explicitly allows adding description text under the front matter while forbidding appending duplicate content..changeset/wise-frogs-pretend.md (1)
5-5: Consider adding more specific details about the improvement.The description is a bit vague—users would benefit from knowing what specifically changed. For example, does the diagnostic now mention temporal dead zones, provide a code suggestion, or use clearer wording? A concrete detail would make the release note more informative whilst remaining concise.
Example: More specific description
-Improved the `noInvalidUseBeforeDeclaration` diagnostic to better explain why using a declaration too early is problematic and how to fix it. +Improved the `noInvalidUseBeforeDeclaration` diagnostic to now explain temporal dead zones and suggest moving declarations earlier in the code.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.changeset/wise-frogs-pretend.md at line 5, Update the release note line about the noInvalidUseBeforeDeclaration diagnostic to be more specific: state that it now explains temporal dead zones (TDZ), gives a brief example of the problematic pattern and a suggested fix (e.g., move declaration before use or use let/const appropriately), and mention that wording was clarified for readability; ensure the single-sentence changelog still reads concisely but includes those concrete details (reference the diagnostic name noInvalidUseBeforeDeclaration and the concepts "temporal dead zone" and "suggested fix")..changeset/rude-apples-prove.md (1)
5-7: Consider adding an inline example.Whilst the documentation link is helpful, the guidelines recommend including examples directly in the changeset for new rules. A brief code snippet showing the before/after would make this more immediately useful to users scanning the changelog.
📝 Example addition
-Added a new nursery rule [`useStringStartsEndsWith`](https://biomejs.dev/linter/rules/use-string-starts-ends-with/), which prefers `startsWith()` and `endsWith()` over verbose string prefix and suffix checks. +Added a new nursery rule [`useStringStartsEndsWith`](https://biomejs.dev/linter/rules/use-string-starts-ends-with/), which prefers `startsWith()` and `endsWith()` over verbose string prefix and suffix checks. For example, `str[0] === "a"` should be written as `str.startsWith("a")`. The rule uses type information, so it only reports on strings and skips array lookups such as `items[0] === "a"`.As per coding guidelines, changeset descriptions for new rules should include examples with inline code snippets.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.changeset/rude-apples-prove.md around lines 5 - 7, Add a brief before/after code example for the new nursery rule useStringStartsEndsWith to the changeset description: show a short "before" snippet using verbose prefix/suffix checks and an "after" snippet using startsWith()/endsWith(), and place it inline in the changeset text near the rule link so readers scanning the changelog see the transformation immediately; ensure the example clarifies that the rule targets string operations and omits array-index examples like items[0] === "a"..changeset/stale-ties-report.md (1)
7-14: Consider adding a valid example.Showing only the invalid case leaves users guessing what the correct pattern looks like. A brief valid example would clarify that server actions need the
asynckeyword.📝 Suggested addition
**Invalid:** ```js function serverFunction() { 'use server'; // ... }
+Valid:
+
+```js
+async function serverFunction() {
- 'use server';
- // ...
+}
+```</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against the current code and only fix it if needed.
In @.changeset/stale-ties-report.md around lines 7 - 14, The doc shows only an
invalid example of serverFunction without the async keyword; update the
.changeset/stale-ties-report.mdexample by adding a "Valid" code block that
demonstrates the correct pattern (useasync function serverFunction() { 'use server'; /* ... */ }) so readers see the required async server action form, and
place it alongside or immediately after the existing "Invalid" block and the
suggested addition snippet.</details> </blockquote></details> <details> <summary>.claude/skills/lint-rule-development/SKILL.md (2)</summary><blockquote> `308-310`: **Consider documenting `cargo insta review` as well.** Whilst `accept` and `reject` cover bulk operations, `cargo insta review` allows reviewing snapshots individually, which can be valuable when working with multiple snapshot changes. Based on learnings, all three commands are valid workflow options. <details> <summary>📝 Suggested addition</summary> ```diff cargo insta accept # accept all snapshots cargo insta reject # reject all snapshots +cargo insta review # review snapshots individually🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.claude/skills/lint-rule-development/SKILL.md around lines 308 - 310, Add documentation for the individual-review workflow by mentioning the `cargo insta review` command alongside the existing `cargo insta accept` and `cargo insta reject` entries; describe briefly that `cargo insta review` lets you inspect and decide on snapshots one-by-one (useful when multiple snapshot changes exist) and recommend it as an alternative to bulk `accept`/`reject` operations in the same section where `cargo insta accept` and `cargo insta reject` are listed.
415-450: Excellent addition to document diagnostic quality requirements.The three-pillar structure is clearly explained with good examples showing both correct and incorrect approaches. The guidance on placing "how to fix it" in action messages vs diagnostic advice is particularly helpful for rule authors.
Minor nitpick: The heading could be "High-Quality Diagnostics" (hyphenated compound adjective), though this is purely stylistic.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.claude/skills/lint-rule-development/SKILL.md around lines 415 - 450, Rename the heading "High Quality Diagnostics" to the hyphenated "High-Quality Diagnostics" to use a correct compound adjective; update the single heading text (search for the exact string "High Quality Diagnostics" in SKILL.md) and any matching internal references/anchors that rely on that heading so links remain valid (ensure the examples and subsequent paragraphs remain unchanged)..changeset/khaki-mangos-sparkle.md (1)
5-5: Consider being more specific about what improved.The description "Improved the diagnostic to better explain" is a bit vague. Users would benefit from knowing what specifically changed. For instance: "The
noRootTypediagnostic now clarifies that the reported root type is disallowed by project configuration and provides guidance on next steps."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.changeset/khaki-mangos-sparkle.md at line 5, Update the changelog entry to be specific about the change: replace the vague phrase "Improved the `noRootType` diagnostic to better explain that the reported root type is disallowed by project configuration and how to proceed." with an explicit sentence such as "The `noRootType` diagnostic now clarifies that the reported root type is disallowed by project configuration and provides guidance on next steps (how to change the root type or update configuration)." Locate and edit the `.changeset/khaki-mangos-sparkle.md` entry referencing the `noRootType` diagnostic and update the description to this clearer wording so users immediately see what changed and what actions they can take.crates/biome_css_formatter/src/comments.rs (1)
157-159: Tiny clarity nit: wording and behaviour diverge.The comment says “dangling” but the code returns
trailing; please align either the wording or the placement kind. Future-you will thank present-you.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_css_formatter/src/comments.rs` around lines 157 - 159, The comment and the returned placement disagree: update one to match the other. Either change the comment to say "Place comment as trailing on the property..." to match the returned CommentPlacement::trailing(generic_property.into_syntax(), comment), or if the intent was a dangling placement use CommentPlacement::dangling(generic_property.into_syntax(), comment) instead; adjust the text or the call accordingly to keep wording and behavior consistent (refer to CommentPlacement::trailing and CommentPlacement::dangling and the call site using generic_property.into_syntax())..changeset/violet-turtles-smile.md (1)
5-5: Tighten release-note wording for clarity.Consider replacing “should do a bit better” with a direct outcome statement, and capitalise ESLint consistently.
As per coding guidelines: "Write changeset descriptions for end users, not developers."Suggested edit
-Added extra rule sources from react-xyz. `biome migrate eslint` should do a bit better detecting rules in your eslint configurations. +Added extra rule sources from `react-xyz`. `biome migrate eslint` now detects more rules in your ESLint configurations.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.changeset/violet-turtles-smile.md at line 5, Update the changeset message to use direct, end-user facing wording and consistently capitalize "ESLint": replace "biome migrate eslint should do a bit better detecting rules in your eslint configurations" with a clear outcome such as "biome migrate ESLint improves detection of rules in your ESLint configurations" (or similar concise phrasing) so the note reads as a direct benefit to users.crates/biome_analyze_macros/src/lib.rs (1)
32-34: Please add rustdoc for the new derive macro.This is new public proc-macro surface, so it deserves the same treatment as
declare_group_from_fs: one-line purpose, expected input, and a tiny example would do the job.As per coding guidelines, "Add inline rustdoc documentation for new features, rules, assists, and their options".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_analyze_macros/src/lib.rs` around lines 32 - 34, Add inline rustdoc above the proc-macro derive declaration for RuleSourceVariantIndex (the pub fn rule_source_variant_index that calls rule_source_variant_index::rule_source_variant_index_impl) describing in one line what the derive does, what input type/format it expects, and a tiny usage example showing the derive on an enum; ensure the doc is written as standard Rust /// comments directly above the #[proc_macro_derive(RuleSourceVariantIndex)] and the pub fn so it becomes part of the public API docs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.changeset/clear-bananas-lie.md:
- Line 2: The changeset currently uses the wrong release type: update the second
line in .changeset/clear-bananas-lie.md from "patch" to "minor" to reflect a
user-facing non-breaking improvement on the next branch (package identifier:
"@biomejs/biome"); ensure the file now reads the correct release type so the
changeset follows the repo policy for next-branch non-breaking additions.
In @.changeset/dry-dryers-flash.md:
- Line 2: Update the changeset entry that currently contains the line
`"@biomejs/biome": patch` so the release type reflects a new feature; change the
token `patch` to `minor` (i.e., replace `"@biomejs/biome": patch` with
`"@biomejs/biome": minor`) to correctly mark this as a non-breaking addition
targeting next.
In @.changeset/fair-snails-peel.md:
- Line 5: Update the release note sentence in the changeset so the verb agrees
with the plural subject: replace "files that contains scripts and styles" with
"files that contain scripts and styles" in the line describing the `lint
--write` idempotency fix.
In @.changeset/famous-zebras-end.md:
- Line 2: Update the changeset entry for the package key "@biomejs/biome" by
replacing the change type value "patch" with "minor" so the semver bump
correctly reflects a non-breaking user-facing improvement for the next branch;
locate the line containing the "@biomejs/biome" key in the .changeset content
and change its associated value to "minor".
In @.changeset/forty-lemons-stick.md:
- Line 2: Update the changeset entry that currently reads "@biomejs/biome":
patch to use the minor release type instead of patch; locate the string in
.changeset/forty-lemons-stick.md and change the value from patch to minor so the
new user-facing rule targeting next is released as a minor version.
In @.changeset/four-forks-smile.md:
- Line 5: Update the changeset description to include a direct link to the
noSelfCompare rule docs: locate the sentence that mentions `noSelfCompare` in
.changeset/four-forks-smile.md and append or replace the plain rule name with a
hyperlink to its documentation (use the canonical docs URL for the project's
lint rules or rule index), ensuring the link text remains `noSelfCompare` so
users can click through to the rule behavior/details.
In @.changeset/fresh-years-serve.md:
- Line 2: Update the changeset entry that currently reads "@biomejs/biome":
patch to use the non-breaking change type by replacing patch with minor (i.e.,
change the mapping line "@biomejs/biome": patch to "@biomejs/biome": minor) so
the changeset targets a minor release for the next branch.
In @.changeset/giant-bags-wave.md:
- Line 5: The changeset mentions the rule noShorthandPropertyOverrides but
doesn't include a docs link; update the .changeset entry so the rule name is
hyperlinked to its documentation (e.g., replace plain
`noShorthandPropertyOverrides` with a markdown link to the rule's docs URL) so
readers can click through to the rule page—ensure the link text remains the rule
name `noShorthandPropertyOverrides`.
In @.changeset/loose-adults-show.md:
- Line 2: Update the changeset entry so the release type is "minor" instead of
"patch" for the package identifier "@biomejs/biome" in the
.changeset/loose-adults-show.md file; locate the line containing the package
mapping (the string "@biomejs/biome": patch) and change the value from patch to
minor to reflect a non-breaking feature addition targeted for the next branch.
In @.changeset/tender-chicken-swim.md:
- Around line 2-5: The changeset currently declares a "patch" release but
documents added support for parsing member expressions (a new feature) targeting
the next branch; open the file .changeset/tender-chicken-swim.md and change the
release type string from "patch" to "minor" (the line that currently reads
"@biomejs/biome": patch) so the changeset correctly signals a minor (feature)
bump for the `@biomejs/biome` package while leaving the rest of the changeset text
intact.
In @.changeset/use-reduce-type-parameter-1774115911.md:
- Line 2: Update the changeset entry that currently contains the line
`"@biomejs/biome": patch` to use a minor release instead of patch by changing
`patch` to `minor` so the changeset reflects a new non-breaking addition on the
next branch; ensure the single-line mapping for the package name remains exactly
`"@biomejs/biome": minor`.
In @.github/workflows/pull_request.yml:
- Around line 70-82: The workflow's "deny" job currently runs the
taiki-e/install-action to install only the cargo-deny binary but doesn't ensure
a Rust toolchain is present; add a step before the "Install cargo-deny" step to
install a Rust toolchain (e.g., using actions-rs/toolchain or
rust-lang/simple-get-started/rustup) and configure PATH so cargo and rustc are
available for the subsequent "Install cargo-deny" action and the "cargo deny
check ..." runs; ensure the new step is placed before the taiki-e/install-action
step and references the job name "deny" and the existing run steps "cargo deny
check bans" / "cargo deny check advisories" so the toolchain is available when
those commands execute.
In `@crates/biome_analyze/src/rule.rs`:
- Around line 818-821: The advertised/resolved action category is inconsistent:
RuleCategory::Action maps "organizeImports" to SourceActionKind::OrganizeImports
but the helper rule_action_category!() still returns
SourceActionKind::Other("organizeImports"), causing a mismatch. Update the
rule_action_category!() expansion (or the code that builds rule actions) so that
when the rule name is "organizeImports" it returns
SourceActionKind::OrganizeImports instead of
SourceActionKind::Other("organizeImports"); keep references to
RuleCategory::Action, rule_action_category!(), SourceActionKind::OrganizeImports
and SourceActionKind::Other so the mapping is consistent everywhere.
In `@crates/biome_analyze/src/signals.rs`:
- Around line 646-691: actions_metadata currently advertises fixes and
suppression actions unconditionally which can create “phantom” code actions that
resolve() cannot build; update actions_metadata to mirror the real availability
checks used in actions(): only push a fix ActionMetadata when the rule will
actually produce a fix (i.e., honor options.rule_fix_kind and
R::METADATA.fix_kind and verify the rule would produce a fix by using the same
predicate/actions used in actions() — for example call or reuse the logic behind
R::action or the same check actions() uses to decide a fix exists), and only add
suppression ActionMetadata when the suppression-generation logic used by
actions() (e.g., R::text_range or whatever suppression helper actions() invokes)
can actually produce an inline or toplevel suppression; in short, make
actions_metadata call the same availability predicates or helpers as actions()
(and reference options.rule_fix_kind, R::METADATA.fix_kind, R::action, and
R::text_range) before pushing metadata so editors aren’t advertised actions that
can’t be resolved.
In `@crates/biome_cli/src/execute/migrate/eslint_to_biome.rs`:
- Around line 971-999: The test helper run_migrator_spec_test currently calls
serde_json::from_str(&input_code) which fails for .jsonc fixtures containing
comments or trailing commas; update the test to handle JSONC by either
pre-processing input_code to strip comments/trailing commas or by replacing
serde_json::from_str with a lenient parser (e.g., a jsonc/json5 crate) before
creating raw_spec and calling deserialize_migrator_spec, or alternatively
restrict the test glob to only .json — ensure changes touch
run_migrator_spec_test and the calls to
serde_json::from_str/deserialize_migrator_spec so that .jsonc fixtures are
parsed without panicking.
In `@crates/biome_configuration/src/analyzer/mod.rs`:
- Around line 718-732: Add a rustdoc comment with a doctest for the new public
constructor RuleSelector::from_group_and_rule: document the function purpose and
include a fenced code block showing example usages (e.g., asserting
RuleSelector::from_group_and_rule("style", "useConst") ==
Some(RuleSelector::Rule("style","useConst")) and that an unknown rule returns
None); place the doc above the pub fn from_group_and_rule declaration and ensure
the examples compile as doctests; reference the relevant symbols in the text
(from_group_and_rule, RuleSelector, linter::RuleGroup, assist::RuleGroup, Rules,
Actions) so readers can find the implementation easily.
In `@crates/biome_configuration/src/organize_imports.rs`:
- Around line 12-21: The initializer still sets a non-existent field `ignore`
when constructing OrganizeImports (e.g., `Self { enabled: ..., includes: ...,
ignore: ... }`), causing a type error; locate the OrganizeImports
constructor/Default implementation or any `Self { ... }` expressions and remove
the `ignore: ...` entry (or alternatively restore the `ignore` field to the
OrganizeImports struct if that was intended), and apply the same fix to the
other occurrence mentioned (lines 23-29) so the struct fields in the initializer
match the struct definition (`enabled` and `includes` only).
In `@crates/biome_css_formatter/src/comments.rs`:
- Around line 142-143: The identity check currently compares comment text
(piece.text() == comment_piece.text()) which can misattach comments with
identical text; update the condition in the matching logic (the block using
piece.is_comments() and piece.text()) to compare comment ranges/positions
instead (e.g., piece.range() or piece.start()/end() vs
comment_piece.range()/start()/end()) so that you match the exact comment node by
its span rather than by its text content.
In `@crates/biome_css_formatter/src/scss/auxiliary/interpolated_string.rs`:
- Around line 22-47: The code currently flips quotes via preferred_quote_style
and write_quote_token even when some ScssStringText parts are suppressed
(detected by f.comments().is_suppressed), which can leave escapes invalid;
modify the logic in interpolated_string formatting so that you detect if any
AnyScssInterpolatedStringPart::ScssStringText is suppressed (e.g., compute a
boolean like any_text_suppressed by iterating parts and calling
f.comments().is_suppressed(text.syntax()) before deciding on quotes), and if so
disable quote rewriting by forcing quotes_will_change to false (or use the
original quote style when calling write_quote_token for opening_quote_token and
closing_quote_token) and skip changing quotes in write_string_text, keeping
existing behavior for interpolations and non-suppressed text.
- Around line 12-49: Add a snapshot test that covers an interpolated SCSS string
containing a suppressed segment (e.g., annotated with biome-ignore) to ensure
suppressed string parts bypass quote-rewriting; specifically craft an input
where preferred_quote_style would normally change quotes and include a
suppressed AnyScssInterpolatedStringPart (so
f.comments().is_suppressed(text.syntax()) returns true) and assert the output
keeps the original text untouched. Place the test alongside other SCSS
interpolated string tests, exercise FormatScssInterpolatedString
(ScssInterpolatedString via the formatter) and verify that write_string_text is
not applied to suppressed text while non-suppressed parts still follow
preferred_quote_style logic.
---
Outside diff comments:
In `@crates/biome_cli/src/execute/migrate/eslint_to_biome.rs`:
- Around line 139-157: The summary math omits the new CoveredByRule bucket;
update the counts to include it by adding filtering for
UnsupportedRuleReason::CoveredByRule(...) where appropriate (e.g., alongside
FormatterCovers in the formatter_covers_count filter or as its own
covered_by_rule_count), then include that count when computing
total_migratable_count / total_covered_count and total_covered_percent
(variables: formatter_covers_count, total_migratable_count, total_covered_count,
total_covered_percent); also propagate the same inclusion into the
unsupported-rule breakdown header logic referenced around the other affected
blocks so the headline percentage and breakdown sums include CoveredByRule.
---
Nitpick comments:
In @.changeset/khaki-mangos-sparkle.md:
- Line 5: Update the changelog entry to be specific about the change: replace
the vague phrase "Improved the `noRootType` diagnostic to better explain that
the reported root type is disallowed by project configuration and how to
proceed." with an explicit sentence such as "The `noRootType` diagnostic now
clarifies that the reported root type is disallowed by project configuration and
provides guidance on next steps (how to change the root type or update
configuration)." Locate and edit the `.changeset/khaki-mangos-sparkle.md` entry
referencing the `noRootType` diagnostic and update the description to this
clearer wording so users immediately see what changed and what actions they can
take.
In @.changeset/rude-apples-prove.md:
- Around line 5-7: Add a brief before/after code example for the new nursery
rule useStringStartsEndsWith to the changeset description: show a short "before"
snippet using verbose prefix/suffix checks and an "after" snippet using
startsWith()/endsWith(), and place it inline in the changeset text near the rule
link so readers scanning the changelog see the transformation immediately;
ensure the example clarifies that the rule targets string operations and omits
array-index examples like items[0] === "a".
In @.changeset/stale-ties-report.md:
- Around line 7-14: The doc shows only an invalid example of serverFunction
without the async keyword; update the `.changeset/stale-ties-report.md` example
by adding a "Valid" code block that demonstrates the correct pattern (use `async
function serverFunction() { 'use server'; /* ... */ }`) so readers see the
required async server action form, and place it alongside or immediately after
the existing "Invalid" block and the suggested addition snippet.
In @.changeset/violet-turtles-smile.md:
- Line 5: Update the changeset message to use direct, end-user facing wording
and consistently capitalize "ESLint": replace "biome migrate eslint should do a
bit better detecting rules in your eslint configurations" with a clear outcome
such as "biome migrate ESLint improves detection of rules in your ESLint
configurations" (or similar concise phrasing) so the note reads as a direct
benefit to users.
In @.changeset/wise-frogs-pretend.md:
- Line 5: Update the release note line about the noInvalidUseBeforeDeclaration
diagnostic to be more specific: state that it now explains temporal dead zones
(TDZ), gives a brief example of the problematic pattern and a suggested fix
(e.g., move declaration before use or use let/const appropriately), and mention
that wording was clarified for readability; ensure the single-sentence changelog
still reads concisely but includes those concrete details (reference the
diagnostic name noInvalidUseBeforeDeclaration and the concepts "temporal dead
zone" and "suggested fix").
In @.claude/skills/biome-developer/SKILL.md:
- Line 299: Edit the sentence shown in the diff (the guidance line beginning "Do
NOT scope comments to the specific trigger that prompted the change. For
example, if a bug was reported for Astro but the fix applies broadly, do NOT
write `// Fix for Astro embedding`.") and insert a comma after "Astro" so it
reads "if a bug was reported for Astro, but the fix applies broadly…"; update
the surrounding punctuation as needed to keep the sentence grammatical and
preserve the existing phrase `// Fix for Astro embedding`.
In @.claude/skills/changeset/SKILL.md:
- Line 28: Update the ambiguous sentence "Do not simply append to the changeset
description below the existing content" to a clear directive: instruct
contributors to populate the YAML front matter in .changeset/*.md files and then
place a single concise end-user-facing description below that front matter (do
not duplicate or append to any existing description block). Reference the terms
"front matter" and "description" in the change so reviewers can find and replace
the offending line, and ensure the new wording explicitly allows adding
description text under the front matter while forbidding appending duplicate
content.
In @.claude/skills/lint-rule-development/SKILL.md:
- Around line 308-310: Add documentation for the individual-review workflow by
mentioning the `cargo insta review` command alongside the existing `cargo insta
accept` and `cargo insta reject` entries; describe briefly that `cargo insta
review` lets you inspect and decide on snapshots one-by-one (useful when
multiple snapshot changes exist) and recommend it as an alternative to bulk
`accept`/`reject` operations in the same section where `cargo insta accept` and
`cargo insta reject` are listed.
- Around line 415-450: Rename the heading "High Quality Diagnostics" to the
hyphenated "High-Quality Diagnostics" to use a correct compound adjective;
update the single heading text (search for the exact string "High Quality
Diagnostics" in SKILL.md) and any matching internal references/anchors that rely
on that heading so links remain valid (ensure the examples and subsequent
paragraphs remain unchanged).
In `@crates/biome_analyze_macros/src/lib.rs`:
- Around line 32-34: Add inline rustdoc above the proc-macro derive declaration
for RuleSourceVariantIndex (the pub fn rule_source_variant_index that calls
rule_source_variant_index::rule_source_variant_index_impl) describing in one
line what the derive does, what input type/format it expects, and a tiny usage
example showing the derive on an enum; ensure the doc is written as standard
Rust /// comments directly above the
#[proc_macro_derive(RuleSourceVariantIndex)] and the pub fn so it becomes part
of the public API docs.
In `@crates/biome_css_formatter/src/comments.rs`:
- Around line 157-159: The comment and the returned placement disagree: update
one to match the other. Either change the comment to say "Place comment as
trailing on the property..." to match the returned
CommentPlacement::trailing(generic_property.into_syntax(), comment), or if the
intent was a dangling placement use
CommentPlacement::dangling(generic_property.into_syntax(), comment) instead;
adjust the text or the call accordingly to keep wording and behavior consistent
(refer to CommentPlacement::trailing and CommentPlacement::dangling and the call
site using generic_property.into_syntax()).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8564459a-a3d3-4c44-9932-b27c4b584d97
⛔ Files ignored due to path filters (107)
Cargo.lockis excluded by!**/*.lockand included by**crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rsis excluded by!**/migrate/eslint_any_rule_to_biome.rsand included by**crates/biome_cli/tests/snapshots/main_cases_css_parsing/check_combined_format_with_errors_and_css_modules.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_css_parsing/check_css_parse_css_modules_false.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_css_parsing/ci_css_parse_css_modules_false.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_format_with_errors/check_format_with_errors_false.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_format_with_errors/check_format_with_errors_overrides_config.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_format_with_errors/check_format_with_errors_respects_config_false.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_format_with_errors/check_format_with_errors_respects_config_true.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_format_with_errors/check_format_with_errors_true.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_format_with_errors/ci_format_with_errors_false.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_format_with_errors/ci_format_with_errors_true.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_handle_astro_files/full_support.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_handle_astro_files/issue_7912.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_html/check_write_html_with_embedded_style_is_idempotent.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_html/lint_write_html_with_embedded_script_is_idempotent.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_json_parsing/check_json_parse_allow_comments_false.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_json_parsing/check_json_parse_allow_trailing_commas_false.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_linter_domains/should_enable_domain_via_cli.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_linter_domains/skip_domain_does_not_report_unused_suppression.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_overrides_formatter/disallow_comments_on_well_known_files.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_checkstyle/reports_diagnostics_checkstyle_check_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_checkstyle/reports_diagnostics_checkstyle_check_command_file.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_checkstyle/reports_diagnostics_checkstyle_ci_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_checkstyle/reports_diagnostics_checkstyle_lint_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_concise/reports_diagnostics_concise_check_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_concise/reports_diagnostics_concise_ci_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_concise/reports_diagnostics_concise_lint_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_github/reports_diagnostics_github_check_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_github/reports_diagnostics_github_ci_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_github/reports_diagnostics_github_lint_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_gitlab/reports_diagnostics_gitlab_check_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_gitlab/reports_diagnostics_gitlab_ci_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_gitlab/reports_diagnostics_gitlab_lint_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_json/reports_diagnostics_json_check_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_json/reports_diagnostics_json_check_command_file.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_json/reports_diagnostics_json_ci_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_json/reports_diagnostics_json_lint_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_junit/reports_diagnostics_junit_check_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_junit/reports_diagnostics_junit_check_command_file.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_junit/reports_diagnostics_junit_ci_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_junit/reports_diagnostics_junit_lint_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_rdjson/reports_diagnostics_rdjson_check_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_rdjson/reports_diagnostics_rdjson_check_command_file.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_rdjson/reports_diagnostics_rdjson_ci_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_rdjson/reports_diagnostics_rdjson_lint_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_sarif/reports_diagnostics_sarif_check_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_sarif/reports_diagnostics_sarif_ci_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_sarif/reports_diagnostics_sarif_lint_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_summary/reports_diagnostics_summary_check_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_summary/reports_diagnostics_summary_check_verbose_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_summary/reports_diagnostics_summary_check_verbose_command_destination.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_summary/reports_diagnostics_summary_ci_command.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_terminal/reports_diagnostics_check_command_verbose.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_terminal/reports_diagnostics_check_write_command_file.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_cases_reporter_terminal/reports_diagnostics_check_write_command_verbose.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_check/apply_bogus_argument.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_check/check_format_with_syntax_errors_when_flag_enabled.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_check/check_js_plugin_with_native_field_names.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_check/check_skip_parse_errors.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_check/lint_error.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_check/lint_error_without_file_paths.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_check/maximum_diagnostics.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_check/parse_error.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_check/print_verbose.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_check/print_verbose_write.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_ci/ci_lint_error.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_ci/ci_parse_error.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_ci/ci_skip_parse_errors.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_ci/print_verbose.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_lint/lint_error.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_lint/lint_error_without_file_paths.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_lint/lint_skip_parse_errors.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_lint/maximum_diagnostics.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_lint/print_verbose.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_migrate_eslint/migrate_jest_consistent_test_it_no_options.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_migrate_eslint/migrate_jest_consistent_test_it_with_options.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_migrate_eslint/migrate_vitest_consistent_test_it_with_options.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/snapshots/main_commands_search/search_js_pattern_with_native_field_names.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/specs/migrate_eslint/jestConsistentTestIt/defaults.jsonc.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/specs/migrate_eslint/jestConsistentTestIt/withOptions.jsonc.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/specs/migrate_eslint/jsxA11yAriaRole/basic.jsonc.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/specs/migrate_eslint/noRestrictedGlobals/basic.jsonc.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/specs/migrate_eslint/typescriptArrayType/generic.jsonc.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/specs/migrate_eslint/typescriptConsistentTypeImports/inlineTypeImports.jsonc.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/specs/migrate_eslint/typescriptExplicitMemberAccessibility/explicit.jsonc.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/specs/migrate_eslint/typescriptNamingConvention/basic.jsonc.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/specs/migrate_eslint/unicornFilenameCase/basic.jsonc.snapis excluded by!**/*.snapand included by**crates/biome_cli/tests/specs/migrate_eslint/vitestConsistentTestIt/withOptions.jsonc.snapis excluded by!**/*.snapand included by**crates/biome_configuration/src/analyzer/linter/rules.rsis excluded by!**/rules.rsand included by**crates/biome_configuration/src/generated/domain_selector.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_configuration/src/generated/linter_options_check.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_css_analyze/tests/specs/correctness/noUnknownMediaFeatureName/invalid.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/correctness/noUnknownUnit/invalid.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.css.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.max2.css.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.nested.css.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.pseudo.css.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.zero.css.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.zero.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/valid.css.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/valid.max2.css.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/valid.zero.css.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/valid.zero.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_analyze/tests/specs/suspicious/noShorthandPropertyOverrides/invalid.css.snapis excluded by!**/*.snapand included by**crates/biome_css_factory/src/generated/node_factory.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_css_factory/src/generated/syntax_factory.rsis excluded by!**/generated/**,!**/generated/**and included by**
📒 Files selected for processing (193)
.changeset/add-no-duplicate-selectors.md.changeset/add-no-identical-test-title.md.changeset/clear-bananas-lie.md.changeset/dry-dryers-flash.md.changeset/fair-otters-count.md.changeset/fair-snails-applaud.md.changeset/fair-snails-peel.md.changeset/famous-zebras-end.md.changeset/feat-use-optional-chain-negated-or.md.changeset/fix-adjacent-overload-static.md.changeset/fix-ambient-module-signature-panic.md.changeset/fix-domain-group-enables.md.changeset/fix-js-parser-9548.md.changeset/fix-lone-block-comments.md.changeset/fix-lsp-missing-workspace-folders.md.changeset/fix-use-expect-false-negatives.md.changeset/fix-vue-directive-expression-parsing.md.changeset/forty-lemons-stick.md.changeset/forty-women-move.md.changeset/four-forks-smile.md.changeset/fresh-years-serve.md.changeset/giant-bags-wave.md.changeset/hip-things-hang.md.changeset/khaki-mangos-sparkle.md.changeset/large-buses-stick.md.changeset/loose-adults-show.md.changeset/many-snakes-wonder.md.changeset/mighty-mayflies-rest.md.changeset/neat-oranges-open.md.changeset/plain-keys-arrive.md.changeset/plain-turkeys-beam.md.changeset/pretty-hornets-rescue.md.changeset/rare-schools-raise.md.changeset/rude-apples-prove.md.changeset/sad-buttons-kneel.md.changeset/stale-ties-report.md.changeset/strong-mirrors-attend.md.changeset/tender-chicken-swim.md.changeset/three-candles-tan.md.changeset/three-peaches-dress.md.changeset/tidy-bags-draw.md.changeset/use-reduce-type-parameter-1774115911.md.changeset/violet-turtles-smile.md.changeset/wise-frogs-pretend.md.changeset/yellow-fans-glow.md.claude/skills/biome-developer/SKILL.md.claude/skills/changeset/SKILL.md.claude/skills/diagnostics-development/SKILL.md.claude/skills/eslint-migrate-options/SKILL.md.claude/skills/lint-rule-development/SKILL.md.github/workflows/benchmark_configuration.yml.github/workflows/benchmark_css.yml.github/workflows/benchmark_graphql.yml.github/workflows/benchmark_grit.yml.github/workflows/benchmark_html.yml.github/workflows/benchmark_js.yml.github/workflows/benchmark_json.yml.github/workflows/benchmark_manifests.yml.github/workflows/benchmark_markdown.yml.github/workflows/benchmark_module_graph.yml.github/workflows/benchmark_tailwind.yml.github/workflows/beta.yml.github/workflows/beta_js_api.yml.github/workflows/main.yml.github/workflows/preview.yml.github/workflows/pull_request.yml.github/workflows/pull_request_markdown.yml.github/workflows/pull_request_node.yml.github/workflows/release.yml.github/workflows/release_cli.yml.github/workflows/release_js_api.yml.github/workflows/repository_dispatch.ymlCONTRIBUTING.mdCargo.tomlDockerfile.benchmarkbenchmark/package.jsoncrates/biome_analyze/CONTRIBUTING.mdcrates/biome_analyze/Cargo.tomlcrates/biome_analyze/src/lib.rscrates/biome_analyze/src/rule.rscrates/biome_analyze/src/signals.rscrates/biome_analyze_macros/src/lib.rscrates/biome_analyze_macros/src/rule_source_variant_index.rscrates/biome_cli/Cargo.tomlcrates/biome_cli/src/commands/clean.rscrates/biome_cli/src/commands/explain.rscrates/biome_cli/src/commands/rage.rscrates/biome_cli/src/commands/search.rscrates/biome_cli/src/execute/migrate.rscrates/biome_cli/src/execute/migrate/eslint_eslint.rscrates/biome_cli/src/execute/migrate/eslint_jest.rscrates/biome_cli/src/execute/migrate/eslint_to_biome.rscrates/biome_cli/src/execute/migrate/unsupported_rules.rscrates/biome_cli/src/runner/crawler.rscrates/biome_cli/src/runner/handler.rscrates/biome_cli/src/runner/impls/collectors/default.rscrates/biome_cli/src/runner/impls/process_file/check.rscrates/biome_cli/src/runner/impls/process_file/format.rscrates/biome_cli/src/runner/impls/process_file/lint_and_assist.rscrates/biome_cli/src/runner/mod.rscrates/biome_cli/src/runner/process_file.rscrates/biome_cli/tests/cases/html.rscrates/biome_cli/tests/cases/linter_domains.rscrates/biome_cli/tests/commands/check.rscrates/biome_cli/tests/commands/format.rscrates/biome_cli/tests/commands/migrate_eslint.rscrates/biome_cli/tests/commands/search.rscrates/biome_cli/tests/specs/migrate_eslint/jestConsistentTestIt/defaults.jsonccrates/biome_cli/tests/specs/migrate_eslint/jestConsistentTestIt/withOptions.jsonccrates/biome_cli/tests/specs/migrate_eslint/jsxA11yAriaRole/basic.jsonccrates/biome_cli/tests/specs/migrate_eslint/noRestrictedGlobals/basic.jsonccrates/biome_cli/tests/specs/migrate_eslint/typescriptArrayType/generic.jsonccrates/biome_cli/tests/specs/migrate_eslint/typescriptConsistentTypeImports/inlineTypeImports.jsonccrates/biome_cli/tests/specs/migrate_eslint/typescriptExplicitMemberAccessibility/explicit.jsonccrates/biome_cli/tests/specs/migrate_eslint/typescriptNamingConvention/basic.jsonccrates/biome_cli/tests/specs/migrate_eslint/unicornFilenameCase/basic.jsonccrates/biome_cli/tests/specs/migrate_eslint/vitestConsistentTestIt/withOptions.jsonccrates/biome_configuration/Cargo.tomlcrates/biome_configuration/src/analyzer/assist/mod.rscrates/biome_configuration/src/analyzer/linter/mod.rscrates/biome_configuration/src/analyzer/mod.rscrates/biome_configuration/src/css.rscrates/biome_configuration/src/formatter.rscrates/biome_configuration/src/graphql.rscrates/biome_configuration/src/grit.rscrates/biome_configuration/src/html.rscrates/biome_configuration/src/javascript/formatter.rscrates/biome_configuration/src/javascript/mod.rscrates/biome_configuration/src/json.rscrates/biome_configuration/src/lib.rscrates/biome_configuration/src/markdown.rscrates/biome_configuration/src/organize_imports.rscrates/biome_configuration/src/overrides.rscrates/biome_configuration/src/vcs.rscrates/biome_configuration_macros/Cargo.tomlcrates/biome_console/Cargo.tomlcrates/biome_css_analyze/Cargo.tomlcrates/biome_css_analyze/benches/css_analyzer.rscrates/biome_css_analyze/src/lib.rscrates/biome_css_analyze/src/lint/correctness/no_unknown_media_feature_name.rscrates/biome_css_analyze/src/lint/correctness/no_unknown_unit.rscrates/biome_css_analyze/src/lint/nursery/no_duplicate_selectors.rscrates/biome_css_analyze/src/lint/nursery/no_excessive_selector_classes.rscrates/biome_css_analyze/src/lint/nursery/use_baseline.rscrates/biome_css_analyze/src/lint/suspicious/no_shorthand_property_overrides.rscrates/biome_css_analyze/tests/quick_test.rscrates/biome_css_analyze/tests/spec_tests.rscrates/biome_css_analyze/tests/specs/correctness/noUnknownMediaFeatureName/invalid.scsscrates/biome_css_analyze/tests/specs/correctness/noUnknownUnit/invalid.scsscrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.csscrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.max2.csscrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.max2.options.jsoncrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.nested.csscrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.nested.options.jsoncrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.options.jsoncrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.pseudo.csscrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.pseudo.options.jsoncrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.zero.csscrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.zero.options.jsoncrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/invalid.zero.scsscrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/valid.csscrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/valid.max2.csscrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/valid.max2.options.jsoncrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/valid.zero.csscrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/valid.zero.options.jsoncrates/biome_css_analyze/tests/specs/nursery/noExcessiveSelectorClasses/valid.zero.scsscrates/biome_css_formatter/Cargo.tomlcrates/biome_css_formatter/src/comments.rscrates/biome_css_formatter/src/css/any/attribute_matcher_value.rscrates/biome_css_formatter/src/css/any/function_name.rscrates/biome_css_formatter/src/css/any/import_url.rscrates/biome_css_formatter/src/css/any/keyframes_selector.rscrates/biome_css_formatter/src/css/any/mod.rscrates/biome_css_formatter/src/css/any/pseudo_value.rscrates/biome_css_formatter/src/css/any/query_feature_name.rscrates/biome_css_formatter/src/css/any/query_feature_value.rscrates/biome_css_formatter/src/css/any/url_value.rscrates/biome_css_formatter/src/css/any/value.rscrates/biome_css_formatter/src/css/auxiliary/attribute_matcher_value.rscrates/biome_css_formatter/src/css/properties/generic_property.rscrates/biome_css_formatter/src/css/selectors/keyframes_range_selector.rscrates/biome_css_formatter/src/css/selectors/mod.rscrates/biome_css_formatter/src/generated.rscrates/biome_css_formatter/src/scss/any/import_item.rscrates/biome_css_formatter/src/scss/any/interpolated_identifier_part.rscrates/biome_css_formatter/src/scss/any/interpolated_string_part.rscrates/biome_css_formatter/src/scss/any/mod.rscrates/biome_css_formatter/src/scss/auxiliary/interpolated_identifier_hyphen.rscrates/biome_css_formatter/src/scss/auxiliary/interpolated_string.rscrates/biome_css_formatter/src/scss/auxiliary/mod.rscrates/biome_css_formatter/src/scss/auxiliary/string_text.rscrates/biome_css_formatter/src/scss/lists/interpolated_string_part_list.rscrates/biome_css_formatter/src/scss/lists/mod.rs
💤 Files with no reviewable changes (17)
- .changeset/fix-ambient-module-signature-panic.md
- .changeset/fix-lone-block-comments.md
- .changeset/hip-things-hang.md
- .changeset/neat-oranges-open.md
- .changeset/plain-turkeys-beam.md
- .changeset/pretty-hornets-rescue.md
- .changeset/strong-mirrors-attend.md
- .changeset/three-candles-tan.md
- .changeset/add-no-duplicate-selectors.md
- .changeset/feat-use-optional-chain-negated-or.md
- .changeset/fix-adjacent-overload-static.md
- .changeset/fix-domain-group-enables.md
- .changeset/fix-js-parser-9548.md
- .changeset/fix-lsp-missing-workspace-folders.md
- .changeset/fix-use-expect-false-negatives.md
- .changeset/fix-vue-directive-expression-parsing.md
- .changeset/forty-women-move.md
| @@ -0,0 +1,5 @@ | |||
| --- | |||
| "@biomejs/biome": patch | |||
There was a problem hiding this comment.
Use minor release type for this next-branch changeset.
Line 2 is currently patch, but this is a user-facing non-breaking improvement on next, so it should be minor per repo policy.
As per coding guidelines: "Use 'minor' change type for new features and non-breaking additions targeting the next branch."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.changeset/clear-bananas-lie.md at line 2, The changeset currently uses the
wrong release type: update the second line in .changeset/clear-bananas-lie.md
from "patch" to "minor" to reflect a user-facing non-breaking improvement on the
next branch (package identifier: "@biomejs/biome"); ensure the file now reads
the correct release type so the changeset follows the repo policy for
next-branch non-breaking additions.
| @@ -0,0 +1,25 @@ | |||
| --- | |||
| "@biomejs/biome": patch | |||
There was a problem hiding this comment.
Use minor here, not patch
Line 2 marks this as patch, but this entry documents a new rule (feature) on next, so it should be minor to keep release semantics tidy.
Suggested fix
---
-"@biomejs/biome": patch
+"@biomejs/biome": minor
---As per coding guidelines, .changeset/*.md entries must use minor for new features and non-breaking additions targeting the next branch.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "@biomejs/biome": patch | |
| --- | |
| "@biomejs/biome": minor | |
| --- |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.changeset/dry-dryers-flash.md at line 2, Update the changeset entry that
currently contains the line `"@biomejs/biome": patch` so the release type
reflects a new feature; change the token `patch` to `minor` (i.e., replace
`"@biomejs/biome": patch` with `"@biomejs/biome": minor`) to correctly mark this
as a non-breaking addition targeting next.
| "@biomejs/biome": patch | ||
| --- | ||
|
|
||
| Fixed [#9901](https://github.com/biomejs/biome/issues/9901): the command `lint --write` is now idempotent when it's run against HTML-ish files that contains scripts and styles. |
There was a problem hiding this comment.
Fix grammar in the release note sentence.
Line 5 should use plural agreement: “files that contain scripts and styles”.
Suggested edit
-Fixed [`#9901`](https://github.com/biomejs/biome/issues/9901): the command `lint --write` is now idempotent when it's run against HTML-ish files that contains scripts and styles.
+Fixed [`#9901`](https://github.com/biomejs/biome/issues/9901): the command `lint --write` is now idempotent when it's run against HTML-ish files that contain scripts and styles.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Fixed [#9901](https://github.com/biomejs/biome/issues/9901): the command `lint --write` is now idempotent when it's run against HTML-ish files that contains scripts and styles. | |
| Fixed [`#9901`](https://github.com/biomejs/biome/issues/9901): the command `lint --write` is now idempotent when it's run against HTML-ish files that contain scripts and styles. |
🧰 Tools
🪛 LanguageTool
[grammar] ~5-~5: Possible subject-verb agreement error detected.
Context: ...en it's run against HTML-ish files that contains scripts and styles.
(PLURAL_THAT_AGREEMENT)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.changeset/fair-snails-peel.md at line 5, Update the release note sentence
in the changeset so the verb agrees with the plural subject: replace "files that
contains scripts and styles" with "files that contain scripts and styles" in the
line describing the `lint --write` idempotency fix.
| @@ -0,0 +1,5 @@ | |||
| --- | |||
| "@biomejs/biome": patch | |||
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Semver bump type looks off for next branch
Line 2 should likely be minor, not patch, for a user-facing non-breaking improvement on next. Tiny zebra, big release train 🚂
Suggested fix
"@biomejs/biome": patch
+"@biomejs/biome": minor🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.changeset/famous-zebras-end.md at line 2, Update the changeset entry for
the package key "@biomejs/biome" by replacing the change type value "patch" with
"minor" so the semver bump correctly reflects a non-breaking user-facing
improvement for the next branch; locate the line containing the "@biomejs/biome"
key in the .changeset content and change its associated value to "minor".
| @@ -0,0 +1,11 @@ | |||
| --- | |||
| "@biomejs/biome": patch | |||
There was a problem hiding this comment.
Use minor here, not patch
This changeset describes a new user-facing rule, and this PR targets next, so the release type should be minor.
Suggested fix
"@biomejs/biome": patch
+"@biomejs/biome": minorAs per coding guidelines: “Use 'minor' change type for new features and non-breaking additions targeting the next branch.”
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.changeset/forty-lemons-stick.md at line 2, Update the changeset entry that
currently reads "@biomejs/biome": patch to use the minor release type instead of
patch; locate the string in .changeset/forty-lemons-stick.md and change the
value from patch to minor so the new user-facing rule targeting next is released
as a minor version.
| pub fn from_group_and_rule(group: &str, rule: &str) -> Option<Self> { | ||
| if let Ok(group) = linter::RuleGroup::from_str(group) | ||
| && let Some(rule) = Rules::has_rule(group, rule) | ||
| { | ||
| return Some(Self::Rule(group.as_str(), rule)); | ||
| } | ||
|
|
||
| if let Ok(group) = assist::RuleGroup::from_str(group) | ||
| && let Some(rule) = Actions::has_rule(group, rule) | ||
| { | ||
| return Some(Self::Rule(group.as_str(), rule)); | ||
| } | ||
|
|
||
| None | ||
| } |
There was a problem hiding this comment.
Add rustdoc + a doctest for this new public constructor.
Nice helper, but Line 718 introduces a public API without docs/examples, so it’ll be harder to discover and maintain.
Suggested patch
+ /// Builds a [`RuleSelector`] from explicit group and rule names.
+ ///
+ /// Returns `None` when the group doesn't exist or the rule/action is unknown
+ /// for that group.
+ ///
+ /// ```
+ /// use biome_configuration::analyzer::RuleSelector;
+ ///
+ /// assert_eq!(
+ /// RuleSelector::from_group_and_rule("style", "useConst"),
+ /// Some(RuleSelector::Rule("style", "useConst"))
+ /// );
+ /// assert_eq!(RuleSelector::from_group_and_rule("style", "notARule"), None);
+ /// ```
pub fn from_group_and_rule(group: &str, rule: &str) -> Option<Self> {As per coding guidelines, “Add inline rustdoc documentation for new features, rules, assists, and their options” and “Write doctest examples in doc comments using markdown code blocks, ensuring assertions pass during testing”.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@crates/biome_configuration/src/analyzer/mod.rs` around lines 718 - 732, Add a
rustdoc comment with a doctest for the new public constructor
RuleSelector::from_group_and_rule: document the function purpose and include a
fenced code block showing example usages (e.g., asserting
RuleSelector::from_group_and_rule("style", "useConst") ==
Some(RuleSelector::Rule("style","useConst")) and that an unknown rule returns
None); place the doc above the pub fn from_group_and_rule declaration and ensure
the examples compile as doctests; reference the relevant symbols in the text
(from_group_and_rule, RuleSelector, linter::RuleGroup, assist::RuleGroup, Rules,
Actions) so readers can find the implementation easily.
| if piece.is_comments() && piece.text() == comment_piece.text() { | ||
| // Our placement is slightly better than Prettier because it adds some spacing |
There was a problem hiding this comment.
Use comment range (not text) for identity checks.
Line 142 currently matches by text content only; identical comment text can attach the wrong comment node within the same property.
Suggested patch
- if piece.is_comments() && piece.text() == comment_piece.text() {
+ if piece.is_comments() && piece.text_range() == comment_piece.text_range() {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if piece.is_comments() && piece.text() == comment_piece.text() { | |
| // Our placement is slightly better than Prettier because it adds some spacing | |
| if piece.is_comments() && piece.text_range() == comment_piece.text_range() { | |
| // Our placement is slightly better than Prettier because it adds some spacing |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@crates/biome_css_formatter/src/comments.rs` around lines 142 - 143, The
identity check currently compares comment text (piece.text() ==
comment_piece.text()) which can misattach comments with identical text; update
the condition in the matching logic (the block using piece.is_comments() and
piece.text()) to compare comment ranges/positions instead (e.g., piece.range()
or piece.start()/end() vs comment_piece.range()/start()/end()) so that you match
the exact comment node by its span rather than by its text content.
| impl FormatNodeRule<ScssInterpolatedString> for FormatScssInterpolatedString { | ||
| fn fmt_fields(&self, node: &ScssInterpolatedString, f: &mut CssFormatter) -> FormatResult<()> { | ||
| let ScssInterpolatedStringFields { | ||
| opening_quote_token, | ||
| parts, | ||
| closing_quote_token, | ||
| } = node.as_fields(); | ||
| let opening_quote_token = opening_quote_token?; | ||
| let closing_quote_token = closing_quote_token?; | ||
|
|
||
| let preferred_quote = preferred_quote_style(&parts, f.options().quote_style()); | ||
| let quotes_will_change = opening_quote_token | ||
| .text_trimmed() | ||
| .bytes() | ||
| .next() | ||
| .and_then(QuoteStyle::from_byte) | ||
| .is_some_and(|current_quote| current_quote != preferred_quote); | ||
|
|
||
| write_quote_token(&opening_quote_token, preferred_quote, f)?; | ||
|
|
||
| for part in parts { | ||
| match part { | ||
| AnyScssInterpolatedStringPart::ScssInterpolation(interpolation) => { | ||
| interpolation.format().fmt(f)?; | ||
| } | ||
| AnyScssInterpolatedStringPart::ScssStringText(text) => { | ||
| if f.comments().is_suppressed(text.syntax()) { | ||
| text.format().fmt(f)?; | ||
| } else { | ||
| write_string_text(&text, preferred_quote, quotes_will_change, f)?; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| write_quote_token(&closing_quote_token, preferred_quote, f) | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Read-only verification: locate snapshot/tests covering ScssInterpolatedString formatting.
rg -n --type=rs -C2 'ScssInterpolatedString|FormatScssInterpolatedString|interpolated string' -g '**/tests/**'
rg -n --type=rs -C2 'is_suppressed|normalize_string|quote_style' -g '**/tests/**'Repository: biomejs/biome
Length of output: 110
🏁 Script executed:
#!/bin/bash
# Search for SCSS interpolated string test files with corrected syntax
echo "=== Searching for test files related to ScssInterpolatedString ==="
find crates/biome_css_formatter/tests -type f -name "*.rs" -o -name "*.snap" -o -name "*.toml" 2>/dev/null | head -20
echo "=== Searching in tests directory structure ==="
ls -la crates/biome_css_formatter/tests/specs/ 2>/dev/null | head -20
echo "=== Looking for interpolated string references ==="
rg -l "interpolated" crates/biome_css_formatter/tests/ 2>/dev/null || echo "No matches found"
echo "=== Checking snapshot file structure ==="
find crates/biome_css_formatter/tests -name "*.snap" 2>/dev/null | head -10Repository: biomejs/biome
Length of output: 2879
🏁 Script executed:
#!/bin/bash
echo "=== Checking interpolated-string snapshot file ==="
ls -la crates/biome_css_formatter/tests/specs/css/scss/declaration/quote_style/
echo -e "\n=== Content of interpolated-string.scss.snap ==="
head -100 crates/biome_css_formatter/tests/specs/css/scss/declaration/quote_style/interpolated-string.scss.snap
echo -e "\n=== Looking for corresponding input file ==="
find crates/biome_css_formatter/tests/specs/css/scss/declaration/quote_style/ -name "interpolated-string.scss" -type f
echo -e "\n=== Checking if input file exists and list directory ==="
ls -la crates/biome_css_formatter/tests/specs/css/scss/declaration/quote_style/ 2>/dev/nullRepository: biomejs/biome
Length of output: 1502
🏁 Script executed:
#!/bin/bash
echo "=== Full content of interpolated-string.scss input file ==="
cat crates/biome_css_formatter/tests/specs/css/scss/declaration/quote_style/interpolated-string.scss
echo -e "\n=== Searching for suppression-related tests in CSS formatter ==="
rg -l "suppress|is_suppressed" crates/biome_css_formatter/tests/ 2>/dev/null || echo "No suppression tests found"
echo -e "\n=== Listing all quote_style test files ==="
find crates/biome_css_formatter/tests/specs/css/scss/declaration/quote_style/ -type f -name "*.scss"
echo -e "\n=== Checking other SCSS test files for suppression ==="
rg "suppress" crates/biome_css_formatter/tests/specs/css/scss/ -A2 -B2 2>/dev/null || echo "No suppression patterns found"Repository: biomejs/biome
Length of output: 692
Add snapshot test for suppressed interpolated strings.
The basic interpolated string snapshot exists and covers quote style changes correctly. However, the code handles comment suppression (see lines 28–30), but there's no snapshot test for the suppression + quote-change case. Add a test case with biome-ignore or equivalent suppression annotation to verify that suppressed text bypasses the quote rewriting logic.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@crates/biome_css_formatter/src/scss/auxiliary/interpolated_string.rs` around
lines 12 - 49, Add a snapshot test that covers an interpolated SCSS string
containing a suppressed segment (e.g., annotated with biome-ignore) to ensure
suppressed string parts bypass quote-rewriting; specifically craft an input
where preferred_quote_style would normally change quotes and include a
suppressed AnyScssInterpolatedStringPart (so
f.comments().is_suppressed(text.syntax()) returns true) and assert the output
keeps the original text untouched. Place the test alongside other SCSS
interpolated string tests, exercise FormatScssInterpolatedString
(ScssInterpolatedString via the formatter) and verify that write_string_text is
not applied to suppressed text while non-suppressed parts still follow
preferred_quote_style logic.
| let preferred_quote = preferred_quote_style(&parts, f.options().quote_style()); | ||
| let quotes_will_change = opening_quote_token | ||
| .text_trimmed() | ||
| .bytes() | ||
| .next() | ||
| .and_then(QuoteStyle::from_byte) | ||
| .is_some_and(|current_quote| current_quote != preferred_quote); | ||
|
|
||
| write_quote_token(&opening_quote_token, preferred_quote, f)?; | ||
|
|
||
| for part in parts { | ||
| match part { | ||
| AnyScssInterpolatedStringPart::ScssInterpolation(interpolation) => { | ||
| interpolation.format().fmt(f)?; | ||
| } | ||
| AnyScssInterpolatedStringPart::ScssStringText(text) => { | ||
| if f.comments().is_suppressed(text.syntax()) { | ||
| text.format().fmt(f)?; | ||
| } else { | ||
| write_string_text(&text, preferred_quote, quotes_will_change, f)?; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| write_quote_token(&closing_quote_token, preferred_quote, f) |
There was a problem hiding this comment.
Quote rewrites should be disabled when any string-text part is suppressed.
At Line 30 and Line 47, quotes are rewritten even if Line 38 detects a suppressed ScssStringText and Line 39 keeps its raw token. That can leave escaping in an invalid state after quote flipping.
Suggested fix
- let preferred_quote = preferred_quote_style(&parts, f.options().quote_style());
- let quotes_will_change = opening_quote_token
+ let current_quote = opening_quote_token
.text_trimmed()
.bytes()
.next()
- .and_then(QuoteStyle::from_byte)
- .is_some_and(|current_quote| current_quote != preferred_quote);
+ .and_then(QuoteStyle::from_byte);
+
+ let has_suppressed_text = parts.iter().any(|part| {
+ matches!(
+ part,
+ AnyScssInterpolatedStringPart::ScssStringText(text)
+ if f.comments().is_suppressed(text.syntax())
+ )
+ });
+
+ let preferred_quote = if has_suppressed_text {
+ current_quote.unwrap_or_else(|| f.options().quote_style())
+ } else {
+ preferred_quote_style(&parts, f.options().quote_style())
+ };
+
+ let quotes_will_change = current_quote.is_some_and(|quote| quote != preferred_quote);
@@
- AnyScssInterpolatedStringPart::ScssStringText(text) => {
- if f.comments().is_suppressed(text.syntax()) {
+ AnyScssInterpolatedStringPart::ScssStringText(text) => {
+ if has_suppressed_text || f.comments().is_suppressed(text.syntax()) {
text.format().fmt(f)?;
} else {
write_string_text(&text, preferred_quote, quotes_will_change, f)?;
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let preferred_quote = preferred_quote_style(&parts, f.options().quote_style()); | |
| let quotes_will_change = opening_quote_token | |
| .text_trimmed() | |
| .bytes() | |
| .next() | |
| .and_then(QuoteStyle::from_byte) | |
| .is_some_and(|current_quote| current_quote != preferred_quote); | |
| write_quote_token(&opening_quote_token, preferred_quote, f)?; | |
| for part in parts { | |
| match part { | |
| AnyScssInterpolatedStringPart::ScssInterpolation(interpolation) => { | |
| interpolation.format().fmt(f)?; | |
| } | |
| AnyScssInterpolatedStringPart::ScssStringText(text) => { | |
| if f.comments().is_suppressed(text.syntax()) { | |
| text.format().fmt(f)?; | |
| } else { | |
| write_string_text(&text, preferred_quote, quotes_will_change, f)?; | |
| } | |
| } | |
| } | |
| } | |
| write_quote_token(&closing_quote_token, preferred_quote, f) | |
| let current_quote = opening_quote_token | |
| .text_trimmed() | |
| .bytes() | |
| .next() | |
| .and_then(QuoteStyle::from_byte); | |
| let has_suppressed_text = parts.iter().any(|part| { | |
| matches!( | |
| part, | |
| AnyScssInterpolatedStringPart::ScssStringText(text) | |
| if f.comments().is_suppressed(text.syntax()) | |
| ) | |
| }); | |
| let preferred_quote = if has_suppressed_text { | |
| current_quote.unwrap_or_else(|| f.options().quote_style()) | |
| } else { | |
| preferred_quote_style(&parts, f.options().quote_style()) | |
| }; | |
| let quotes_will_change = current_quote.is_some_and(|quote| quote != preferred_quote); | |
| write_quote_token(&opening_quote_token, preferred_quote, f)?; | |
| for part in parts { | |
| match part { | |
| AnyScssInterpolatedStringPart::ScssInterpolation(interpolation) => { | |
| interpolation.format().fmt(f)?; | |
| } | |
| AnyScssInterpolatedStringPart::ScssStringText(text) => { | |
| if has_suppressed_text || f.comments().is_suppressed(text.syntax()) { | |
| text.format().fmt(f)?; | |
| } else { | |
| write_string_text(&text, preferred_quote, quotes_will_change, f)?; | |
| } | |
| } | |
| } | |
| } | |
| write_quote_token(&closing_quote_token, preferred_quote, f) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@crates/biome_css_formatter/src/scss/auxiliary/interpolated_string.rs` around
lines 22 - 47, The code currently flips quotes via preferred_quote_style and
write_quote_token even when some ScssStringText parts are suppressed (detected
by f.comments().is_suppressed), which can leave escapes invalid; modify the
logic in interpolated_string formatting so that you detect if any
AnyScssInterpolatedStringPart::ScssStringText is suppressed (e.g., compute a
boolean like any_text_suppressed by iterating parts and calling
f.comments().is_suppressed(text.syntax()) before deciding on quotes), and if so
disable quote rewriting by forcing quotes_will_change to false (or use the
original quote style when calling write_quote_token for opening_quote_token and
closing_quote_token) and skip changing quotes in write_string_text, keeping
existing behavior for interpolations and non-suppressed text.
Summary
This PR merges main into next, so that hopefully when we want to release the next minor, it won't be that bad.
Generated by gpt 5.4
Here is the agent's summary (its very verbose)
Conflict Areas And Decisions
1.
RuleSourcemerge incrates/biome_analyze/src/rule.rsThe branch had both a new
RuleSourceVariantIndexderive macro and an older hand-writtenvariant_index()implementation.Duplicate method definitions, ambiguous method resolution, and a stale manual match missing newer enum variants.
Keep the derive-based implementation and remove the manual
variant_index()implementation.The derive is the newer source of truth and avoids future drift when enum variants are added.
2.
BiomeEnvand formatter override conflictscrates/biome_flags/src/lib.rs,crates/biome_configuration/src/formatter.rs,crates/biome_configuration/src/overrides.rsThe merge combined older field-level implementations with newer static-table/config-attribute patterns.
Kept the newer
BiomeEnv::ENV_VARIABLES/value_forstructure and restored the missingBIOME_DISTRIBUTIONvariable.Wrapped new
bpaffield attributes with#[cfg_attr(feature = "cli", ...)].Those patterns match the surrounding code and compile cleanly in both CLI and non-CLI builds.
3. Analyzer/service API drift in CSS and HTML handlers
crates/biome_service/src/file_handlers/css.rscrates/biome_service/src/file_handlers/html.rsmainhad newer analyzer service types and code-action plumbing, while the branch still used older call patterns.Updated service initializers and analyzer calls to include the newer fields and arguments:
module_graph,project_layout,compute_actions, andHtmlAnalyzerServices.This preserved the newer analyzer behavior instead of regressing to older signatures.
4. HTML embedded-language parsing changes
crates/biome_service/src/file_handlers/html/parse_embedded_nodes.rsThe branch had older embed helper signatures, but
mainintroduced a newis_class_attributebit onEmbedCandidate::DirectiveandEmbeddingKind::Astro.Threaded
is_class_attributethrough the relevant builders and Astro embedding logic.For Astro/plain HTML expression attributes, class-related attributes are detected and passed through.
This matches the newer embedding model and avoids losing framework-specific semantics.
5. Svelte member-property AST addition
crates/biome_html_analyze/src/assist/source/use_sorted_attributes.rsA new
AnySvelteBindingProperty::SvelteMemberPropertyvariant existed, but an assist match still assumed only literal/name variants.Handle
SvelteMemberPropertyby sorting on its terminalmember()identifier.This is the smallest behavior-preserving fix and aligns with how simple binding names are already compared.
6. CSS analyzer service expansion
crates/biome_service/src/file_handlers/css.rsCssAnalyzerServicesgainedmodule_graphandproject_layoutfields.Populate those fields in all CSS analysis phases, including suppression and final diagnostic passes.
Keeping the fields populated is safer than mixing partially initialized service objects across phases.
7. Diagnostics parameter rename and expansion
crates/biome_service/src/workspace/server.tests.rscrates/biome_service/src/workspace.tests.rsTest code still used
pull_code_actions, but the active API now expectsinclude_code_fixand also requiresmax_diagnostics,diagnostic_level, andenforce_assist.Renamed
pull_code_actionstoinclude_code_fixand added explicit defaults:max_diagnostics: None,diagnostic_level: Severity::Hint,enforce_assist: false.I copied the defaults already used by nearby passing tests instead of inventing new behavior.
8. Analyzer signal API update
crates/biome_json_analyze/tests/compat_sortpkg_tests.rsevent.actions()now requires anActionFilterargument.Updated the test to use
event.actions(ActionFilter::all()).This matches the rest of the codebase and preserves the prior test intent.
9. CLI crawler API update
crates/biome_cli/src/runner/mod.rsThe watch-mode crawler path still used the older
Crawler::crawlsignature.Passed
execution.get_max_diagnostics(cli_options)andcli_options.diagnostic_levelin watch mode too.This keeps watch-mode aligned with the normal execution path and the updated crawler interface.
10. Reporter snapshot updates
crates/biome_cli/tests/snapshots/main_cases_reporter_concise/*.snapAfter the code compiled, three snapshot tests still failed because
noRedeclarediagnostics now use newer, shorter wording.Updated the three concise reporter snapshots to the current output and removed the temporary
.snap.newfiles.These were legitimate output changes, not merge mistakes.
11.
server.tests.rsconflict handlingcrates/biome_service/src/workspace/server.tests.rsOne large conflict was effectively overlapping append-only test additions from both sides.
During initial conflict resolution, I took the current branch version for that conflicted test file so the merge could complete, then fixed compile/test drift afterward in-place.
That was the least risky way to avoid accidentally interleaving unrelated test blocks by hand during the raw merge.
Test Plan
green ci, with probably no snapshot changes?
Guide for Reviewing
aab36ae is the merge commit. The clanker was told simply to "resolve merge conflicts".
Anything after that is things that the clanker didn't fix initially, and likely needs the most attention.
In general, this PR should be mostly additions, not deletions. If you see a bunch of deletions, that might be something to look at a little more closely.
Docs