Skip to content

Commit 6918c9e

Browse files
ruidosujeiraautofix-ci[bot]ematipico
authored
fix(parser): accept scroll-state(...) in @container not queries (#8855)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Emanuele Stoppa <[email protected]>
1 parent 086a0c5 commit 6918c9e

9 files changed

Lines changed: 258 additions & 13 deletions

File tree

.changeset/loose-eyes-roll.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@biomejs/biome": patch
3+
---
4+
5+
Fixed [#8840](https://github.com/biomejs/biome/issues/8840). Now the Biome CSS parser correctly parses `not + scroll-state` inside `@container` queries.

crates/biome_css_formatter/src/css/any/container_query_in_parens.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ impl FormatRule<AnyCssContainerQueryInParens> for FormatAnyCssContainerQueryInPa
88
type Context = CssFormatContext;
99
fn fmt(&self, node: &AnyCssContainerQueryInParens, f: &mut CssFormatter) -> FormatResult<()> {
1010
match node {
11+
AnyCssContainerQueryInParens::AnyCssValue(node) => node.format().fmt(f),
1112
AnyCssContainerQueryInParens::CssContainerQueryInParens(node) => node.format().fmt(f),
1213
AnyCssContainerQueryInParens::CssContainerSizeFeatureInParens(node) => {
1314
node.format().fmt(f)

crates/biome_css_parser/src/syntax/at_rule/container/mod.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ use crate::syntax::at_rule::error::{
1111
use crate::syntax::at_rule::feature::{expected_any_query_feature, parse_any_query_feature};
1212
use crate::syntax::block::parse_conditional_block;
1313
use crate::syntax::parse_error::expected_non_css_wide_keyword_identifier;
14-
use crate::syntax::{is_at_declaration, parse_custom_identifier, parse_declaration};
14+
use crate::syntax::value::function::is_nth_at_function;
15+
use crate::syntax::{
16+
is_at_declaration, parse_any_value, parse_custom_identifier, parse_declaration,
17+
};
1518
use biome_css_syntax::CssSyntaxKind::*;
1619
use biome_css_syntax::{CssSyntaxKind, T};
1720
use biome_parser::parse_recovery::ParseRecovery;
@@ -199,6 +202,20 @@ fn is_at_container_not_query(p: &mut CssParser) -> bool {
199202
p.at(T![not])
200203
}
201204

205+
#[inline]
206+
fn is_at_container_scroll_state_query(p: &mut CssParser) -> bool {
207+
is_nth_at_function(p, 0) && p.cur_text().eq_ignore_ascii_case("scroll-state")
208+
}
209+
210+
#[inline]
211+
fn parse_container_scroll_state_query(p: &mut CssParser) -> ParsedSyntax {
212+
if !is_at_container_scroll_state_query(p) {
213+
return Absent;
214+
}
215+
216+
parse_any_value(p)
217+
}
218+
202219
/// Parses a negated container query using the `not(...)` syntax.
203220
///
204221
/// # Example
@@ -233,14 +250,19 @@ pub(crate) fn parse_any_container_query_in_parens(p: &mut CssParser) -> ParsedSy
233250
parse_container_query_in_parens(p)
234251
} else if is_at_container_size_feature_in_parens(p) {
235252
parse_container_size_feature_in_parens(p)
253+
} else if is_at_container_scroll_state_query(p) {
254+
parse_container_scroll_state_query(p)
236255
} else {
237256
Absent
238257
}
239258
}
240259

241260
#[inline]
242261
fn is_at_container_query_in_parens(p: &mut CssParser) -> bool {
243-
p.at(T!['(']) && (p.nth_at(1, T![not]) || p.nth_at(1, T!['(']))
262+
p.at(T!['('])
263+
&& (p.nth_at(1, T![not])
264+
|| p.nth_at(1, T!['('])
265+
|| (p.nth_at(1, T![ident]) && p.nth_at(2, T!['('])))
244266
}
245267

246268
/// Parses a parenthesized container query.

crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_and_query_error.css.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
source: crates/biome_css_parser/tests/spec_test.rs
3+
assertion_line: 179
34
expression: snapshot
45
---
56

crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_or_query_error.css.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
source: crates/biome_css_parser/tests/spec_test.rs
3+
assertion_line: 179
34
expression: snapshot
45
---
56

crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,9 @@
3636
@container name not style(color: red) {}
3737

3838
@container style (--responsive: true) { }
39+
40+
@container not scroll-state(stuck) { }
41+
42+
@container not (scroll-state(stuck)) { }
43+
44+
@container (not scroll-state(stuck)) { }

crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container.css.snap

Lines changed: 194 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ expression: snapshot
4545
4646
@container style (--responsive: true) { }
4747
48+
@container not scroll-state(stuck) { }
49+
50+
@container not (scroll-state(stuck)) { }
51+
52+
@container (not scroll-state(stuck)) { }
53+
4854
```
4955

5056

@@ -766,17 +772,128 @@ CssRoot {
766772
},
767773
},
768774
},
775+
CssAtRule {
776+
at_token: AT@891..894 "@" [Newline("\n"), Newline("\n")] [],
777+
rule: CssContainerAtRule {
778+
declarator: CssContainerAtRuleDeclarator {
779+
container_token: CONTAINER_KW@894..904 "container" [] [Whitespace(" ")],
780+
name: CssCustomIdentifier {
781+
value_token: IDENT@904..908 "not" [] [Whitespace(" ")],
782+
},
783+
query: CssFunction {
784+
name: CssIdentifier {
785+
value_token: IDENT@908..920 "scroll-state" [] [],
786+
},
787+
l_paren_token: L_PAREN@920..921 "(" [] [],
788+
items: CssParameterList [
789+
CssParameter {
790+
any_css_expression: CssListOfComponentValuesExpression {
791+
css_component_value_list: CssComponentValueList [
792+
CssIdentifier {
793+
value_token: IDENT@921..926 "stuck" [] [],
794+
},
795+
],
796+
},
797+
},
798+
],
799+
r_paren_token: R_PAREN@926..928 ")" [] [Whitespace(" ")],
800+
},
801+
},
802+
block: CssRuleBlock {
803+
l_curly_token: L_CURLY@928..931 "{" [] [Whitespace(" ")],
804+
rules: CssRuleList [],
805+
r_curly_token: R_CURLY@931..932 "}" [] [],
806+
},
807+
},
808+
},
809+
CssAtRule {
810+
at_token: AT@932..935 "@" [Newline("\n"), Newline("\n")] [],
811+
rule: CssContainerAtRule {
812+
declarator: CssContainerAtRuleDeclarator {
813+
container_token: CONTAINER_KW@935..945 "container" [] [Whitespace(" ")],
814+
name: CssCustomIdentifier {
815+
value_token: IDENT@945..949 "not" [] [Whitespace(" ")],
816+
},
817+
query: CssContainerQueryInParens {
818+
l_paren_token: L_PAREN@949..950 "(" [] [],
819+
query: CssFunction {
820+
name: CssIdentifier {
821+
value_token: IDENT@950..962 "scroll-state" [] [],
822+
},
823+
l_paren_token: L_PAREN@962..963 "(" [] [],
824+
items: CssParameterList [
825+
CssParameter {
826+
any_css_expression: CssListOfComponentValuesExpression {
827+
css_component_value_list: CssComponentValueList [
828+
CssIdentifier {
829+
value_token: IDENT@963..968 "stuck" [] [],
830+
},
831+
],
832+
},
833+
},
834+
],
835+
r_paren_token: R_PAREN@968..969 ")" [] [],
836+
},
837+
r_paren_token: R_PAREN@969..971 ")" [] [Whitespace(" ")],
838+
},
839+
},
840+
block: CssRuleBlock {
841+
l_curly_token: L_CURLY@971..974 "{" [] [Whitespace(" ")],
842+
rules: CssRuleList [],
843+
r_curly_token: R_CURLY@974..975 "}" [] [],
844+
},
845+
},
846+
},
847+
CssAtRule {
848+
at_token: AT@975..978 "@" [Newline("\n"), Newline("\n")] [],
849+
rule: CssContainerAtRule {
850+
declarator: CssContainerAtRuleDeclarator {
851+
container_token: CONTAINER_KW@978..988 "container" [] [Whitespace(" ")],
852+
name: missing (optional),
853+
query: CssContainerQueryInParens {
854+
l_paren_token: L_PAREN@988..989 "(" [] [],
855+
query: CssContainerNotQuery {
856+
not_token: NOT_KW@989..993 "not" [] [Whitespace(" ")],
857+
query: CssFunction {
858+
name: CssIdentifier {
859+
value_token: IDENT@993..1005 "scroll-state" [] [],
860+
},
861+
l_paren_token: L_PAREN@1005..1006 "(" [] [],
862+
items: CssParameterList [
863+
CssParameter {
864+
any_css_expression: CssListOfComponentValuesExpression {
865+
css_component_value_list: CssComponentValueList [
866+
CssIdentifier {
867+
value_token: IDENT@1006..1011 "stuck" [] [],
868+
},
869+
],
870+
},
871+
},
872+
],
873+
r_paren_token: R_PAREN@1011..1012 ")" [] [],
874+
},
875+
},
876+
r_paren_token: R_PAREN@1012..1014 ")" [] [Whitespace(" ")],
877+
},
878+
},
879+
block: CssRuleBlock {
880+
l_curly_token: L_CURLY@1014..1017 "{" [] [Whitespace(" ")],
881+
rules: CssRuleList [],
882+
r_curly_token: R_CURLY@1017..1018 "}" [] [],
883+
},
884+
},
885+
},
769886
],
770-
eof_token: EOF@891..892 "" [Newline("\n")] [],
887+
eof_token: EOF@1018..1019 "" [Newline("\n")] [],
771888
}
772889
```
773890

774891
## CST
775892

776893
```
777-
0: CSS_ROOT@0..892
894+
0: CSS_ROOT@0..1019
778895
0: (empty)
779-
1: CSS_ROOT_ITEM_LIST@0..891
896+
1: CSS_ROOT_ITEM_LIST@0..1018
780897
781898
0: [email protected] "@" [] []
782899
@@ -1270,6 +1387,79 @@ CssRoot {
12701387
0: L_CURLY@887..890 "{" [] [Whitespace(" ")]
12711388
1: CSS_RULE_LIST@890..890
12721389
2: R_CURLY@890..891 "}" [] []
1273-
2: EOF@891..892 "" [Newline("\n")] []
1390+
20: CSS_AT_RULE@891..932
1391+
0: AT@891..894 "@" [Newline("\n"), Newline("\n")] []
1392+
1: CSS_CONTAINER_AT_RULE@894..932
1393+
0: CSS_CONTAINER_AT_RULE_DECLARATOR@894..928
1394+
0: CONTAINER_KW@894..904 "container" [] [Whitespace(" ")]
1395+
1: CSS_CUSTOM_IDENTIFIER@904..908
1396+
0: IDENT@904..908 "not" [] [Whitespace(" ")]
1397+
2: CSS_FUNCTION@908..928
1398+
0: CSS_IDENTIFIER@908..920
1399+
0: IDENT@908..920 "scroll-state" [] []
1400+
1: L_PAREN@920..921 "(" [] []
1401+
2: CSS_PARAMETER_LIST@921..926
1402+
0: CSS_PARAMETER@921..926
1403+
0: CSS_LIST_OF_COMPONENT_VALUES_EXPRESSION@921..926
1404+
0: CSS_COMPONENT_VALUE_LIST@921..926
1405+
0: CSS_IDENTIFIER@921..926
1406+
0: IDENT@921..926 "stuck" [] []
1407+
3: R_PAREN@926..928 ")" [] [Whitespace(" ")]
1408+
1: CSS_RULE_BLOCK@928..932
1409+
0: L_CURLY@928..931 "{" [] [Whitespace(" ")]
1410+
1: CSS_RULE_LIST@931..931
1411+
2: R_CURLY@931..932 "}" [] []
1412+
21: CSS_AT_RULE@932..975
1413+
0: AT@932..935 "@" [Newline("\n"), Newline("\n")] []
1414+
1: CSS_CONTAINER_AT_RULE@935..975
1415+
0: CSS_CONTAINER_AT_RULE_DECLARATOR@935..971
1416+
0: CONTAINER_KW@935..945 "container" [] [Whitespace(" ")]
1417+
1: CSS_CUSTOM_IDENTIFIER@945..949
1418+
0: IDENT@945..949 "not" [] [Whitespace(" ")]
1419+
2: CSS_CONTAINER_QUERY_IN_PARENS@949..971
1420+
0: L_PAREN@949..950 "(" [] []
1421+
1: CSS_FUNCTION@950..969
1422+
0: CSS_IDENTIFIER@950..962
1423+
0: IDENT@950..962 "scroll-state" [] []
1424+
1: L_PAREN@962..963 "(" [] []
1425+
2: CSS_PARAMETER_LIST@963..968
1426+
0: CSS_PARAMETER@963..968
1427+
0: CSS_LIST_OF_COMPONENT_VALUES_EXPRESSION@963..968
1428+
0: CSS_COMPONENT_VALUE_LIST@963..968
1429+
0: CSS_IDENTIFIER@963..968
1430+
0: IDENT@963..968 "stuck" [] []
1431+
3: R_PAREN@968..969 ")" [] []
1432+
2: R_PAREN@969..971 ")" [] [Whitespace(" ")]
1433+
1: CSS_RULE_BLOCK@971..975
1434+
0: L_CURLY@971..974 "{" [] [Whitespace(" ")]
1435+
1: CSS_RULE_LIST@974..974
1436+
2: R_CURLY@974..975 "}" [] []
1437+
22: CSS_AT_RULE@975..1018
1438+
0: AT@975..978 "@" [Newline("\n"), Newline("\n")] []
1439+
1: CSS_CONTAINER_AT_RULE@978..1018
1440+
0: CSS_CONTAINER_AT_RULE_DECLARATOR@978..1014
1441+
0: CONTAINER_KW@978..988 "container" [] [Whitespace(" ")]
1442+
1: (empty)
1443+
2: CSS_CONTAINER_QUERY_IN_PARENS@988..1014
1444+
0: L_PAREN@988..989 "(" [] []
1445+
1: CSS_CONTAINER_NOT_QUERY@989..1012
1446+
0: NOT_KW@989..993 "not" [] [Whitespace(" ")]
1447+
1: CSS_FUNCTION@993..1012
1448+
0: CSS_IDENTIFIER@993..1005
1449+
0: IDENT@993..1005 "scroll-state" [] []
1450+
1: L_PAREN@1005..1006 "(" [] []
1451+
2: CSS_PARAMETER_LIST@1006..1011
1452+
0: CSS_PARAMETER@1006..1011
1453+
0: CSS_LIST_OF_COMPONENT_VALUES_EXPRESSION@1006..1011
1454+
0: CSS_COMPONENT_VALUE_LIST@1006..1011
1455+
0: CSS_IDENTIFIER@1006..1011
1456+
0: IDENT@1006..1011 "stuck" [] []
1457+
3: R_PAREN@1011..1012 ")" [] []
1458+
2: R_PAREN@1012..1014 ")" [] [Whitespace(" ")]
1459+
1: CSS_RULE_BLOCK@1014..1018
1460+
0: L_CURLY@1014..1017 "{" [] [Whitespace(" ")]
1461+
1: CSS_RULE_LIST@1017..1017
1462+
2: R_CURLY@1017..1018 "}" [] []
1463+
2: EOF@1018..1019 "" [Newline("\n")] []
12741464
12751465
```

0 commit comments

Comments
 (0)