Skip to content

fix(css): parse scroll-state and general-enclosed queries#9284

Merged
denbezrukov merged 2 commits intomainfrom
dbezrukov/scss-mode
Mar 2, 2026
Merged

fix(css): parse scroll-state and general-enclosed queries#9284
denbezrukov merged 2 commits intomainfrom
dbezrukov/scss-mode

Conversation

@denbezrukov
Copy link
Copy Markdown
Contributor

@denbezrukov denbezrukov commented Mar 1, 2026

This PR was created with AI assistance (Codex).

The root issue was that parsing fallback paths for unknown/general-enclosed syntax used
SCSS-aware value parsing even in .css files.
That caused false-positive diagnostics like “Expected a SCSS expression” for CSS
constructs.

This change splits value parsing into two modes:

  • ScssAware (used where SCSS syntax is actually allowed)
  • CssOnly (used in CSS general-enclosed fallback branches)

I'd like to try to keep parse_exclusive_syntax because it's useful because it gives both:

  1. a precise SCSS-only diagnostic, and
  2. better parser recovery (consume as one unit, fewer cascading errors).

Test Plan

  • cargo test -p biome_css_parser
  • cargo test -p biome_css_formatter

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 1, 2026

🦋 Changeset detected

Latest commit: 8f24677

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

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

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

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

@github-actions github-actions bot added A-Parser Area: parser A-Formatter Area: formatter L-CSS Language: CSS and super languages labels Mar 1, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 1, 2026

Walkthrough

This PR fixes false-positive diagnostics for valid @container and @supports general‑enclosed queries by introducing context‑aware value parsing (ValueParsingMode / ValueParsingContext) and switching general‑enclosed fallbacks to a CSS‑only value parser. parse_any_container_query_in_parens now accepts an optional chain token for correct chain‑token recovery; function/url parsing helpers were made context‑aware and CSS‑only helpers (e.g., parse_any_css_value, is_at_any_css_function, is_nth_at_css_function) were added. Multiple tests for container scroll‑state, container general‑enclosed and supports general‑enclosed were added.

Possibly related PRs

