Skip to content

feat(css_formatter): improve formatting for SCSS parenthesized expressions and include arguments - #10269

Merged
denbezrukov merged 1 commit into
mainfrom
db/scss-formatter-17
May 6, 2026
Merged

denbezrukov merged 1 commit into
mainfrom
db/scss-formatter-17

Conversation

@denbezrukov

Copy link
Copy Markdown
Contributor

This PR was created with AI assistance (Codex).

Summary

Improves SCSS formatter output for parenthesized expressions, map/list values, and @include keyword arguments to better match Prettier.

Example output:

$map: (
	key: (
		#d82d2d,
		#666,
	),
	other-key: (
		#52bf4a,
		#fff,
	),
);

@include container(
	$foo: (
		$bar + $baz,
		$qux * 2,
	)
);

$map: (
	very-very-very-very-very-very-very-verylong-key:
		very-very-very-very-very-very-very-verylong-value,
	other-key: other-value,
);

Test Plan

  • cargo test -p biome_css_formatter

@changeset-bot

changeset-bot Bot commented May 5, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 1746f6d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@github-actions github-actions Bot added A-Parser Area: parser A-Formatter Area: formatter L-CSS Language: CSS and super languages labels May 5, 2026
@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR refactors SCSS formatting logic for parenthesised expressions, binary expressions, and list layouts. It introduces new layout helpers to centralise parenthesised-expression and include-keyword-argument formatting decisions, replaces the scss_map_context function with the ScssMapContext::from_node method, and removes the ScssMapOuterParenthesizedValuePayloadKind enum in favour of separate predicate functions. The changes improve indentation, trailing-comma handling, and expansion logic across parenthesised, list, and map contexts whilst maintaining existing formatting behaviour.

Possibly related PRs

  • biomejs/biome#10217: Modifies SCSS parenthesised-list and map formatting with changes to ScssListLayout::fmt behaviour for outer-parenthesised value lists.
  • biomejs/biome#10207: Refactors SCSS parenthesised and map formatting with overlapping changes to parenthesised-value detection and layout helpers.
  • biomejs/biome#10150: Modifies SCSS include-argument formatting and separator/comment handling for parenthesised expressions and lists.

Suggested labels

A-Formatter, L-CSS

Suggested reviewers

  • dyc3
  • ematipico
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: improving SCSS parenthesized expression and include argument formatting.
Description check ✅ Passed The description clearly relates to the changeset, providing concrete examples of improved formatting and test plan.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch db/scss-formatter-17

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

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
crates/biome_css_formatter/src/utils/scss_list_layout.rs (1)

205-240: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Keep keyword-comment expansion scoped to the direct value list.

