feat(css): add support for SCSS @use and @forward at-rules#9440
feat(css): add support for SCSS @use and @forward at-rules#9440denbezrukov merged 13 commits intomainfrom
@use and @forward at-rules#9440Conversation
|
Parser conformance results onjs/262
jsx/babel
markdown/commonmark
symbols/microsoft
ts/babel
ts/microsoft
|
Merging this PR will not alter performance
Comparing Footnotes
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds comprehensive SCSS Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
crates/biome_css_parser/src/syntax/scss/at_rule/parameter.rs (1)
21-30: Please turn these rustdoc samples into doctests.The new
scssfences help readers, but they won't be exercised by rustdoc and can drift quietly.As per coding guidelines, "Use doc tests (doctest) format with code blocks in rustdoc comments; ensure assertions pass in tests".
Also applies to: 69-78
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_css_parser/src/syntax/scss/at_rule/parameter.rs` around lines 21 - 30, The SCSS code fences in the doc comment for the SCSS parameter parser are using ```scss which prevents rustdoc from running them; update those examples in parameter.rs to be actual doctests by replacing the ```scss fences with Rust doctest fences (use ```rust or an unlabelled ``` so rustdoc treats them as tests) and convert the sample into a small Rust doctest that invokes the parser API (replace the SCSS snippet with a Rust example that calls the relevant parsing function in this module and asserts expected output), and do the same for the other sample at lines 69-78 so both examples are exercised by rustdoc and their assertions pass.crates/biome_css_parser/src/syntax/scss/at_rule/module_clauses.rs (1)
182-232: Consider addingdiagnose_missing_elementfor configuration item lists.Unlike
ScssModuleMemberList, this implementation doesn't overridediagnose_missing_element. If a trailing comma appears before), the default diagnostic may be less helpful than a custom message like "Expected a configuration item after,".♻️ Optional: Add custom diagnostic for missing elements
fn allow_empty(&self) -> bool { false } + + fn diagnose_missing_element(&mut self, p: &mut Self::Parser<'_>) { + p.error(expected_scss_module_configuration(p, p.cur_range())); + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_css_parser/src/syntax/scss/at_rule/module_clauses.rs` around lines 182 - 232, ScssModuleConfigurationItemList lacks a custom diagnose_missing_element override, so when a trailing comma appears before ')' users get the generic diagnostic; implement diagnose_missing_element on ScssModuleConfigurationItemList (similar to ScssModuleMemberList) to call p.err_with_diagnostic or emit a specific message like "Expected a configuration item after `,`" and reference the separating element T![,] and LIST_KIND SCSS_MODULE_CONFIGURATION_ITEM_LIST so the parser reports the precise missing-element diagnostic for configuration item lists.
🤖 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/scss/at_rule/forward_at_rule.rs`:
- Around line 68-71: The code currently makes the hyphen optional in the "as
<prefix>-*" sequence by calling p.eat(T![-]) which accepts absence of '-' —
change this to p.expect(T![-]) so the parser requires the literal hyphen; update
the sequence around p.bump(T![as]) /
parse_regular_identifier(p).or_add_diagnostic(p, expected_identifier) to call
p.expect(T![-]) before p.expect(T![*]) to enforce the Sass spec requirement for
"as <prefix>-*".
---
Nitpick comments:
In `@crates/biome_css_parser/src/syntax/scss/at_rule/module_clauses.rs`:
- Around line 182-232: ScssModuleConfigurationItemList lacks a custom
diagnose_missing_element override, so when a trailing comma appears before ')'
users get the generic diagnostic; implement diagnose_missing_element on
ScssModuleConfigurationItemList (similar to ScssModuleMemberList) to call
p.err_with_diagnostic or emit a specific message like "Expected a configuration
item after `,`" and reference the separating element T![,] and LIST_KIND
SCSS_MODULE_CONFIGURATION_ITEM_LIST so the parser reports the precise
missing-element diagnostic for configuration item lists.
In `@crates/biome_css_parser/src/syntax/scss/at_rule/parameter.rs`:
- Around line 21-30: The SCSS code fences in the doc comment for the SCSS
parameter parser are using ```scss which prevents rustdoc from running them;
update those examples in parameter.rs to be actual doctests by replacing the
```scss fences with Rust doctest fences (use ```rust or an unlabelled ``` so
rustdoc treats them as tests) and convert the sample into a small Rust doctest
that invokes the parser API (replace the SCSS snippet with a Rust example that
calls the relevant parsing function in this module and asserts expected output),
and do the same for the other sample at lines 69-78 so both examples are
exercised by rustdoc and their assertions pass.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b5685968-edc4-4589-868c-86ccaad9e1fd
⛔ Files ignored due to path filters (12)
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**crates/biome_css_formatter/tests/specs/css/scss/at-rule/forward.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_formatter/tests/specs/css/scss/at-rule/use.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/forward.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/use.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/forward.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/use.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_syntax/src/generated/kind.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_css_syntax/src/generated/macros.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_css_syntax/src/generated/nodes.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_css_syntax/src/generated/nodes_mut.rsis excluded by!**/generated/**,!**/generated/**and included by**
📒 Files selected for processing (46)
crates/biome_css_formatter/src/css/any/at_rule.rscrates/biome_css_formatter/src/css/any/ts_type.rscrates/biome_css_formatter/src/css/bogus/bogus_declaration_item.rscrates/biome_css_formatter/src/css/bogus/bogus_type.rscrates/biome_css_formatter/src/css/bogus/mod.rscrates/biome_css_formatter/src/generated.rscrates/biome_css_formatter/src/scss/any/forward_visibility_clause.rscrates/biome_css_formatter/src/scss/any/mod.rscrates/biome_css_formatter/src/scss/any/module_configuration.rscrates/biome_css_formatter/src/scss/any/use_namespace.rscrates/biome_css_formatter/src/scss/auxiliary/forward_as_clause.rscrates/biome_css_formatter/src/scss/auxiliary/hide_clause.rscrates/biome_css_formatter/src/scss/auxiliary/mod.rscrates/biome_css_formatter/src/scss/auxiliary/module_configuration.rscrates/biome_css_formatter/src/scss/auxiliary/module_configuration_list.rscrates/biome_css_formatter/src/scss/auxiliary/show_clause.rscrates/biome_css_formatter/src/scss/auxiliary/use_all_namespace.rscrates/biome_css_formatter/src/scss/auxiliary/use_as_clause.rscrates/biome_css_formatter/src/scss/auxiliary/with_clause.rscrates/biome_css_formatter/src/scss/lists/mod.rscrates/biome_css_formatter/src/scss/lists/module_configuration_item_list.rscrates/biome_css_formatter/src/scss/lists/module_member_list.rscrates/biome_css_formatter/src/scss/statements/forward_at_rule.rscrates/biome_css_formatter/src/scss/statements/mod.rscrates/biome_css_formatter/src/scss/statements/use_at_rule.rscrates/biome_css_formatter/tests/specs/css/scss/at-rule/forward.scsscrates/biome_css_formatter/tests/specs/css/scss/at-rule/use.scsscrates/biome_css_parser/src/lexer/mod.rscrates/biome_css_parser/src/syntax/at_rule/mod.rscrates/biome_css_parser/src/syntax/scss/at_rule/content_at_rule.rscrates/biome_css_parser/src/syntax/scss/at_rule/forward_at_rule.rscrates/biome_css_parser/src/syntax/scss/at_rule/include_at_rule.rscrates/biome_css_parser/src/syntax/scss/at_rule/mod.rscrates/biome_css_parser/src/syntax/scss/at_rule/module_clauses.rscrates/biome_css_parser/src/syntax/scss/at_rule/parameter.rscrates/biome_css_parser/src/syntax/scss/at_rule/use_at_rule.rscrates/biome_css_parser/src/syntax/scss/mod.rscrates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/forward.scsscrates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/use.scsscrates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/forward.scsscrates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/use.scsscrates/biome_css_syntax/src/lib.rscrates/biome_grit_patterns/src/grit_target_language/css_target_language/generated_mappings.rscrates/biome_parser/src/parse_lists.rsxtask/codegen/css.ungramxtask/codegen/src/css_kinds_src.rs
💤 Files with no reviewable changes (5)
- crates/biome_css_formatter/src/css/bogus/mod.rs
- crates/biome_css_formatter/src/css/any/ts_type.rs
- crates/biome_css_formatter/src/css/bogus/bogus_type.rs
- crates/biome_css_syntax/src/lib.rs
- crates/biome_css_formatter/src/css/bogus/bogus_declaration_item.rs
There was a problem hiding this comment.
♻️ Duplicate comments (1)
crates/biome_css_parser/src/syntax/scss/at_rule/forward_at_rule.rs (1)
66-69:⚠️ Potential issue | 🟠 MajorThe hyphen in
as <prefix>-*should be required, not optional.The Sass specification mandates
as <prefix>-*with a literal hyphen. Usingp.eat(T![-])allows the parser to accept invalid syntax like@forward "theme" as foo*;.🐛 Proposed fix
p.bump(T![as]); parse_regular_identifier(p).or_add_diagnostic(p, expected_identifier); - p.eat(T![-]); + p.expect(T![-]); p.expect(T![*]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_css_parser/src/syntax/scss/at_rule/forward_at_rule.rs` around lines 66 - 69, The hyphen in the `as <prefix>-*` production is currently optional because the code uses `p.eat(T![-])`; change this to require the hyphen by replacing `p.eat(T![-])` with `p.expect(T![-])` (keeping the surrounding calls: `parse_regular_identifier(p).or_add_diagnostic(p, expected_identifier)` and `p.expect(T![*])`) so the parser rejects inputs like `@forward "theme" as foo*;` and reports a proper diagnostic when the hyphen is missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@crates/biome_css_parser/src/syntax/scss/at_rule/forward_at_rule.rs`:
- Around line 66-69: The hyphen in the `as <prefix>-*` production is currently
optional because the code uses `p.eat(T![-])`; change this to require the hyphen
by replacing `p.eat(T![-])` with `p.expect(T![-])` (keeping the surrounding
calls: `parse_regular_identifier(p).or_add_diagnostic(p, expected_identifier)`
and `p.expect(T![*])`) so the parser rejects inputs like `@forward "theme" as
foo*;` and reports a proper diagnostic when the hyphen is missing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 94533b6a-c0c9-454b-b888-d9bc00877b26
📒 Files selected for processing (7)
crates/biome_css_formatter/src/scss/auxiliary/hide_clause.rscrates/biome_css_formatter/src/scss/auxiliary/module_configuration.rscrates/biome_css_formatter/src/scss/auxiliary/show_clause.rscrates/biome_css_formatter/src/scss/auxiliary/use_as_clause.rscrates/biome_css_parser/src/syntax/scss/at_rule/forward_at_rule.rscrates/biome_css_parser/src/syntax/scss/at_rule/module_clauses.rscrates/biome_css_parser/src/syntax/scss/at_rule/use_at_rule.rs
🚧 Files skipped from review as they are similar to previous changes (3)
- crates/biome_css_formatter/src/scss/auxiliary/module_configuration.rs
- crates/biome_css_formatter/src/scss/auxiliary/show_clause.rs
- crates/biome_css_formatter/src/scss/auxiliary/hide_clause.rs
There was a problem hiding this comment.
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 `@xtask/codegen/css.ungram`:
- Around line 2665-2688: The grammar node ScssModuleConfiguration currently ends
at value: ScssExpression and cannot represent the `!default` modifier; update
ScssModuleConfiguration to include an optional modifier (e.g., default: '!'? or
default: '!default' boolean) and adjust parsing to allow an optional `!default`
token following value: ScssExpression, ensuring AnyScssModuleConfiguration and
ScssModuleConfigurationItemList still accept the new form; update any relevant
comments/examples to show "$primary: blue !default" and ensure downstream
consumers of ScssModuleConfiguration (AST builders/visitors) handle the new
optional field.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2921e2a3-d5bd-40d6-833d-eab8bc9400e4
⛔ Files ignored due to path filters (6)
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**crates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/forward.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/forward.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_syntax/src/generated/nodes.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_css_syntax/src/generated/nodes_mut.rsis excluded by!**/generated/**,!**/generated/**and included by**
📒 Files selected for processing (4)
crates/biome_css_formatter/src/scss/auxiliary/forward_as_clause.rscrates/biome_css_parser/src/syntax/scss/at_rule/forward_at_rule.rscrates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/forward.scssxtask/codegen/css.ungram
🚧 Files skipped from review as they are similar to previous changes (3)
- crates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/forward.scss
- crates/biome_css_formatter/src/scss/auxiliary/forward_as_clause.rs
- crates/biome_css_parser/src/syntax/scss/at_rule/forward_at_rule.rs
@use, @forward, @show, and @hide at-rules@use and @forward at-rules
…sing and handling edge cases
…` token handling
…t for spaces and disallowed patterns
…d clause validation and formatting rules
…r optional modifiers, improved clause validation, and refined snapshot generation
…n for improved readability
a9667ac to
a65d6f4
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
crates/biome_css_parser/src/syntax/scss/at_rule/module_clauses.rs (2)
143-146: Note:parse_scss_module_member_listalways returnsPresent.Since this function wraps
parse_list()inPresentunconditionally, callers using.or_add_diagnostic()will never trigger that diagnostic—the error path is handled internally viadiagnose_missing_element. This works correctly but the caller-side.or_add_diagnostic()is effectively dead code.Not blocking; the error handling is sound via the list implementation.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_css_parser/src/syntax/scss/at_rule/module_clauses.rs` around lines 143 - 146, The wrapper parse_scss_module_member_list always returns Present by wrapping ScssModuleMemberList.parse_list(p), which prevents callers' .or_add_diagnostic() from ever firing; change parse_scss_module_member_list to return the ParsedSyntax produced by ScssModuleMemberList.parse_list(p) directly (i.e., remove the unconditional Present(...) wrapper) so the Missing path propagates to callers and .or_add_diagnostic() can work, leaving any internal diagnose_missing_element logic inside the list implementation intact.
242-280:ScssModuleConfigurationItemListis missingdiagnose_missing_element.Unlike
ScssModuleMemberList, this list relies solely on therecover()method for diagnostics. This works, but for consistency you may want to add the override here as well—especially if you want uniform error messages for trailing commas likewith ($a: 1,).Not blocking; current behaviour is acceptable.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_css_parser/src/syntax/scss/at_rule/module_clauses.rs` around lines 242 - 280, Add a diagnose_missing_element override to the ParseSeparatedList impl for ScssModuleConfigurationItemList so the parser emits the same missing-element/trailing-comma diagnostics as ScssModuleMemberList; implement diagnose_missing_element to produce a diagnostic when a separating element (T![,]) is present but the next configuration is missing, reusing the same recovery/expectation helpers (parse_scss_module_configuration, ScssModuleConfigurationItemListRecovery, expected_scss_module_configuration) and the list kind SCSS_MODULE_CONFIGURATION_ITEM_LIST so behavior matches the other list implementation.
🤖 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_formatter/src/scss/auxiliary/with_clause.rs`:
- Around line 15-23: The code special-cases trailing `@forward` clauses to emit
`with(` (no separator) while other paths emit `with (`, causing inconsistent
normalization; update the formatter so all branches output the same separator
after with_token (i.e., always include space() between with_token.format() and
configurations.format()), removing the branch that writes with_token.format()
without a separator and changing the hard_space() case to space() as well; apply
the same change to the corresponding code block referenced at lines 28-45 (use
the same consistent write! pattern with with_token.format(), space(),
configurations.format()), letting the parent at-rule formatter handle line
placement.
---
Nitpick comments:
In `@crates/biome_css_parser/src/syntax/scss/at_rule/module_clauses.rs`:
- Around line 143-146: The wrapper parse_scss_module_member_list always returns
Present by wrapping ScssModuleMemberList.parse_list(p), which prevents callers'
.or_add_diagnostic() from ever firing; change parse_scss_module_member_list to
return the ParsedSyntax produced by ScssModuleMemberList.parse_list(p) directly
(i.e., remove the unconditional Present(...) wrapper) so the Missing path
propagates to callers and .or_add_diagnostic() can work, leaving any internal
diagnose_missing_element logic inside the list implementation intact.
- Around line 242-280: Add a diagnose_missing_element override to the
ParseSeparatedList impl for ScssModuleConfigurationItemList so the parser emits
the same missing-element/trailing-comma diagnostics as ScssModuleMemberList;
implement diagnose_missing_element to produce a diagnostic when a separating
element (T![,]) is present but the next configuration is missing, reusing the
same recovery/expectation helpers (parse_scss_module_configuration,
ScssModuleConfigurationItemListRecovery, expected_scss_module_configuration) and
the list kind SCSS_MODULE_CONFIGURATION_ITEM_LIST so behavior matches the other
list implementation.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 86f2d31b-1b64-4a77-95bf-688a1bec75a0
⛔ Files ignored due to path filters (10)
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**crates/biome_css_formatter/tests/specs/css/scss/at-rule/forward.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_formatter/tests/specs/css/scss/at-rule/use.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/forward.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/use.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/forward.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/use.scss.snapis excluded by!**/*.snapand included by**crates/biome_css_syntax/src/generated/nodes.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_css_syntax/src/generated/nodes_mut.rsis excluded by!**/generated/**,!**/generated/**and included by**
📒 Files selected for processing (14)
crates/biome_css_formatter/src/scss/auxiliary/forward_as_clause.rscrates/biome_css_formatter/src/scss/auxiliary/hide_clause.rscrates/biome_css_formatter/src/scss/auxiliary/module_configuration.rscrates/biome_css_formatter/src/scss/auxiliary/module_configuration_list.rscrates/biome_css_formatter/src/scss/auxiliary/show_clause.rscrates/biome_css_formatter/src/scss/auxiliary/with_clause.rscrates/biome_css_formatter/tests/specs/css/scss/at-rule/forward.scsscrates/biome_css_formatter/tests/specs/css/scss/at-rule/use.scsscrates/biome_css_parser/src/syntax/scss/at_rule/forward_at_rule.rscrates/biome_css_parser/src/syntax/scss/at_rule/module_clauses.rscrates/biome_css_parser/tests/css_test_suite/error/scss/at-rule/use.scsscrates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/forward.scsscrates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/use.scssxtask/codegen/css.ungram
🚧 Files skipped from review as they are similar to previous changes (4)
- crates/biome_css_formatter/tests/specs/css/scss/at-rule/use.scss
- crates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/use.scss
- crates/biome_css_formatter/src/scss/auxiliary/forward_as_clause.rs
- crates/biome_css_parser/tests/css_test_suite/ok/scss/at-rule/forward.scss
…g conditional clause handling
Summary
Adds SCSS support for
@useand@forward.Test Plan