Suggested reviewers

  • dyc3
  • ematipico
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: fixing parsing of scroll-state and general-enclosed queries in CSS, which directly addresses the false-positive diagnostics issue outlined in the description.
Description check ✅ Passed The description clearly explains the root issue (SCSS-aware parsing in CSS fallback paths causing false-positives), the solution (splitting value parsing into ScssAware and CssOnly modes), and includes a test plan.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dbezrukov/scss-mode

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

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/biome_css_parser/src/syntax/value/function.rs`:
- Around line 432-435: The recovery currently used by
ComponentValueExpressionList::recover and the
parsed_element.or_recover_with_token_set call only stops at ) and ; and
therefore can over-consume past commas or binary-operator boundaries; update the
recovery token set passed to parsed_element.or_recover_with_token_set (and the
recovery logic in ComponentValueExpressionList::recover) to also include comma
and binary-operator tokens (e.g. T![,], T![+], T![-], T![*], T![/] or your
project's equivalent operator token symbols) so recovery will stop at argument
separators and operators instead of swallowing the rest of the expression.
Ensure you reference and modify the ParseRecoveryTokenSet construction used in
the shown call and any corresponding recover method to include these tokens.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e43e730 and b7ea069.

⛔ Files ignored due to path filters (11)
  • crates/biome_css_formatter/tests/specs/css/scss/at-rule/container-general-enclosed.scss.snap is excluded by !**/*.snap and included by **
  • crates/biome_css_formatter/tests/specs/css/scss/at-rule/supports-general-enclosed.scss.snap is excluded by !**/*.snap and included by **
  • crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_general_enclosed_error.css.snap is excluded by !**/*.snap and included by **
  • crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_scroll_state_error.css.snap is excluded by !**/*.snap and included by **
  • crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_supports/at_rule_supports_general_enclosed_error.css.snap is excluded by !**/*.snap and included by **
  • crates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/container-general-enclosed.scss.snap is excluded by !**/*.snap and included by **
  • crates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/supports-general-enclosed.scss.snap is excluded by !**/*.snap and included by **
  • crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container_general_enclosed.css.snap is excluded by !**/*.snap and included by **
  • crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container_scroll_state.css.snap is excluded by !**/*.snap and included by **
  • crates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/container-general-enclosed.scss.snap is excluded by !**/*.snap and included by **
  • crates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/container-scroll-state.scss.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (17)
  • .changeset/fix-false-positive-container-query-diagnostics.md
  • crates/biome_css_formatter/tests/specs/css/scss/at-rule/container-general-enclosed.scss
  • crates/biome_css_formatter/tests/specs/css/scss/at-rule/supports-general-enclosed.scss
  • crates/biome_css_parser/src/syntax/at_rule/container/mod.rs
  • crates/biome_css_parser/src/syntax/at_rule/supports/mod.rs
  • crates/biome_css_parser/src/syntax/mod.rs
  • crates/biome_css_parser/src/syntax/value/function.rs
  • crates/biome_css_parser/src/syntax/value/url.rs
  • crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_general_enclosed_error.css
  • crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_scroll_state_error.css
  • crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_supports/at_rule_supports_general_enclosed_error.css
  • crates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/container-general-enclosed.scss
  • crates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/supports-general-enclosed.scss
  • crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container_general_enclosed.css
  • crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container_scroll_state.css
  • crates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/container-general-enclosed.scss
  • crates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/container-scroll-state.scss

Comment thread crates/biome_css_parser/src/syntax/value/function.rs
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Mar 1, 2026

Merging this PR will not alter performance

✅ 29 untouched benchmarks
⏩ 187 skipped benchmarks1


Comparing dbezrukov/scss-mode (8f24677) with main (e43e730)

Open in CodSpeed

Footnotes

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
crates/biome_css_parser/src/syntax/value/function.rs (2)

114-119: Hardcoded offset of n + 3 for SCSS qualified names.

This assumes SCSS qualified names are always exactly 3 tokens. If the structure ever changes, this will silently break. Consider adding a brief comment clarifying the expected token structure (e.g., namespace.name).

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

In `@crates/biome_css_parser/src/syntax/value/function.rs` around lines 114 - 119,
The check using a hardcoded offset n + 3 when validating SCSS qualified names
can break if token layout changes; update the code around the function that
returns bool (the block that calls is_nth_at_identifier,
context.is_scss_syntax_allowed(), and is_nth_at_scss_qualified_name) to add a
short clarifying comment explaining the expected token layout for SCSS qualified
names (e.g., "expects namespace . name => tokens: IDENT, '.', IDENT, '(' so we
check n+3 for '('"), and keep the existing n + 3 check but document why that
offset is used so future readers know the assumed structure; reference
is_nth_at_scss_qualified_name and the p.nth_at(n + 3, T!['(']) call when adding
the comment.

83-91: Consider adding rustdoc for consistency.

is_at_css_function and is_at_function_with_context lack documentation whilst similar functions like is_at_function (line 74-77) have it. A brief doc comment would aid discoverability.

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

In `@crates/biome_css_parser/src/syntax/value/function.rs` around lines 83 - 91,
Add brief rustdoc comments for the two helper functions so their intent matches
surrounding documented APIs: document is_at_css_function(p: &mut CssParser) to
state it checks for a simple function head in CSS-only mode and document
is_at_function_with_context(p: &mut CssParser, context: ValueParsingContext) to
state it checks for a function head using the supplied ValueParsingContext (and
mention that it excludes url() via its implementation). Keep the comments
concise and consistent in style with the existing doc on is_at_function.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/biome_css_parser/src/syntax/value/function.rs`:
- Around line 114-119: The check using a hardcoded offset n + 3 when validating
SCSS qualified names can break if token layout changes; update the code around
the function that returns bool (the block that calls is_nth_at_identifier,
context.is_scss_syntax_allowed(), and is_nth_at_scss_qualified_name) to add a
short clarifying comment explaining the expected token layout for SCSS qualified
names (e.g., "expects namespace . name => tokens: IDENT, '.', IDENT, '(' so we
check n+3 for '('"), and keep the existing n + 3 check but document why that
offset is used so future readers know the assumed structure; reference
is_nth_at_scss_qualified_name and the p.nth_at(n + 3, T!['(']) call when adding
the comment.
- Around line 83-91: Add brief rustdoc comments for the two helper functions so
their intent matches surrounding documented APIs: document is_at_css_function(p:
&mut CssParser) to state it checks for a simple function head in CSS-only mode
and document is_at_function_with_context(p: &mut CssParser, context:
ValueParsingContext) to state it checks for a function head using the supplied
ValueParsingContext (and mention that it excludes url() via its implementation).
Keep the comments concise and consistent in style with the existing doc on
is_at_function.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b7ea069 and 8f24677.

⛔ Files ignored due to path filters (1)
  • crates/biome_css_parser/tests/css_test_suite/error/function/component_value_expression_recovery.css.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (2)
  • crates/biome_css_parser/src/syntax/value/function.rs
  • crates/biome_css_parser/tests/css_test_suite/error/function/component_value_expression_recovery.css

@denbezrukov denbezrukov merged commit ec3a17f into main Mar 2, 2026
17 checks passed
@denbezrukov denbezrukov deleted the dbezrukov/scss-mode branch March 2, 2026 12:55
@github-actions github-actions bot mentioned this pull request Mar 2, 2026
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