scss_include_keyword_argument_owner(...) is ancestor-based, so a nested list inside something like $arg: (key: (a, b)) /* end */ can inherit the outer keyword argument’s dangling comment here and get forced into the include-value layout as well. That leaks outer comment ownership into inner lists that should stay inline.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/biome_css_formatter/src/utils/scss_list_layout.rs` around lines 205 -
240, The issue is that scss_include_keyword_argument_owner is being run against
ancestor parenthesized expressions and can surface an outer keyword argument for
nested lists; in is_include_keyword_list_value_expanded_by_comments restrict the
keyword-argument lookup to the immediate parenthesized wrapper only (use
node.syntax().parent().and_then(ScssParenthesizedExpression::cast) instead of
ancestors().skip(1).find_map(...)) and only call
scss_include_keyword_argument_owner on that immediate parenthesized (or directly
on node.syntax() in the no-parenthesized branch) so dangling-comment ownership
is scoped to the direct value list.
🧹 Nitpick comments (1)
crates/biome_css_formatter/src/utils/scss_include_keyword_value.rs (1)

27-36: 💤 Low value

descendants() walk with per-node scss_include_keyword_argument_owner calls is O(n·d) — acceptable for typical SCSS.

No action needed; just flagging it as a future hot-spot if people start writing deeply nested SCSS maps.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/biome_css_formatter/src/utils/scss_include_keyword_value.rs` around
lines 27 - 36, No code change required for correctness, but annotate the
potential O(n·d) hotspot: add a brief comment near the traversal in
scss_include_keyword_value (the block using
value.syntax().descendants().filter_map(ScssParenthesizedExpression::cast).any(...))
noting that repeated calls to scss_include_keyword_argument_owner for each
descendant can become O(n·d) on deeply nested SCSS maps and may need
optimization later (e.g., caching owner lookups or switching to a single
traversal that computes owners and nesting with
is_nested_in_keyword_parentheses).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/biome_css_syntax/src/lib.rs`:
- Around line 19-24: You removed ScssMapOuterParenthesizedValuePayloadKind and
scss_map_context from the pub use list in lib.rs which is semver-breaking for
published crates; either restore those two exports (re-add
ScssMapOuterParenthesizedValuePayloadKind and scss_map_context to the pub use
block that contains ScssMapContext, ScssMapPositionKind, ScssMapRole, etc.) so
existing downstream users keep compatibility, or if the removal is intentional,
update the crate version (major/minor as appropriate) and add a changelog entry
noting the removal before publishing.

In `@crates/biome_css_syntax/src/scss_ext/map.rs`:
- Around line 54-85: Add runnable doctest examples to the doc comments for the
map-shape classifier functions (e.g., is_scss_map_outer_parenthesized_value_map
and is_scss_map_outer_parenthesized_value_list and the similar functions around
the other map helpers) by replacing or augmenting the prose examples with Rust
doc code blocks (/// ```rust ... ``` ) that construct minimal Scss AST nodes (or
call existing test helpers) and assert the expected boolean result; ensure the
examples compile by importing or referencing any helper constructors in the
doctest prelude (or use fully-qualified paths) and keep the examples focused
(one assertion per example) so they run as doctests during cargo test.

---

Outside diff comments:
In `@crates/biome_css_formatter/src/utils/scss_list_layout.rs`:
- Around line 205-240: The issue is that scss_include_keyword_argument_owner is
being run against ancestor parenthesized expressions and can surface an outer
keyword argument for nested lists; in
is_include_keyword_list_value_expanded_by_comments restrict the keyword-argument
lookup to the immediate parenthesized wrapper only (use
node.syntax().parent().and_then(ScssParenthesizedExpression::cast) instead of
ancestors().skip(1).find_map(...)) and only call
scss_include_keyword_argument_owner on that immediate parenthesized (or directly
on node.syntax() in the no-parenthesized branch) so dangling-comment ownership
is scoped to the direct value list.

---

Nitpick comments:
In `@crates/biome_css_formatter/src/utils/scss_include_keyword_value.rs`:
- Around line 27-36: No code change required for correctness, but annotate the
potential O(n·d) hotspot: add a brief comment near the traversal in
scss_include_keyword_value (the block using
value.syntax().descendants().filter_map(ScssParenthesizedExpression::cast).any(...))
noting that repeated calls to scss_include_keyword_argument_owner for each
descendant can become O(n·d) on deeply nested SCSS maps and may need
optimization later (e.g., caching owner lookups or switching to a single
traversal that computes owners and nesting with
is_nested_in_keyword_parentheses).
🪄 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: a5f921f4-3c01-4f75-8710-2919e750b88e

📥 Commits

Reviewing files that changed from the base of the PR and between 3bd2b6a and 1746f6d.

⛔ Files ignored due to path filters (2)
  • crates/biome_css_formatter/tests/specs/prettier/scss/math/7419.scss.snap is excluded by !**/*.snap and included by **
  • crates/biome_css_formatter/tests/specs/scss/at-rule/include-arguments.scss.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (12)
  • crates/biome_css_formatter/src/scss/auxiliary/binary_expression.rs
  • crates/biome_css_formatter/src/scss/auxiliary/parenthesized_expression.rs
  • crates/biome_css_formatter/src/utils/mod.rs
  • crates/biome_css_formatter/src/utils/scss_control_condition.rs
  • crates/biome_css_formatter/src/utils/scss_include_keyword_value.rs
  • crates/biome_css_formatter/src/utils/scss_keyword_argument_layout.rs
  • crates/biome_css_formatter/src/utils/scss_list_layout.rs
  • crates/biome_css_formatter/src/utils/scss_separator_comments.rs
  • crates/biome_css_formatter/tests/specs/scss/at-rule/include-arguments.scss
  • crates/biome_css_syntax/src/lib.rs
  • crates/biome_css_syntax/src/scss_ext/map.rs
  • crates/biome_css_syntax/src/scss_ext/mod.rs

Comment thread crates/biome_css_syntax/src/lib.rs
Comment thread crates/biome_css_syntax/src/scss_ext/map.rs
@codspeed

codspeed Bot commented May 5, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 29 untouched benchmarks
⏩ 227 skipped benchmarks1


Comparing db/scss-formatter-17 (1746f6d) with main (c5d7d89)

Open in CodSpeed

Footnotes

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

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

Labels

A-Formatter Area: formatter A-Parser Area: parser L-CSS Language: CSS and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant