From af40d0428d1710286b5db85fa44f28e91bace200 Mon Sep 17 00:00:00 2001 From: Denis Bezrukov <6227442+denbezrukov@users.noreply.github.com> Date: Sun, 2 Mar 2025 21:45:05 +0200 Subject: [PATCH] refactor(css_parser): improved error handling for the container at rule --- .changeset/ten-hands-open.md | 5 + .../src/syntax/at_rule/container.rs | 255 ---- .../src/syntax/at_rule/container/error.rs | 55 + .../src/syntax/at_rule/container/mod.rs | 590 ++++++++ .../src/syntax/at_rule/feature.rs | 16 +- .../biome_css_parser/src/syntax/block/mod.rs | 7 +- .../at_rule_container_and_query_error.css | 27 + ...at_rule_container_and_query_error.css.snap | 728 ++++++++++ .../at_rule_container_error.css | 0 .../at_rule_container_error.css.snap | 955 ++++++++++++ .../at_rule_container_or_query_error.css | 35 + .../at_rule_container_or_query_error.css.snap | 861 +++++++++++ .../at_rule_container_style_not_query.css | 41 + ...at_rule_container_style_not_query.css.snap | 669 +++++++++ .../at_rule_container_style_query_error.css | 69 + ..._rule_container_style_query_error.css.snap | 1281 +++++++++++++++++ .../at_rule/at_rule_container_error.css.snap | 1115 -------------- .../at_rule_keyframes_1.css.snap | 158 +- .../error/block/css_unfinished_block.css.snap | 20 +- .../ok/at_rule/at_rule_container.css | 4 +- .../ok/at_rule/at_rule_container.css.snap | 72 +- crates/biome_css_parser/tests/spec_test.rs | 7 +- 22 files changed, 5482 insertions(+), 1488 deletions(-) create mode 100644 .changeset/ten-hands-open.md delete mode 100644 crates/biome_css_parser/src/syntax/at_rule/container.rs create mode 100644 crates/biome_css_parser/src/syntax/at_rule/container/error.rs create mode 100644 crates/biome_css_parser/src/syntax/at_rule/container/mod.rs create mode 100644 crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_and_query_error.css create mode 100644 crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_and_query_error.css.snap rename crates/biome_css_parser/tests/css_test_suite/error/at_rule/{ => at_rule_container}/at_rule_container_error.css (100%) create mode 100644 crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_error.css.snap create mode 100644 crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_or_query_error.css create mode 100644 crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_or_query_error.css.snap create mode 100644 crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_not_query.css create mode 100644 crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_not_query.css.snap create mode 100644 crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_query_error.css create mode 100644 crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_query_error.css.snap delete mode 100644 crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container_error.css.snap diff --git a/.changeset/ten-hands-open.md b/.changeset/ten-hands-open.md new file mode 100644 index 000000000000..96d4ab0b1e36 --- /dev/null +++ b/.changeset/ten-hands-open.md @@ -0,0 +1,5 @@ +--- +"@biomejs/biome": patch +--- + +Improved error handling for the container at-rule. diff --git a/crates/biome_css_parser/src/syntax/at_rule/container.rs b/crates/biome_css_parser/src/syntax/at_rule/container.rs deleted file mode 100644 index ed32d2dfc628..000000000000 --- a/crates/biome_css_parser/src/syntax/at_rule/container.rs +++ /dev/null @@ -1,255 +0,0 @@ -use crate::lexer::CssLexContext; -use crate::parser::CssParser; -use crate::syntax::at_rule::feature::parse_any_query_feature; -use crate::syntax::block::parse_conditional_block; -use crate::syntax::parse_error::expected_non_css_wide_keyword_identifier; -use crate::syntax::{is_at_declaration, parse_custom_identifier, parse_declaration}; -use biome_css_syntax::CssSyntaxKind::*; -use biome_css_syntax::T; -use biome_parser::parsed_syntax::ParsedSyntax::Present; -use biome_parser::prelude::ParsedSyntax::Absent; -use biome_parser::prelude::*; - -#[inline] -pub(crate) fn is_at_container_at_rule(p: &mut CssParser) -> bool { - p.at(T![container]) -} - -#[inline] -pub(crate) fn parse_container_at_rule(p: &mut CssParser) -> ParsedSyntax { - if !is_at_container_at_rule(p) { - return Absent; - } - - let m = p.start(); - - p.bump(T![container]); - - if parse_custom_identifier(p, CssLexContext::Regular) - .ok() - .is_none() - { - // Because the name is optional, we have to indirectly check if it's - // a CSS-wide keyword that can't be used. If it was required, we could - // use `.or_recover` or `.or_add_diagnostic` here instead. - if p.cur().is_css_wide_keyword() { - p.err_and_bump( - expected_non_css_wide_keyword_identifier(p, p.cur_range()), - CSS_BOGUS, - ) - } - }; - - parse_any_container_query(p).ok(); // TODO handle error - parse_conditional_block(p); - - Present(m.complete(p, CSS_CONTAINER_AT_RULE)) -} - -#[inline] -fn parse_any_container_query(p: &mut CssParser) -> ParsedSyntax { - if is_at_container_not_query(p) { - parse_container_not_query(p) - } else { - let query_in_parens = parse_any_container_query_in_parens(p); - - match p.cur() { - T![and] => { - let m = query_in_parens.precede(p); - p.bump(T![and]); - parse_container_and_query(p).ok(); // TODO handle error - Present(m.complete(p, CSS_CONTAINER_AND_QUERY)) - } - T![or] => { - let m = query_in_parens.precede(p); - p.bump(T![or]); - parse_container_or_query(p).ok(); // TODO handle error - Present(m.complete(p, CSS_CONTAINER_OR_QUERY)) - } - _ => query_in_parens, - } - } -} - -#[inline] -fn parse_container_and_query(p: &mut CssParser) -> ParsedSyntax { - let query_in_parens = parse_any_container_query_in_parens(p); - - if p.at(T![and]) { - let m = query_in_parens.precede(p); - p.bump(T![and]); - parse_container_and_query(p).ok(); // TODO handle error - Present(m.complete(p, CSS_CONTAINER_AND_QUERY)) - } else { - query_in_parens - } -} - -#[inline] -fn parse_container_or_query(p: &mut CssParser) -> ParsedSyntax { - let query_in_parens = parse_any_container_query_in_parens(p); - - if p.at(T![or]) { - let m = query_in_parens.precede(p); - p.bump(T![or]); - parse_container_or_query(p).ok(); // TODO handle error - Present(m.complete(p, CSS_CONTAINER_OR_QUERY)) - } else { - query_in_parens - } -} - -#[inline] -fn is_at_container_not_query(p: &mut CssParser) -> bool { - p.at(T![not]) -} -#[inline] -fn parse_container_not_query(p: &mut CssParser) -> ParsedSyntax { - if !is_at_container_not_query(p) { - return Absent; - } - - let m = p.start(); - - p.bump(T![not]); - parse_any_container_query_in_parens(p).ok(); // TODO handle error - - Present(m.complete(p, CSS_CONTAINER_NOT_QUERY)) -} -#[inline] -fn parse_any_container_query_in_parens(p: &mut CssParser) -> ParsedSyntax { - if is_at_container_query_in_parens(p) { - parse_container_query_in_parens(p) - } else if is_at_container_style_query_in_parens(p) { - parse_container_style_query_in_parens(p) - } else if is_at_container_size_feature_in_parens(p) { - parse_container_size_feature_in_parens(p) - } else { - Absent - } -} - -#[inline] -fn is_at_container_query_in_parens(p: &mut CssParser) -> bool { - p.at(T!['(']) && (p.nth_at(1, T![not]) || p.nth_at(1, T!['('])) -} - -#[inline] -fn parse_container_query_in_parens(p: &mut CssParser) -> ParsedSyntax { - if !is_at_container_query_in_parens(p) { - return Absent; - } - - let m = p.start(); - - p.bump(T!['(']); - parse_any_container_query(p).ok(); // TODO handle error - p.bump(T![')']); - - Present(m.complete(p, CSS_CONTAINER_QUERY_IN_PARENS)) -} - -#[inline] -fn is_at_container_size_feature_in_parens(p: &mut CssParser) -> bool { - p.at(T!['(']) -} - -#[inline] -fn parse_container_size_feature_in_parens(p: &mut CssParser) -> ParsedSyntax { - if !is_at_container_size_feature_in_parens(p) { - return Absent; - } - - let m = p.start(); - - p.bump(T!['(']); - parse_any_query_feature(p).ok(); // TODO handle error - p.expect(T![')']); - - Present(m.complete(p, CSS_CONTAINER_SIZE_FEATURE_IN_PARENS)) -} - -#[inline] -fn is_at_container_style_query_in_parens(p: &mut CssParser) -> bool { - p.at(T![style]) -} - -#[inline] -fn parse_container_style_query_in_parens(p: &mut CssParser) -> ParsedSyntax { - if !is_at_container_style_query_in_parens(p) { - return Absent; - } - - let m = p.start(); - - p.bump(T![style]); - p.expect(T!['(']); - parse_any_container_style_query(p).ok(); // TODO handle error - p.expect(T![')']); - - Present(m.complete(p, CSS_CONTAINER_STYLE_QUERY_IN_PARENS)) -} - -#[inline] -fn parse_any_container_style_query(p: &mut CssParser) -> ParsedSyntax { - if is_at_container_style_not_query(p) { - parse_container_style_not_query(p) - } else if is_at_declaration(p) { - parse_declaration(p) - } else { - parse_any_container_style_combinable_query(p) - } -} - -#[inline] -fn parse_any_container_style_combinable_query(p: &mut CssParser) -> ParsedSyntax { - let style_in_parens = parse_container_style_in_parens(p); - - match p.cur() { - T![and] => { - let m = style_in_parens.precede(p); - p.bump(T![and]); - parse_any_container_style_combinable_query(p).ok(); // TODO handle error - Present(m.complete(p, CSS_CONTAINER_STYLE_AND_QUERY)) - } - T![or] => { - let m = style_in_parens.precede(p); - p.bump(T![or]); - parse_any_container_style_combinable_query(p).ok(); // TODO handle error - Present(m.complete(p, CSS_CONTAINER_STYLE_OR_QUERY)) - } - _ => style_in_parens, - } -} - -#[inline] -fn is_at_container_style_not_query(p: &mut CssParser) -> bool { - p.at(T![not]) && p.nth_at(1, T!['(']) -} - -#[inline] -fn parse_container_style_not_query(p: &mut CssParser) -> ParsedSyntax { - if !is_at_container_style_not_query(p) { - return Absent; - } - - let m = p.start(); - - p.bump(T![not]); - parse_container_style_in_parens(p).ok(); // TODO handle error - - Present(m.complete(p, CSS_CONTAINER_STYLE_NOT_QUERY)) -} - -#[inline] -fn parse_container_style_in_parens(p: &mut CssParser) -> ParsedSyntax { - if !p.at(T!['(']) { - return Absent; - } - - let m = p.start(); - p.bump(T!['(']); - parse_any_container_style_query(p).ok(); // TODO handle error - p.expect(T![')']); - Present(m.complete(p, CSS_CONTAINER_STYLE_IN_PARENS)) -} diff --git a/crates/biome_css_parser/src/syntax/at_rule/container/error.rs b/crates/biome_css_parser/src/syntax/at_rule/container/error.rs new file mode 100644 index 000000000000..2547634e6acf --- /dev/null +++ b/crates/biome_css_parser/src/syntax/at_rule/container/error.rs @@ -0,0 +1,55 @@ +use crate::parser::CssParser; +use biome_css_syntax::TextRange; +use biome_parser::diagnostic::{ParseDiagnostic, ToDiagnostic, expect_one_of}; + +pub(crate) fn expected_any_container_query(p: &CssParser, range: TextRange) -> ParseDiagnostic { + expect_one_of( + &[ + "not ", + "", + " and ", + " or ", + ], + range, + ) + .into_diagnostic(p) +} + +pub(crate) fn expected_any_container_query_in_parens( + p: &CssParser, + range: TextRange, +) -> ParseDiagnostic { + expect_one_of( + &[ + "( )", + "( )", + "style( )", + ], + range, + ) + .into_diagnostic(p) +} + +pub(crate) fn expected_any_container_style_query( + p: &CssParser, + range: TextRange, +) -> ParseDiagnostic { + expect_one_of( + &[ + "not ", + "", + " and ", + " or ", + "", + ], + range, + ) + .into_diagnostic(p) +} + +pub(crate) fn expected_any_container_style_in_parens( + p: &CssParser, + range: TextRange, +) -> ParseDiagnostic { + expect_one_of(&["( )", "( )"], range).into_diagnostic(p) +} diff --git a/crates/biome_css_parser/src/syntax/at_rule/container/mod.rs b/crates/biome_css_parser/src/syntax/at_rule/container/mod.rs new file mode 100644 index 000000000000..b463342d873a --- /dev/null +++ b/crates/biome_css_parser/src/syntax/at_rule/container/mod.rs @@ -0,0 +1,590 @@ +mod error; + +use crate::lexer::CssLexContext; +use crate::parser::CssParser; +use crate::syntax::at_rule::container::error::{ + expected_any_container_style_in_parens, expected_any_container_style_query, +}; +use crate::syntax::at_rule::feature::{expected_any_query_feature, parse_any_query_feature}; +use crate::syntax::block::parse_conditional_block; +use crate::syntax::parse_error::expected_non_css_wide_keyword_identifier; +use crate::syntax::{is_at_declaration, parse_custom_identifier, parse_declaration}; +use biome_css_syntax::CssSyntaxKind::*; +use biome_css_syntax::{CssSyntaxKind, T}; +use biome_parser::parse_recovery::ParseRecovery; +use biome_parser::parsed_syntax::ParsedSyntax::Present; +use biome_parser::prelude::ParsedSyntax::Absent; +use biome_parser::prelude::*; +use error::{expected_any_container_query, expected_any_container_query_in_parens}; + +/// Checks if the current token in the parser is an `@container` at-rule. +#[inline] +pub(crate) fn is_at_container_at_rule(p: &mut CssParser) -> bool { + p.at(T![container]) +} + +/// Parses an `@container` at-rule in a CSS stylesheet. +/// +/// This function processes the `@container` rule, as specified in the +/// [CSS Conditional Rules Module Level 5](https://drafts.csswg.org/css-conditional-5/#container-rule), +/// +/// # Examples +/// Basic usage in CSS: +/// +/// ```css +/// @container (min-width: 400px) { +/// /* Styles apply only if the container is at least 400px wide */ +/// .sidebar { +/// padding: 1rem; +/// } +/// } +/// ``` +/// +/// Named containers: +/// +/// ```css +/// @container sidebar (min-width: 300px) { +/// /* Styles apply only if the container named "sidebar" is at least 300px wide */ +/// .item { +/// display: flex; +/// } +/// } +/// ``` +/// +/// Multiple container queries chained with logical operators: +/// +/// ```css +/// @container (width > 300px) and (height > 200px) { +/// /* Only applies if both width and height exceed the specified thresholds */ +/// .article { +/// margin: 2rem; +/// } +/// } +/// ``` +#[inline] +pub(crate) fn parse_container_at_rule(p: &mut CssParser) -> ParsedSyntax { + if !is_at_container_at_rule(p) { + return Absent; + } + + let m = p.start(); + + p.bump(T![container]); + + if parse_custom_identifier(p, CssLexContext::Regular) + .ok() + .is_none() + { + // Because the name is optional, we have to indirectly check if it's + // a CSS-wide keyword that can't be used. If it was required, we could + // use `.or_recover` or `.or_add_diagnostic` here instead. + if p.cur().is_css_wide_keyword() { + p.err_and_bump( + expected_non_css_wide_keyword_identifier(p, p.cur_range()), + CSS_BOGUS, + ) + } + }; + + parse_any_container_query(p) + .or_recover( + p, + &AnyContainerQueryParseRecovery, + expected_any_container_query, + ) + .ok(); + parse_conditional_block(p); + + Present(m.complete(p, CSS_CONTAINER_AT_RULE)) +} + +struct AnyContainerQueryParseRecovery; + +impl ParseRecovery for AnyContainerQueryParseRecovery { + type Kind = CssSyntaxKind; + type Parser<'source> = CssParser<'source>; + const RECOVERED_KIND: Self::Kind = CSS_BOGUS; + + fn is_at_recovered(&self, p: &mut Self::Parser<'_>) -> bool { + // We need to recover the invalid container query: + // 1. The next block starts. + // @container name invalid-query { <--------------------+ + // ^^^^^^^^^^^^^ we skip it until the block starts + // } + // 2. The line break is missing before the next block. + // @container name invalid-query + // ^^^^^^^^^^^^^ we skip it but the block start token is missing + // } + p.at(T!['{']) || p.has_preceding_line_break() + } +} + +#[inline] +fn parse_any_container_query(p: &mut CssParser) -> ParsedSyntax { + if is_at_container_not_query(p) { + parse_container_not_query(p) + } else { + parse_any_container_query_in_parens(p).map(|lhs| match p.cur() { + T![and] => parse_container_and_query(p, lhs), + T![or] => parse_container_or_query(p, lhs), + _ => lhs, + }) + } +} + +/// Parses an `and` condition for a container query, chaining multiple conditions. +/// +/// # Example +/// ```css +/// @container (width > 300px) and (height > 200px) { +/// /* Styles apply only if both conditions are true. */ +/// } +/// ``` +#[inline] +fn parse_container_and_query(p: &mut CssParser, lhs: CompletedMarker) -> CompletedMarker { + if !p.at(T![and]) { + return lhs; + } + + let m = lhs.precede(p); + p.bump(T![and]); + + let recovery_result = parse_any_container_query_in_parens(p) + .or_recover( + p, + &AnyContainerQueryInParensChainParseRecovery::new(T![and]), + expected_any_container_query_in_parens, + ) + .map(|rhs| parse_container_and_query(p, rhs)); + + if recovery_result.is_err() && p.at(T![and]) { + // If we're here, it seems that we have + // @container (width > 300px) and and and ... + // parse_any_container_query_in_parens failed to parse, + // but the parser is already at a recovered position. + let m = p.start(); + let rhs = m.complete(p, CSS_BOGUS); + parse_container_and_query(p, rhs); + } + + m.complete(p, CSS_CONTAINER_AND_QUERY) +} + +/// Parses an `or` condition for a container query, allowing alternative conditions. +/// +/// # Example +/// ```css +/// @container (orientation: landscape) or (width > 400px) { } +/// ``` +#[inline] +fn parse_container_or_query(p: &mut CssParser, lhs: CompletedMarker) -> CompletedMarker { + if !p.at(T![or]) { + return lhs; + } + + let m = lhs.precede(p); + p.bump(T![or]); + + let recovery_result = parse_any_container_query_in_parens(p) + .or_recover( + p, + &AnyContainerQueryInParensChainParseRecovery::new(T![or]), + expected_any_container_query_in_parens, + ) + .map(|rhs| parse_container_or_query(p, rhs)); + + if recovery_result.is_err() && p.at(T![or]) { + // If we're here, it seems that we have + // @container (width > 300px) or or or + // and parse_any_container_query_in_parens failed to parse, + // but the parser is already at a recovered position. + let m = p.start(); + let rhs = m.complete(p, CSS_BOGUS); + parse_container_or_query(p, rhs); + } + + m.complete(p, CSS_CONTAINER_OR_QUERY) +} + +struct AnyContainerQueryInParensChainParseRecovery { + chain_kind: CssSyntaxKind, +} + +impl AnyContainerQueryInParensChainParseRecovery { + fn new(chain_kind: CssSyntaxKind) -> Self { + Self { chain_kind } + } +} + +impl ParseRecovery for AnyContainerQueryInParensChainParseRecovery { + type Kind = CssSyntaxKind; + type Parser<'source> = CssParser<'source>; + const RECOVERED_KIND: Self::Kind = CSS_BOGUS; + + fn is_at_recovered(&self, p: &mut Self::Parser<'_>) -> bool { + // We need to recover the invalid container query: + // 1. The next block starts. + // @container name (width > 300) and invalid { <--------------------+ + // ^^^^^^^ we skip it until the block starts + // } + // 2. The line break is missing before the next block. + // @container name (width > 300) and invalid + // ^^^^^^^ we skip it but the block start token is missing + // } + p.at(T!['{']) || p.at(self.chain_kind) || p.has_preceding_line_break() + } +} + +#[inline] +fn is_at_container_not_query(p: &mut CssParser) -> bool { + p.at(T![not]) +} + +/// Parses a negated container query using the `not(...)` syntax. +/// +/// # Example +/// ```css +/// @container not(width > 300px) { } +/// ``` +#[inline] +fn parse_container_not_query(p: &mut CssParser) -> ParsedSyntax { + if !is_at_container_not_query(p) { + return Absent; + } + + let m = p.start(); + + p.bump(T![not]); + parse_any_container_query_in_parens(p) + .or_recover( + p, + &AnyContainerQueryInParensNotQueryParseRecovery, + expected_any_container_query_in_parens, + ) + .ok(); + + Present(m.complete(p, CSS_CONTAINER_NOT_QUERY)) +} + +struct AnyContainerQueryInParensNotQueryParseRecovery; + +impl ParseRecovery for AnyContainerQueryInParensNotQueryParseRecovery { + type Kind = CssSyntaxKind; + type Parser<'source> = CssParser<'source>; + const RECOVERED_KIND: Self::Kind = CSS_BOGUS; + + fn is_at_recovered(&self, p: &mut Self::Parser<'_>) -> bool { + // We need to recover the invalid container query: + // 1. The next block starts. + // @container name not invalid { <--------------------+ + // ^^^^^^^ we skip it until the block starts + // } + // 2. The line break is missing before the next block. + // @container name not invalid + // ^^^^^^^ we skip it but the block start token is missing + // } + p.at(T!['{']) || p.has_preceding_line_break() + } +} + +#[inline] +fn parse_any_container_query_in_parens(p: &mut CssParser) -> ParsedSyntax { + if is_at_container_style_query_in_parens(p) { + parse_container_style_query_in_parens(p) + } else if is_at_container_query_in_parens(p) { + parse_container_query_in_parens(p) + } else if is_at_container_size_feature_in_parens(p) { + parse_container_size_feature_in_parens(p) + } else { + Absent + } +} + +#[inline] +fn is_at_container_query_in_parens(p: &mut CssParser) -> bool { + p.at(T!['(']) && (p.nth_at(1, T![not]) || p.nth_at(1, T!['('])) +} + +/// Parses a parenthesized container query. +/// +/// # Examples +/// +/// ```css +/// @container ( (width > 300px) ) { } +/// ``` +#[inline] +fn parse_container_query_in_parens(p: &mut CssParser) -> ParsedSyntax { + if !is_at_container_query_in_parens(p) { + return Absent; + } + + let m = p.start(); + + p.bump(T!['(']); + parse_any_container_query(p) + .or_recover( + p, + &AnyContainerQueryParseRecovery, + expected_any_container_query, + ) + .ok(); + p.expect(T![')']); + + Present(m.complete(p, CSS_CONTAINER_QUERY_IN_PARENS)) +} + +#[inline] +fn is_at_container_size_feature_in_parens(p: &mut CssParser) -> bool { + p.at(T!['(']) +} + +/// Parses a parenthesized [container size feature] query. +/// # Examples +/// +/// ```css +/// @container (min-width: 400px) { } +/// ``` +#[inline] +fn parse_container_size_feature_in_parens(p: &mut CssParser) -> ParsedSyntax { + if !is_at_container_size_feature_in_parens(p) { + return Absent; + } + + let m = p.start(); + + p.bump(T!['(']); + parse_any_query_feature(p) + .or_recover( + p, + &AnyQueryInParensParseRecovery, + expected_any_query_feature, + ) + .ok(); + p.expect(T![')']); + + Present(m.complete(p, CSS_CONTAINER_SIZE_FEATURE_IN_PARENS)) +} + +#[inline] +fn is_at_container_style_query_in_parens(p: &mut CssParser) -> bool { + p.at(T![style]) +} + +/// Parses a parenthesized _container style query_ following the `style` keyword. +/// +/// # Example +/// +/// ```css +/// @container style(--my-prop: some-value) { } +/// ``` +#[inline] +fn parse_container_style_query_in_parens(p: &mut CssParser) -> ParsedSyntax { + if !is_at_container_style_query_in_parens(p) { + return Absent; + } + + let m = p.start(); + + p.bump(T![style]); + p.expect(T!['(']); + parse_any_container_style_query(p) + .or_recover( + p, + &AnyQueryInParensParseRecovery, + expected_any_container_style_query, + ) + .ok(); + p.expect(T![')']); + + Present(m.complete(p, CSS_CONTAINER_STYLE_QUERY_IN_PARENS)) +} + +#[inline] +fn parse_any_container_style_query(p: &mut CssParser) -> ParsedSyntax { + if is_at_declaration(p) { + parse_declaration(p) + } else if is_at_container_style_not_query(p) { + parse_container_style_not_query(p) + } else { + parse_container_style_in_parens(p).map(|lhs| match p.cur() { + T![and] => parse_container_style_combinable_and_query(p, lhs), + T![or] => parse_container_style_combinable_or_query(p, lhs), + _ => lhs, + }) + } +} + +/// Parses a logical _and_ sequence in a container style query chain. +/// +/// # Examples +/// +/// ```css +/// @container style((color: red) and (background: blue)) { } +/// ``` +#[inline] +fn parse_container_style_combinable_and_query( + p: &mut CssParser, + lhs: CompletedMarker, +) -> CompletedMarker { + if !p.at(T![and]) { + return lhs; + } + + let m = lhs.precede(p); + p.bump(T![and]); + + let recovery_result = parse_container_style_in_parens(p) + .or_recover( + p, + &AnyContainerStyleQueryInParensChainParseRecovery::new(T![and]), + expected_any_container_style_in_parens, + ) + .map(|rhs| parse_container_style_combinable_and_query(p, rhs)); + + if recovery_result.is_err() && p.at(T![and]) { + // If we're here, it seems that we have + // @container style((--b: color) and and and ... + // parse_container_style_in_parens failed to parse, + // but the parser is already at a recovered position. + let m = p.start(); + let rhs = m.complete(p, CSS_BOGUS); + parse_container_style_combinable_and_query(p, rhs); + } + + m.complete(p, CSS_CONTAINER_STYLE_AND_QUERY) +} + +/// Parses a logical _or_ sequence in a container style query chain. +/// +/// # Examples +/// +/// ```css +/// @container style((color: red) or (background: blue)) { } +/// ``` +#[inline] +fn parse_container_style_combinable_or_query( + p: &mut CssParser, + lhs: CompletedMarker, +) -> CompletedMarker { + if !p.at(T![or]) { + return lhs; + } + + let m = lhs.precede(p); + p.bump(T![or]); + + let recovery_result = parse_container_style_in_parens(p) + .or_recover( + p, + &AnyContainerStyleQueryInParensChainParseRecovery::new(T![or]), + expected_any_container_style_in_parens, + ) + .map(|rhs| parse_container_style_combinable_or_query(p, rhs)); + + if recovery_result.is_err() && p.at(T![or]) { + // If we're here, it seems that we have + // @container style((--b: color) or or and ... + // parse_container_style_in_parens failed to parse, + // but the parser is already at a recovered position. + let m = p.start(); + let rhs = m.complete(p, CSS_BOGUS); + parse_container_style_combinable_or_query(p, rhs); + } + + m.complete(p, CSS_CONTAINER_STYLE_OR_QUERY) +} + +struct AnyContainerStyleQueryInParensChainParseRecovery { + chain_kind: CssSyntaxKind, +} + +impl AnyContainerStyleQueryInParensChainParseRecovery { + fn new(chain_kind: CssSyntaxKind) -> Self { + Self { chain_kind } + } +} + +impl ParseRecovery for AnyContainerStyleQueryInParensChainParseRecovery { + type Kind = CssSyntaxKind; + type Parser<'source> = CssParser<'source>; + const RECOVERED_KIND: Self::Kind = CSS_BOGUS; + + fn is_at_recovered(&self, p: &mut Self::Parser<'_>) -> bool { + // We need to recover from an invalid style query in parentheses: + // 1. A sub-expression boundary (another "(" or ")"). + // 2. The start of a new block ("{"). + // 3. Another chain token (like `and` or `or`), which we stored as `chain_kind`. + // 4. A preceding line break that indicates a likely end to the query. + p.at(T!['(']) + || p.at(T![')']) + || p.at(T!['{']) + || p.at(self.chain_kind) + || p.has_preceding_line_break() + } +} + +#[inline] +fn is_at_container_style_not_query(p: &mut CssParser) -> bool { + p.at(T![not]) +} + +#[inline] +fn parse_container_style_not_query(p: &mut CssParser) -> ParsedSyntax { + if !is_at_container_style_not_query(p) { + return Absent; + } + + let m = p.start(); + + p.bump(T![not]); + + parse_container_style_in_parens(p) + .or_recover( + p, + &AnyQueryInParensParseRecovery, + expected_any_container_style_in_parens, + ) + .ok(); + + Present(m.complete(p, CSS_CONTAINER_STYLE_NOT_QUERY)) +} + +#[inline] +fn is_at_container_style_in_parens(p: &mut CssParser) -> bool { + p.at(T!['(']) +} + +#[inline] +fn parse_container_style_in_parens(p: &mut CssParser) -> ParsedSyntax { + if !is_at_container_style_in_parens(p) { + return Absent; + } + + let m = p.start(); + p.bump(T!['(']); + parse_any_container_style_query(p) + .or_recover( + p, + &AnyQueryInParensParseRecovery, + expected_any_container_style_query, + ) + .ok(); + p.expect(T![')']); + Present(m.complete(p, CSS_CONTAINER_STYLE_IN_PARENS)) +} + +struct AnyQueryInParensParseRecovery; + +impl ParseRecovery for AnyQueryInParensParseRecovery { + type Kind = CssSyntaxKind; + type Parser<'source> = CssParser<'source>; + const RECOVERED_KIND: Self::Kind = CSS_BOGUS; + + fn is_at_recovered(&self, p: &mut Self::Parser<'_>) -> bool { + // Skips malformed or incomplete queries in parentheses until: + // 1) '{' (start of a declaration block), + // 2) ')' (closing this query context), or + // 3) a line break (new statement boundary). + p.at(T!['{']) || p.at(T![')']) || p.has_preceding_line_break() + } +} diff --git a/crates/biome_css_parser/src/syntax/at_rule/feature.rs b/crates/biome_css_parser/src/syntax/at_rule/feature.rs index 890cdcdaa191..e2fded6698e2 100644 --- a/crates/biome_css_parser/src/syntax/at_rule/feature.rs +++ b/crates/biome_css_parser/src/syntax/at_rule/feature.rs @@ -2,7 +2,8 @@ use crate::parser::CssParser; use crate::syntax::parse_error::expected_identifier; use crate::syntax::{is_at_any_value, is_at_identifier, parse_any_value, parse_regular_identifier}; use biome_css_syntax::CssSyntaxKind::*; -use biome_css_syntax::{CssSyntaxKind, T}; +use biome_css_syntax::{CssSyntaxKind, T, TextRange}; +use biome_parser::diagnostic::{ParseDiagnostic, ToDiagnostic, expect_one_of}; use biome_parser::parsed_syntax::ParsedSyntax; use biome_parser::parsed_syntax::ParsedSyntax::{Absent, Present}; use biome_parser::{Parser, TokenSet, token_set}; @@ -138,3 +139,16 @@ fn parse_any_query_feature_value(p: &mut CssParser) -> ParsedSyntax { // TODO add diagnostics if the any value is different with gramma parse_any_value(p) } + +pub(crate) fn expected_any_query_feature(p: &CssParser, range: TextRange) -> ParseDiagnostic { + expect_one_of( + &[ + "", + "", + "", + " or ", + ], + range, + ) + .into_diagnostic(p) +} diff --git a/crates/biome_css_parser/src/syntax/block/mod.rs b/crates/biome_css_parser/src/syntax/block/mod.rs index 95c25ee75a59..e95903c1dd56 100644 --- a/crates/biome_css_parser/src/syntax/block/mod.rs +++ b/crates/biome_css_parser/src/syntax/block/mod.rs @@ -37,13 +37,16 @@ pub(crate) trait ParseBlockBody { let is_open_brace_missing = !p.expect(T!['{']); - if is_open_brace_missing && (!self.is_at_element(p) || p.state().speculative_parsing) { + // skip parsing if we are not at the start of a element or a closing brace + // or if we are in a speculative parsing state + if is_open_brace_missing + && (!self.is_at_element(p) && !p.at(T!['}']) || p.state().speculative_parsing) + { p.error(expected_block(p, p.cur_range())); return m.complete(p, CSS_BOGUS_BLOCK); } let old_nesting_block = std::mem::replace(&mut p.state_mut().is_nesting_block, true); - self.parse_list(p); let is_close_brace_missing = !p.expect(T!['}']); diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_and_query_error.css b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_and_query_error.css new file mode 100644 index 000000000000..484cf3cea926 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_and_query_error.css @@ -0,0 +1,27 @@ +/* No valid container query after `and` */ +@container (width > 300px) and { +} + +/* No valid container query after `and missing {` */ +@container (width > 300px) and +} + +/* 200px is not a valid container query start */ +@container (width > 300px) and 200px { +} + +/* The final `and` is missing its sub-query */ +@container (width > 300px) and (height > 200px) and { +} + +/* Missing parenthesis */ +@container (width > 300px) and width > 200px and (height > 200px) { +} + +/* There's an extra `and` that has no query immediately following it. */ +@container (width > 300px) and and (height > 200px) { +} + +/* Invalid query name */ +@container (width > 300px) and randomname and (height > 200px) { +} diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_and_query_error.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_and_query_error.css.snap new file mode 100644 index 000000000000..e2b9c1a631c4 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_and_query_error.css.snap @@ -0,0 +1,728 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```css +/* No valid container query after `and` */ +@container (width > 300px) and { +} + +/* No valid container query after `and missing {` */ +@container (width > 300px) and +} + +/* 200px is not a valid container query start */ +@container (width > 300px) and 200px { +} + +/* The final `and` is missing its sub-query */ +@container (width > 300px) and (height > 200px) and { +} + +/* Missing parenthesis */ +@container (width > 300px) and width > 200px and (height > 200px) { +} + +/* There's an extra `and` that has no query immediately following it. */ +@container (width > 300px) and and (height > 200px) { +} + +/* Invalid query name */ +@container (width > 300px) and randomname and (height > 200px) { +} + +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssAtRule { + at_token: AT@0..44 "@" [Comments("/* No valid container ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@44..54 "container" [] [Whitespace(" ")], + name: missing (optional), + query: CssContainerAndQuery { + left: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@54..55 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@55..61 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@61..63 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@63..66 "300" [] [], + unit_token: IDENT@66..68 "px" [] [], + }, + }, + r_paren_token: R_PAREN@68..70 ")" [] [Whitespace(" ")], + }, + and_token: AND_KW@70..74 "and" [] [Whitespace(" ")], + right: missing (required), + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@74..75 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@75..77 "}" [Newline("\n")] [], + }, + }, + }, + CssAtRule { + at_token: AT@77..133 "@" [Newline("\n"), Newline("\n"), Comments("/* No valid container ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@133..143 "container" [] [Whitespace(" ")], + name: missing (optional), + query: CssContainerAndQuery { + left: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@143..144 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@144..150 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@150..152 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@152..155 "300" [] [], + unit_token: IDENT@155..157 "px" [] [], + }, + }, + r_paren_token: R_PAREN@157..159 ")" [] [Whitespace(" ")], + }, + and_token: AND_KW@159..162 "and" [] [], + right: missing (required), + }, + block: CssBogusBlock { + items: [ + CssRuleList [], + R_CURLY@162..164 "}" [Newline("\n")] [], + ], + }, + }, + }, + CssAtRule { + at_token: AT@164..216 "@" [Newline("\n"), Newline("\n"), Comments("/* 200px is not a val ..."), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@216..226 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@226..227 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@227..233 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@233..235 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@235..238 "300" [] [], + unit_token: IDENT@238..240 "px" [] [], + }, + }, + r_paren_token: R_PAREN@240..242 ")" [] [Whitespace(" ")], + }, + AND_KW@242..246 "and" [] [Whitespace(" ")], + CssBogus { + items: [ + CSS_DIMENSION_VALUE@246..249 "200" [] [], + PX_KW@249..252 "px" [] [Whitespace(" ")], + ], + }, + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@252..253 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@253..255 "}" [Newline("\n")] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@255..305 "@" [Newline("\n"), Newline("\n"), Comments("/* The final `and` is ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@305..315 "container" [] [Whitespace(" ")], + name: missing (optional), + query: CssContainerAndQuery { + left: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@315..316 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@316..322 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@322..324 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@324..327 "300" [] [], + unit_token: IDENT@327..329 "px" [] [], + }, + }, + r_paren_token: R_PAREN@329..331 ")" [] [Whitespace(" ")], + }, + and_token: AND_KW@331..335 "and" [] [Whitespace(" ")], + right: CssContainerAndQuery { + left: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@335..336 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@336..343 "height" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@343..345 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@345..348 "200" [] [], + unit_token: IDENT@348..350 "px" [] [], + }, + }, + r_paren_token: R_PAREN@350..352 ")" [] [Whitespace(" ")], + }, + and_token: AND_KW@352..356 "and" [] [Whitespace(" ")], + right: missing (required), + }, + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@356..357 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@357..359 "}" [Newline("\n")] [], + }, + }, + }, + CssAtRule { + at_token: AT@359..389 "@" [Newline("\n"), Newline("\n"), Comments("/* Missing parenthesi ..."), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@389..399 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@399..400 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@400..406 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@406..408 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@408..411 "300" [] [], + unit_token: IDENT@411..413 "px" [] [], + }, + }, + r_paren_token: R_PAREN@413..415 ")" [] [Whitespace(" ")], + }, + AND_KW@415..419 "and" [] [Whitespace(" ")], + CssBogus { + items: [ + CssBogus { + items: [ + IDENT@419..425 "width" [] [Whitespace(" ")], + R_ANGLE@425..427 ">" [] [Whitespace(" ")], + CSS_DIMENSION_VALUE@427..430 "200" [] [], + PX_KW@430..433 "px" [] [Whitespace(" ")], + ], + }, + AND_KW@433..437 "and" [] [Whitespace(" ")], + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@437..438 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@438..445 "height" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@445..447 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@447..450 "200" [] [], + unit_token: IDENT@450..452 "px" [] [], + }, + }, + r_paren_token: R_PAREN@452..454 ")" [] [Whitespace(" ")], + }, + ], + }, + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@454..455 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@455..457 "}" [Newline("\n")] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@457..533 "@" [Newline("\n"), Newline("\n"), Comments("/* There's an extra ` ..."), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@533..543 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@543..544 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@544..550 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@550..552 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@552..555 "300" [] [], + unit_token: IDENT@555..557 "px" [] [], + }, + }, + r_paren_token: R_PAREN@557..559 ")" [] [Whitespace(" ")], + }, + AND_KW@559..563 "and" [] [Whitespace(" ")], + CssBogus { + items: [ + CssBogus { + items: [], + }, + AND_KW@563..567 "and" [] [Whitespace(" ")], + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@567..568 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@568..575 "height" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@575..577 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@577..580 "200" [] [], + unit_token: IDENT@580..582 "px" [] [], + }, + }, + r_paren_token: R_PAREN@582..584 ")" [] [Whitespace(" ")], + }, + ], + }, + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@584..585 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@585..587 "}" [Newline("\n")] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@587..615 "@" [Newline("\n"), Newline("\n"), Comments("/* Invalid query name */"), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@615..625 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@625..626 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@626..632 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@632..634 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@634..637 "300" [] [], + unit_token: IDENT@637..639 "px" [] [], + }, + }, + r_paren_token: R_PAREN@639..641 ")" [] [Whitespace(" ")], + }, + AND_KW@641..645 "and" [] [Whitespace(" ")], + CssBogus { + items: [ + CssBogus { + items: [ + IDENT@645..656 "randomname" [] [Whitespace(" ")], + ], + }, + AND_KW@656..660 "and" [] [Whitespace(" ")], + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@660..661 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@661..668 "height" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@668..670 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@670..673 "200" [] [], + unit_token: IDENT@673..675 "px" [] [], + }, + }, + r_paren_token: R_PAREN@675..677 ")" [] [Whitespace(" ")], + }, + ], + }, + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@677..678 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@678..680 "}" [Newline("\n")] [], + }, + ], + }, + }, + ], + eof_token: EOF@680..681 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..681 + 0: (empty) + 1: CSS_RULE_LIST@0..680 + 0: CSS_AT_RULE@0..77 + 0: AT@0..44 "@" [Comments("/* No valid container ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@44..77 + 0: CONTAINER_KW@44..54 "container" [] [Whitespace(" ")] + 1: (empty) + 2: CSS_CONTAINER_AND_QUERY@54..74 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@54..70 + 0: L_PAREN@54..55 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@55..68 + 0: CSS_IDENTIFIER@55..61 + 0: IDENT@55..61 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@61..63 + 0: R_ANGLE@61..63 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@63..68 + 0: CSS_NUMBER_LITERAL@63..66 "300" [] [] + 1: IDENT@66..68 "px" [] [] + 2: R_PAREN@68..70 ")" [] [Whitespace(" ")] + 1: AND_KW@70..74 "and" [] [Whitespace(" ")] + 2: (empty) + 3: CSS_RULE_BLOCK@74..77 + 0: L_CURLY@74..75 "{" [] [] + 1: CSS_RULE_LIST@75..75 + 2: R_CURLY@75..77 "}" [Newline("\n")] [] + 1: CSS_AT_RULE@77..164 + 0: AT@77..133 "@" [Newline("\n"), Newline("\n"), Comments("/* No valid container ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@133..164 + 0: CONTAINER_KW@133..143 "container" [] [Whitespace(" ")] + 1: (empty) + 2: CSS_CONTAINER_AND_QUERY@143..162 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@143..159 + 0: L_PAREN@143..144 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@144..157 + 0: CSS_IDENTIFIER@144..150 + 0: IDENT@144..150 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@150..152 + 0: R_ANGLE@150..152 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@152..157 + 0: CSS_NUMBER_LITERAL@152..155 "300" [] [] + 1: IDENT@155..157 "px" [] [] + 2: R_PAREN@157..159 ")" [] [Whitespace(" ")] + 1: AND_KW@159..162 "and" [] [] + 2: (empty) + 3: CSS_BOGUS_BLOCK@162..164 + 0: CSS_RULE_LIST@162..162 + 1: R_CURLY@162..164 "}" [Newline("\n")] [] + 2: CSS_AT_RULE@164..255 + 0: AT@164..216 "@" [Newline("\n"), Newline("\n"), Comments("/* 200px is not a val ..."), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@216..255 + 0: CONTAINER_KW@216..226 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@226..252 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@226..242 + 0: L_PAREN@226..227 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@227..240 + 0: CSS_IDENTIFIER@227..233 + 0: IDENT@227..233 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@233..235 + 0: R_ANGLE@233..235 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@235..240 + 0: CSS_NUMBER_LITERAL@235..238 "300" [] [] + 1: IDENT@238..240 "px" [] [] + 2: R_PAREN@240..242 ")" [] [Whitespace(" ")] + 1: AND_KW@242..246 "and" [] [Whitespace(" ")] + 2: CSS_BOGUS@246..252 + 0: CSS_DIMENSION_VALUE@246..249 "200" [] [] + 1: PX_KW@249..252 "px" [] [Whitespace(" ")] + 2: CSS_RULE_BLOCK@252..255 + 0: L_CURLY@252..253 "{" [] [] + 1: CSS_RULE_LIST@253..253 + 2: R_CURLY@253..255 "}" [Newline("\n")] [] + 3: CSS_AT_RULE@255..359 + 0: AT@255..305 "@" [Newline("\n"), Newline("\n"), Comments("/* The final `and` is ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@305..359 + 0: CONTAINER_KW@305..315 "container" [] [Whitespace(" ")] + 1: (empty) + 2: CSS_CONTAINER_AND_QUERY@315..356 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@315..331 + 0: L_PAREN@315..316 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@316..329 + 0: CSS_IDENTIFIER@316..322 + 0: IDENT@316..322 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@322..324 + 0: R_ANGLE@322..324 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@324..329 + 0: CSS_NUMBER_LITERAL@324..327 "300" [] [] + 1: IDENT@327..329 "px" [] [] + 2: R_PAREN@329..331 ")" [] [Whitespace(" ")] + 1: AND_KW@331..335 "and" [] [Whitespace(" ")] + 2: CSS_CONTAINER_AND_QUERY@335..356 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@335..352 + 0: L_PAREN@335..336 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@336..350 + 0: CSS_IDENTIFIER@336..343 + 0: IDENT@336..343 "height" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@343..345 + 0: R_ANGLE@343..345 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@345..350 + 0: CSS_NUMBER_LITERAL@345..348 "200" [] [] + 1: IDENT@348..350 "px" [] [] + 2: R_PAREN@350..352 ")" [] [Whitespace(" ")] + 1: AND_KW@352..356 "and" [] [Whitespace(" ")] + 2: (empty) + 3: CSS_RULE_BLOCK@356..359 + 0: L_CURLY@356..357 "{" [] [] + 1: CSS_RULE_LIST@357..357 + 2: R_CURLY@357..359 "}" [Newline("\n")] [] + 4: CSS_AT_RULE@359..457 + 0: AT@359..389 "@" [Newline("\n"), Newline("\n"), Comments("/* Missing parenthesi ..."), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@389..457 + 0: CONTAINER_KW@389..399 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@399..454 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@399..415 + 0: L_PAREN@399..400 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@400..413 + 0: CSS_IDENTIFIER@400..406 + 0: IDENT@400..406 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@406..408 + 0: R_ANGLE@406..408 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@408..413 + 0: CSS_NUMBER_LITERAL@408..411 "300" [] [] + 1: IDENT@411..413 "px" [] [] + 2: R_PAREN@413..415 ")" [] [Whitespace(" ")] + 1: AND_KW@415..419 "and" [] [Whitespace(" ")] + 2: CSS_BOGUS@419..454 + 0: CSS_BOGUS@419..433 + 0: IDENT@419..425 "width" [] [Whitespace(" ")] + 1: R_ANGLE@425..427 ">" [] [Whitespace(" ")] + 2: CSS_DIMENSION_VALUE@427..430 "200" [] [] + 3: PX_KW@430..433 "px" [] [Whitespace(" ")] + 1: AND_KW@433..437 "and" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@437..454 + 0: L_PAREN@437..438 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@438..452 + 0: CSS_IDENTIFIER@438..445 + 0: IDENT@438..445 "height" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@445..447 + 0: R_ANGLE@445..447 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@447..452 + 0: CSS_NUMBER_LITERAL@447..450 "200" [] [] + 1: IDENT@450..452 "px" [] [] + 2: R_PAREN@452..454 ")" [] [Whitespace(" ")] + 2: CSS_RULE_BLOCK@454..457 + 0: L_CURLY@454..455 "{" [] [] + 1: CSS_RULE_LIST@455..455 + 2: R_CURLY@455..457 "}" [Newline("\n")] [] + 5: CSS_AT_RULE@457..587 + 0: AT@457..533 "@" [Newline("\n"), Newline("\n"), Comments("/* There's an extra ` ..."), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@533..587 + 0: CONTAINER_KW@533..543 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@543..584 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@543..559 + 0: L_PAREN@543..544 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@544..557 + 0: CSS_IDENTIFIER@544..550 + 0: IDENT@544..550 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@550..552 + 0: R_ANGLE@550..552 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@552..557 + 0: CSS_NUMBER_LITERAL@552..555 "300" [] [] + 1: IDENT@555..557 "px" [] [] + 2: R_PAREN@557..559 ")" [] [Whitespace(" ")] + 1: AND_KW@559..563 "and" [] [Whitespace(" ")] + 2: CSS_BOGUS@563..584 + 0: CSS_BOGUS@563..563 + 1: AND_KW@563..567 "and" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@567..584 + 0: L_PAREN@567..568 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@568..582 + 0: CSS_IDENTIFIER@568..575 + 0: IDENT@568..575 "height" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@575..577 + 0: R_ANGLE@575..577 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@577..582 + 0: CSS_NUMBER_LITERAL@577..580 "200" [] [] + 1: IDENT@580..582 "px" [] [] + 2: R_PAREN@582..584 ")" [] [Whitespace(" ")] + 2: CSS_RULE_BLOCK@584..587 + 0: L_CURLY@584..585 "{" [] [] + 1: CSS_RULE_LIST@585..585 + 2: R_CURLY@585..587 "}" [Newline("\n")] [] + 6: CSS_AT_RULE@587..680 + 0: AT@587..615 "@" [Newline("\n"), Newline("\n"), Comments("/* Invalid query name */"), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@615..680 + 0: CONTAINER_KW@615..625 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@625..677 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@625..641 + 0: L_PAREN@625..626 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@626..639 + 0: CSS_IDENTIFIER@626..632 + 0: IDENT@626..632 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@632..634 + 0: R_ANGLE@632..634 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@634..639 + 0: CSS_NUMBER_LITERAL@634..637 "300" [] [] + 1: IDENT@637..639 "px" [] [] + 2: R_PAREN@639..641 ")" [] [Whitespace(" ")] + 1: AND_KW@641..645 "and" [] [Whitespace(" ")] + 2: CSS_BOGUS@645..677 + 0: CSS_BOGUS@645..656 + 0: IDENT@645..656 "randomname" [] [Whitespace(" ")] + 1: AND_KW@656..660 "and" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@660..677 + 0: L_PAREN@660..661 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@661..675 + 0: CSS_IDENTIFIER@661..668 + 0: IDENT@661..668 "height" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@668..670 + 0: R_ANGLE@668..670 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@670..675 + 0: CSS_NUMBER_LITERAL@670..673 "200" [] [] + 1: IDENT@673..675 "px" [] [] + 2: R_PAREN@675..677 ")" [] [Whitespace(" ")] + 2: CSS_RULE_BLOCK@677..680 + 0: L_CURLY@677..678 "{" [] [] + 1: CSS_RULE_LIST@678..678 + 2: R_CURLY@678..680 "}" [Newline("\n")] [] + 2: EOF@680..681 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +at_rule_container_and_query_error.css:2:32 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 1 │ /* No valid container query after `and` */ + > 2 │ @container (width > 300px) and { + │ ^ + 3 │ } + 4 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_and_query_error.css:7:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 5 │ /* No valid container query after `and missing {` */ + 6 │ @container (width > 300px) and + > 7 │ } + │ ^ + 8 │ + 9 │ /* 200px is not a valid container query start */ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_and_query_error.css:10:32 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 9 │ /* 200px is not a valid container query start */ + > 10 │ @container (width > 300px) and 200px { + │ ^^^^^ + 11 │ } + 12 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_and_query_error.css:14:53 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 13 │ /* The final `and` is missing its sub-query */ + > 14 │ @container (width > 300px) and (height > 200px) and { + │ ^ + 15 │ } + 16 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_and_query_error.css:18:32 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 17 │ /* Missing parenthesis */ + > 18 │ @container (width > 300px) and width > 200px and (height > 200px) { + │ ^^^^^^^^^^^^^ + 19 │ } + 20 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_and_query_error.css:22:32 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 21 │ /* There's an extra `and` that has no query immediately following it. */ + > 22 │ @container (width > 300px) and and (height > 200px) { + │ ^^^ + 23 │ } + 24 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_and_query_error.css:26:32 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 25 │ /* Invalid query name */ + > 26 │ @container (width > 300px) and randomname and (height > 200px) { + │ ^^^^^^^^^^ + 27 │ } + 28 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +``` diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container_error.css b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_error.css similarity index 100% rename from crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container_error.css rename to crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_error.css diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_error.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_error.css.snap new file mode 100644 index 000000000000..3df5bfb3b97d --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_error.css.snap @@ -0,0 +1,955 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```css +@container inherit (width <= 500px) { } +@container initial (width <= 500px) { } +@container unset (width <= 500px) { } +@container revert (width <= 500px) { } +@container revert-layer (width <= 500px) { } +@container inherit width <= 500px) { } + +@container not width <= 500px) { } + +@container not (width <= 500px { } +@container not (width <=) { } +@container not { } + +@container my-layout (inline-size > 45em) { } + +@container card (inline-size > 30em) or { } + +@container (inline-size >= 0px) } + +@container { } +@container () { } + +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssAtRule { + at_token: AT@0..1 "@" [] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@1..11 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + INHERIT_KW@11..19 "inherit" [] [Whitespace(" ")], + ], + }, + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@19..20 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@20..26 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: LTEQ@26..29 "<=" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@29..32 "500" [] [], + unit_token: IDENT@32..34 "px" [] [], + }, + }, + r_paren_token: R_PAREN@34..36 ")" [] [Whitespace(" ")], + }, + CssRuleBlock { + l_curly_token: L_CURLY@36..38 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@38..39 "}" [] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@39..41 "@" [Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@41..51 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + INITIAL_KW@51..59 "initial" [] [Whitespace(" ")], + ], + }, + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@59..60 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@60..66 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: LTEQ@66..69 "<=" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@69..72 "500" [] [], + unit_token: IDENT@72..74 "px" [] [], + }, + }, + r_paren_token: R_PAREN@74..76 ")" [] [Whitespace(" ")], + }, + CssRuleBlock { + l_curly_token: L_CURLY@76..78 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@78..79 "}" [] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@79..81 "@" [Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@81..91 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + UNSET_KW@91..97 "unset" [] [Whitespace(" ")], + ], + }, + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@97..98 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@98..104 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: LTEQ@104..107 "<=" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@107..110 "500" [] [], + unit_token: IDENT@110..112 "px" [] [], + }, + }, + r_paren_token: R_PAREN@112..114 ")" [] [Whitespace(" ")], + }, + CssRuleBlock { + l_curly_token: L_CURLY@114..116 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@116..117 "}" [] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@117..119 "@" [Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@119..129 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + REVERT_KW@129..136 "revert" [] [Whitespace(" ")], + ], + }, + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@136..137 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@137..143 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: LTEQ@143..146 "<=" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@146..149 "500" [] [], + unit_token: IDENT@149..151 "px" [] [], + }, + }, + r_paren_token: R_PAREN@151..153 ")" [] [Whitespace(" ")], + }, + CssRuleBlock { + l_curly_token: L_CURLY@153..155 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@155..156 "}" [] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@156..158 "@" [Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@158..168 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + REVERT_LAYER_KW@168..181 "revert-layer" [] [Whitespace(" ")], + ], + }, + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@181..182 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@182..188 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: LTEQ@188..191 "<=" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@191..194 "500" [] [], + unit_token: IDENT@194..196 "px" [] [], + }, + }, + r_paren_token: R_PAREN@196..198 ")" [] [Whitespace(" ")], + }, + CssRuleBlock { + l_curly_token: L_CURLY@198..200 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@200..201 "}" [] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@201..203 "@" [Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@203..213 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + INHERIT_KW@213..221 "inherit" [] [Whitespace(" ")], + ], + }, + CssBogus { + items: [ + IDENT@221..227 "width" [] [Whitespace(" ")], + LTEQ@227..230 "<=" [] [Whitespace(" ")], + CSS_DIMENSION_VALUE@230..233 "500" [] [], + PX_KW@233..235 "px" [] [], + R_PAREN@235..237 ")" [] [Whitespace(" ")], + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@237..239 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@239..240 "}" [] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@240..243 "@" [Newline("\n"), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@243..253 "container" [] [Whitespace(" ")], + CssCustomIdentifier { + value_token: IDENT@253..257 "not" [] [Whitespace(" ")], + }, + CssBogus { + items: [ + IDENT@257..263 "width" [] [Whitespace(" ")], + LTEQ@263..266 "<=" [] [Whitespace(" ")], + CSS_DIMENSION_VALUE@266..269 "500" [] [], + PX_KW@269..271 "px" [] [], + R_PAREN@271..273 ")" [] [Whitespace(" ")], + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@273..276 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@276..277 "}" [] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@277..280 "@" [Newline("\n"), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@280..290 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@290..294 "not" [] [Whitespace(" ")], + }, + query: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@294..295 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@295..301 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: LTEQ@301..304 "<=" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@304..307 "500" [] [], + unit_token: IDENT@307..310 "px" [] [Whitespace(" ")], + }, + }, + r_paren_token: missing (required), + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@310..313 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@313..314 "}" [] [], + }, + }, + }, + CssAtRule { + at_token: AT@314..316 "@" [Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@316..326 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@326..330 "not" [] [Whitespace(" ")], + }, + query: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@330..331 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@331..337 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: LTEQ@337..339 "<=" [] [], + }, + right: missing (required), + }, + r_paren_token: R_PAREN@339..341 ")" [] [Whitespace(" ")], + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@341..344 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@344..345 "}" [] [], + }, + }, + }, + CssAtRule { + at_token: AT@345..347 "@" [Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@347..357 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@357..361 "not" [] [Whitespace(" ")], + }, + query: missing (required), + block: CssRuleBlock { + l_curly_token: L_CURLY@361..364 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@364..365 "}" [] [], + }, + }, + }, + CssAtRule { + at_token: AT@365..368 "@" [Newline("\n"), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@368..378 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@378..388 "my-layout" [] [Whitespace(" ")], + }, + query: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@388..389 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@389..401 "inline-size" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@401..403 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@403..405 "45" [] [], + unit_token: IDENT@405..407 "em" [] [], + }, + }, + r_paren_token: R_PAREN@407..409 ")" [] [Whitespace(" ")], + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@409..412 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@412..413 "}" [] [], + }, + }, + }, + CssAtRule { + at_token: AT@413..416 "@" [Newline("\n"), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@416..426 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@426..431 "card" [] [Whitespace(" ")], + }, + query: CssContainerOrQuery { + left: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@431..432 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@432..444 "inline-size" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@444..446 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@446..448 "30" [] [], + unit_token: IDENT@448..450 "em" [] [], + }, + }, + r_paren_token: R_PAREN@450..452 ")" [] [Whitespace(" ")], + }, + or_token: OR_KW@452..455 "or" [] [Whitespace(" ")], + right: missing (required), + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@455..458 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@458..459 "}" [] [], + }, + }, + }, + CssAtRule { + at_token: AT@459..462 "@" [Newline("\n"), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@462..472 "container" [] [Whitespace(" ")], + name: missing (optional), + query: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@472..473 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@473..485 "inline-size" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: GTEQ@485..488 ">=" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@488..489 "0" [] [], + unit_token: IDENT@489..491 "px" [] [], + }, + }, + r_paren_token: R_PAREN@491..494 ")" [] [Whitespace(" ")], + }, + block: CssBogusBlock { + items: [ + CssRuleList [], + R_CURLY@494..495 "}" [] [], + ], + }, + }, + }, + CssAtRule { + at_token: AT@495..498 "@" [Newline("\n"), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@498..508 "container" [] [Whitespace(" ")], + name: missing (optional), + query: missing (required), + block: CssRuleBlock { + l_curly_token: L_CURLY@508..510 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@510..511 "}" [] [], + }, + }, + }, + CssAtRule { + at_token: AT@511..513 "@" [Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@513..523 "container" [] [Whitespace(" ")], + name: missing (optional), + query: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@523..524 "(" [] [], + feature: missing (required), + r_paren_token: R_PAREN@524..526 ")" [] [Whitespace(" ")], + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@526..528 "{" [] [Whitespace(" ")], + rules: CssRuleList [], + r_curly_token: R_CURLY@528..529 "}" [] [], + }, + }, + }, + ], + eof_token: EOF@529..530 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..530 + 0: (empty) + 1: CSS_RULE_LIST@0..529 + 0: CSS_AT_RULE@0..39 + 0: AT@0..1 "@" [] [] + 1: CSS_BOGUS_AT_RULE@1..39 + 0: CONTAINER_KW@1..11 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@11..19 + 0: INHERIT_KW@11..19 "inherit" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@19..36 + 0: L_PAREN@19..20 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@20..34 + 0: CSS_IDENTIFIER@20..26 + 0: IDENT@20..26 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@26..29 + 0: LTEQ@26..29 "<=" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@29..34 + 0: CSS_NUMBER_LITERAL@29..32 "500" [] [] + 1: IDENT@32..34 "px" [] [] + 2: R_PAREN@34..36 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@36..39 + 0: L_CURLY@36..38 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@38..38 + 2: R_CURLY@38..39 "}" [] [] + 1: CSS_AT_RULE@39..79 + 0: AT@39..41 "@" [Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@41..79 + 0: CONTAINER_KW@41..51 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@51..59 + 0: INITIAL_KW@51..59 "initial" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@59..76 + 0: L_PAREN@59..60 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@60..74 + 0: CSS_IDENTIFIER@60..66 + 0: IDENT@60..66 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@66..69 + 0: LTEQ@66..69 "<=" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@69..74 + 0: CSS_NUMBER_LITERAL@69..72 "500" [] [] + 1: IDENT@72..74 "px" [] [] + 2: R_PAREN@74..76 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@76..79 + 0: L_CURLY@76..78 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@78..78 + 2: R_CURLY@78..79 "}" [] [] + 2: CSS_AT_RULE@79..117 + 0: AT@79..81 "@" [Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@81..117 + 0: CONTAINER_KW@81..91 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@91..97 + 0: UNSET_KW@91..97 "unset" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@97..114 + 0: L_PAREN@97..98 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@98..112 + 0: CSS_IDENTIFIER@98..104 + 0: IDENT@98..104 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@104..107 + 0: LTEQ@104..107 "<=" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@107..112 + 0: CSS_NUMBER_LITERAL@107..110 "500" [] [] + 1: IDENT@110..112 "px" [] [] + 2: R_PAREN@112..114 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@114..117 + 0: L_CURLY@114..116 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@116..116 + 2: R_CURLY@116..117 "}" [] [] + 3: CSS_AT_RULE@117..156 + 0: AT@117..119 "@" [Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@119..156 + 0: CONTAINER_KW@119..129 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@129..136 + 0: REVERT_KW@129..136 "revert" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@136..153 + 0: L_PAREN@136..137 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@137..151 + 0: CSS_IDENTIFIER@137..143 + 0: IDENT@137..143 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@143..146 + 0: LTEQ@143..146 "<=" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@146..151 + 0: CSS_NUMBER_LITERAL@146..149 "500" [] [] + 1: IDENT@149..151 "px" [] [] + 2: R_PAREN@151..153 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@153..156 + 0: L_CURLY@153..155 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@155..155 + 2: R_CURLY@155..156 "}" [] [] + 4: CSS_AT_RULE@156..201 + 0: AT@156..158 "@" [Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@158..201 + 0: CONTAINER_KW@158..168 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@168..181 + 0: REVERT_LAYER_KW@168..181 "revert-layer" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@181..198 + 0: L_PAREN@181..182 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@182..196 + 0: CSS_IDENTIFIER@182..188 + 0: IDENT@182..188 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@188..191 + 0: LTEQ@188..191 "<=" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@191..196 + 0: CSS_NUMBER_LITERAL@191..194 "500" [] [] + 1: IDENT@194..196 "px" [] [] + 2: R_PAREN@196..198 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@198..201 + 0: L_CURLY@198..200 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@200..200 + 2: R_CURLY@200..201 "}" [] [] + 5: CSS_AT_RULE@201..240 + 0: AT@201..203 "@" [Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@203..240 + 0: CONTAINER_KW@203..213 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@213..221 + 0: INHERIT_KW@213..221 "inherit" [] [Whitespace(" ")] + 2: CSS_BOGUS@221..237 + 0: IDENT@221..227 "width" [] [Whitespace(" ")] + 1: LTEQ@227..230 "<=" [] [Whitespace(" ")] + 2: CSS_DIMENSION_VALUE@230..233 "500" [] [] + 3: PX_KW@233..235 "px" [] [] + 4: R_PAREN@235..237 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@237..240 + 0: L_CURLY@237..239 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@239..239 + 2: R_CURLY@239..240 "}" [] [] + 6: CSS_AT_RULE@240..277 + 0: AT@240..243 "@" [Newline("\n"), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@243..277 + 0: CONTAINER_KW@243..253 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@253..257 + 0: IDENT@253..257 "not" [] [Whitespace(" ")] + 2: CSS_BOGUS@257..273 + 0: IDENT@257..263 "width" [] [Whitespace(" ")] + 1: LTEQ@263..266 "<=" [] [Whitespace(" ")] + 2: CSS_DIMENSION_VALUE@266..269 "500" [] [] + 3: PX_KW@269..271 "px" [] [] + 4: R_PAREN@271..273 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@273..277 + 0: L_CURLY@273..276 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@276..276 + 2: R_CURLY@276..277 "}" [] [] + 7: CSS_AT_RULE@277..314 + 0: AT@277..280 "@" [Newline("\n"), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@280..314 + 0: CONTAINER_KW@280..290 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@290..294 + 0: IDENT@290..294 "not" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@294..310 + 0: L_PAREN@294..295 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@295..310 + 0: CSS_IDENTIFIER@295..301 + 0: IDENT@295..301 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@301..304 + 0: LTEQ@301..304 "<=" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@304..310 + 0: CSS_NUMBER_LITERAL@304..307 "500" [] [] + 1: IDENT@307..310 "px" [] [Whitespace(" ")] + 2: (empty) + 3: CSS_RULE_BLOCK@310..314 + 0: L_CURLY@310..313 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@313..313 + 2: R_CURLY@313..314 "}" [] [] + 8: CSS_AT_RULE@314..345 + 0: AT@314..316 "@" [Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@316..345 + 0: CONTAINER_KW@316..326 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@326..330 + 0: IDENT@326..330 "not" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@330..341 + 0: L_PAREN@330..331 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@331..339 + 0: CSS_IDENTIFIER@331..337 + 0: IDENT@331..337 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@337..339 + 0: LTEQ@337..339 "<=" [] [] + 2: (empty) + 2: R_PAREN@339..341 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@341..345 + 0: L_CURLY@341..344 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@344..344 + 2: R_CURLY@344..345 "}" [] [] + 9: CSS_AT_RULE@345..365 + 0: AT@345..347 "@" [Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@347..365 + 0: CONTAINER_KW@347..357 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@357..361 + 0: IDENT@357..361 "not" [] [Whitespace(" ")] + 2: (empty) + 3: CSS_RULE_BLOCK@361..365 + 0: L_CURLY@361..364 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@364..364 + 2: R_CURLY@364..365 "}" [] [] + 10: CSS_AT_RULE@365..413 + 0: AT@365..368 "@" [Newline("\n"), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@368..413 + 0: CONTAINER_KW@368..378 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@378..388 + 0: IDENT@378..388 "my-layout" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@388..409 + 0: L_PAREN@388..389 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@389..407 + 0: CSS_IDENTIFIER@389..401 + 0: IDENT@389..401 "inline-size" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@401..403 + 0: R_ANGLE@401..403 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@403..407 + 0: CSS_NUMBER_LITERAL@403..405 "45" [] [] + 1: IDENT@405..407 "em" [] [] + 2: R_PAREN@407..409 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@409..413 + 0: L_CURLY@409..412 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@412..412 + 2: R_CURLY@412..413 "}" [] [] + 11: CSS_AT_RULE@413..459 + 0: AT@413..416 "@" [Newline("\n"), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@416..459 + 0: CONTAINER_KW@416..426 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@426..431 + 0: IDENT@426..431 "card" [] [Whitespace(" ")] + 2: CSS_CONTAINER_OR_QUERY@431..455 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@431..452 + 0: L_PAREN@431..432 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@432..450 + 0: CSS_IDENTIFIER@432..444 + 0: IDENT@432..444 "inline-size" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@444..446 + 0: R_ANGLE@444..446 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@446..450 + 0: CSS_NUMBER_LITERAL@446..448 "30" [] [] + 1: IDENT@448..450 "em" [] [] + 2: R_PAREN@450..452 ")" [] [Whitespace(" ")] + 1: OR_KW@452..455 "or" [] [Whitespace(" ")] + 2: (empty) + 3: CSS_RULE_BLOCK@455..459 + 0: L_CURLY@455..458 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@458..458 + 2: R_CURLY@458..459 "}" [] [] + 12: CSS_AT_RULE@459..495 + 0: AT@459..462 "@" [Newline("\n"), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@462..495 + 0: CONTAINER_KW@462..472 "container" [] [Whitespace(" ")] + 1: (empty) + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@472..494 + 0: L_PAREN@472..473 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@473..491 + 0: CSS_IDENTIFIER@473..485 + 0: IDENT@473..485 "inline-size" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@485..488 + 0: GTEQ@485..488 ">=" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@488..491 + 0: CSS_NUMBER_LITERAL@488..489 "0" [] [] + 1: IDENT@489..491 "px" [] [] + 2: R_PAREN@491..494 ")" [] [Whitespace(" ")] + 3: CSS_BOGUS_BLOCK@494..495 + 0: CSS_RULE_LIST@494..494 + 1: R_CURLY@494..495 "}" [] [] + 13: CSS_AT_RULE@495..511 + 0: AT@495..498 "@" [Newline("\n"), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@498..511 + 0: CONTAINER_KW@498..508 "container" [] [Whitespace(" ")] + 1: (empty) + 2: (empty) + 3: CSS_RULE_BLOCK@508..511 + 0: L_CURLY@508..510 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@510..510 + 2: R_CURLY@510..511 "}" [] [] + 14: CSS_AT_RULE@511..529 + 0: AT@511..513 "@" [Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@513..529 + 0: CONTAINER_KW@513..523 "container" [] [Whitespace(" ")] + 1: (empty) + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@523..526 + 0: L_PAREN@523..524 "(" [] [] + 1: (empty) + 2: R_PAREN@524..526 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@526..529 + 0: L_CURLY@526..528 "{" [] [Whitespace(" ")] + 1: CSS_RULE_LIST@528..528 + 2: R_CURLY@528..529 "}" [] [] + 2: EOF@529..530 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +at_rule_container_error.css:1:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected an identifier but instead found 'inherit' + + > 1 │ @container inherit (width <= 500px) { } + │ ^^^^^^^ + 2 │ @container initial (width <= 500px) { } + 3 │ @container unset (width <= 500px) { } + + i 'inherit' is a CSS-wide keyword that cannot be used here + +at_rule_container_error.css:2:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected an identifier but instead found 'initial' + + 1 │ @container inherit (width <= 500px) { } + > 2 │ @container initial (width <= 500px) { } + │ ^^^^^^^ + 3 │ @container unset (width <= 500px) { } + 4 │ @container revert (width <= 500px) { } + + i 'initial' is a CSS-wide keyword that cannot be used here + +at_rule_container_error.css:3:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected an identifier but instead found 'unset' + + 1 │ @container inherit (width <= 500px) { } + 2 │ @container initial (width <= 500px) { } + > 3 │ @container unset (width <= 500px) { } + │ ^^^^^ + 4 │ @container revert (width <= 500px) { } + 5 │ @container revert-layer (width <= 500px) { } + + i 'unset' is a CSS-wide keyword that cannot be used here + +at_rule_container_error.css:4:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected an identifier but instead found 'revert' + + 2 │ @container initial (width <= 500px) { } + 3 │ @container unset (width <= 500px) { } + > 4 │ @container revert (width <= 500px) { } + │ ^^^^^^ + 5 │ @container revert-layer (width <= 500px) { } + 6 │ @container inherit width <= 500px) { } + + i 'revert' is a CSS-wide keyword that cannot be used here + +at_rule_container_error.css:5:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected an identifier but instead found 'revert-layer' + + 3 │ @container unset (width <= 500px) { } + 4 │ @container revert (width <= 500px) { } + > 5 │ @container revert-layer (width <= 500px) { } + │ ^^^^^^^^^^^^ + 6 │ @container inherit width <= 500px) { } + 7 │ + + i 'revert-layer' is a CSS-wide keyword that cannot be used here + +at_rule_container_error.css:6:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected an identifier but instead found 'inherit' + + 4 │ @container revert (width <= 500px) { } + 5 │ @container revert-layer (width <= 500px) { } + > 6 │ @container inherit width <= 500px) { } + │ ^^^^^^^ + 7 │ + 8 │ @container not width <= 500px) { } + + i 'inherit' is a CSS-wide keyword that cannot be used here + +at_rule_container_error.css:6:20 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 4 │ @container revert (width <= 500px) { } + 5 │ @container revert-layer (width <= 500px) { } + > 6 │ @container inherit width <= 500px) { } + │ ^^^^^^^^^^^^^^^ + 7 │ + 8 │ @container not width <= 500px) { } + + i Expected one of: + + - not + - + - and + - or + +at_rule_container_error.css:8:16 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 6 │ @container inherit width <= 500px) { } + 7 │ + > 8 │ @container not width <= 500px) { } + │ ^^^^^^^^^^^^^^^ + 9 │ + 10 │ @container not (width <= 500px { } + + i Expected one of: + + - not + - + - and + - or + +at_rule_container_error.css:10:32 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `)` but instead found `{` + + 8 │ @container not width <= 500px) { } + 9 │ + > 10 │ @container not (width <= 500px { } + │ ^ + 11 │ @container not (width <=) { } + 12 │ @container not { } + + i Remove { + +at_rule_container_error.css:12:16 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 10 │ @container not (width <= 500px { } + 11 │ @container not (width <=) { } + > 12 │ @container not { } + │ ^ + 13 │ + 14 │ @container my-layout (inline-size > 45em) { } + + i Expected one of: + + - not + - + - and + - or + +at_rule_container_error.css:16:41 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 14 │ @container my-layout (inline-size > 45em) { } + 15 │ + > 16 │ @container card (inline-size > 30em) or { } + │ ^ + 17 │ + 18 │ @container (inline-size >= 0px) } + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_error.css:18:34 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `{` but instead found `}` + + 16 │ @container card (inline-size > 30em) or { } + 17 │ + > 18 │ @container (inline-size >= 0px) } + │ ^ + 19 │ + 20 │ @container { } + + i Remove } + +at_rule_container_error.css:20:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 18 │ @container (inline-size >= 0px) } + 19 │ + > 20 │ @container { } + │ ^ + 21 │ @container () { } + 22 │ + + i Expected one of: + + - not + - + - and + - or + +at_rule_container_error.css:21:13 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 20 │ @container { } + > 21 │ @container () { } + │ ^ + 22 │ + + i Expected one of: + + - + - + - + - or + +``` diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_or_query_error.css b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_or_query_error.css new file mode 100644 index 000000000000..733284594042 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_or_query_error.css @@ -0,0 +1,35 @@ +/* or */ +/* No valid container query after `and` */ +@container (width > 300px) or { +} + +/* No valid container query after `and missing {` */ +@container (width > 300px) or +} + +/* 200px is not a valid container query start */ +@container (width > 300px) or 200px { +} + +/* The final `or` is missing its sub-query */ +@container (width > 300px) or (height > 200px) or { +} + +/* Missing parenthesis */ +@container (width > 300px) or width > 200px or (height > 200px) { +} + +/* There's an extra `or` that has no query immediately following it. */ +@container (width > 300px) or or (height > 200px) { +} + +/* Invalid query name */ +@container (width > 300px) or randomname or (height > 200px) { +} + +/* not */ +@container name not invalid { +} + +@container name not invalid +} diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_or_query_error.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_or_query_error.css.snap new file mode 100644 index 000000000000..b20b6ebc0ea4 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_or_query_error.css.snap @@ -0,0 +1,861 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```css +/* or */ +/* No valid container query after `and` */ +@container (width > 300px) or { +} + +/* No valid container query after `and missing {` */ +@container (width > 300px) or +} + +/* 200px is not a valid container query start */ +@container (width > 300px) or 200px { +} + +/* The final `or` is missing its sub-query */ +@container (width > 300px) or (height > 200px) or { +} + +/* Missing parenthesis */ +@container (width > 300px) or width > 200px or (height > 200px) { +} + +/* There's an extra `or` that has no query immediately following it. */ +@container (width > 300px) or or (height > 200px) { +} + +/* Invalid query name */ +@container (width > 300px) or randomname or (height > 200px) { +} + +/* not */ +@container name not invalid { +} + +@container name not invalid +} + +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssAtRule { + at_token: AT@0..53 "@" [Comments("/* or */"), Newline("\n"), Comments("/* No valid container ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@53..63 "container" [] [Whitespace(" ")], + name: missing (optional), + query: CssContainerOrQuery { + left: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@63..64 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@64..70 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@70..72 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@72..75 "300" [] [], + unit_token: IDENT@75..77 "px" [] [], + }, + }, + r_paren_token: R_PAREN@77..79 ")" [] [Whitespace(" ")], + }, + or_token: OR_KW@79..82 "or" [] [Whitespace(" ")], + right: missing (required), + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@82..83 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@83..85 "}" [Newline("\n")] [], + }, + }, + }, + CssAtRule { + at_token: AT@85..141 "@" [Newline("\n"), Newline("\n"), Comments("/* No valid container ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@141..151 "container" [] [Whitespace(" ")], + name: missing (optional), + query: CssContainerOrQuery { + left: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@151..152 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@152..158 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@158..160 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@160..163 "300" [] [], + unit_token: IDENT@163..165 "px" [] [], + }, + }, + r_paren_token: R_PAREN@165..167 ")" [] [Whitespace(" ")], + }, + or_token: OR_KW@167..169 "or" [] [], + right: missing (required), + }, + block: CssBogusBlock { + items: [ + CssRuleList [], + R_CURLY@169..171 "}" [Newline("\n")] [], + ], + }, + }, + }, + CssAtRule { + at_token: AT@171..223 "@" [Newline("\n"), Newline("\n"), Comments("/* 200px is not a val ..."), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@223..233 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@233..234 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@234..240 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@240..242 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@242..245 "300" [] [], + unit_token: IDENT@245..247 "px" [] [], + }, + }, + r_paren_token: R_PAREN@247..249 ")" [] [Whitespace(" ")], + }, + OR_KW@249..252 "or" [] [Whitespace(" ")], + CssBogus { + items: [ + CSS_DIMENSION_VALUE@252..255 "200" [] [], + PX_KW@255..258 "px" [] [Whitespace(" ")], + ], + }, + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@258..259 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@259..261 "}" [Newline("\n")] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@261..310 "@" [Newline("\n"), Newline("\n"), Comments("/* The final `or` is ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@310..320 "container" [] [Whitespace(" ")], + name: missing (optional), + query: CssContainerOrQuery { + left: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@320..321 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@321..327 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@327..329 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@329..332 "300" [] [], + unit_token: IDENT@332..334 "px" [] [], + }, + }, + r_paren_token: R_PAREN@334..336 ")" [] [Whitespace(" ")], + }, + or_token: OR_KW@336..339 "or" [] [Whitespace(" ")], + right: CssContainerOrQuery { + left: CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@339..340 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@340..347 "height" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@347..349 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@349..352 "200" [] [], + unit_token: IDENT@352..354 "px" [] [], + }, + }, + r_paren_token: R_PAREN@354..356 ")" [] [Whitespace(" ")], + }, + or_token: OR_KW@356..359 "or" [] [Whitespace(" ")], + right: missing (required), + }, + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@359..360 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@360..362 "}" [Newline("\n")] [], + }, + }, + }, + CssAtRule { + at_token: AT@362..392 "@" [Newline("\n"), Newline("\n"), Comments("/* Missing parenthesi ..."), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@392..402 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@402..403 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@403..409 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@409..411 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@411..414 "300" [] [], + unit_token: IDENT@414..416 "px" [] [], + }, + }, + r_paren_token: R_PAREN@416..418 ")" [] [Whitespace(" ")], + }, + OR_KW@418..421 "or" [] [Whitespace(" ")], + CssBogus { + items: [ + CssBogus { + items: [ + IDENT@421..427 "width" [] [Whitespace(" ")], + R_ANGLE@427..429 ">" [] [Whitespace(" ")], + CSS_DIMENSION_VALUE@429..432 "200" [] [], + PX_KW@432..435 "px" [] [Whitespace(" ")], + ], + }, + OR_KW@435..438 "or" [] [Whitespace(" ")], + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@438..439 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@439..446 "height" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@446..448 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@448..451 "200" [] [], + unit_token: IDENT@451..453 "px" [] [], + }, + }, + r_paren_token: R_PAREN@453..455 ")" [] [Whitespace(" ")], + }, + ], + }, + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@455..456 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@456..458 "}" [Newline("\n")] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@458..533 "@" [Newline("\n"), Newline("\n"), Comments("/* There's an extra ` ..."), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@533..543 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@543..544 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@544..550 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@550..552 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@552..555 "300" [] [], + unit_token: IDENT@555..557 "px" [] [], + }, + }, + r_paren_token: R_PAREN@557..559 ")" [] [Whitespace(" ")], + }, + OR_KW@559..562 "or" [] [Whitespace(" ")], + CssBogus { + items: [ + CssBogus { + items: [], + }, + OR_KW@562..565 "or" [] [Whitespace(" ")], + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@565..566 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@566..573 "height" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@573..575 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@575..578 "200" [] [], + unit_token: IDENT@578..580 "px" [] [], + }, + }, + r_paren_token: R_PAREN@580..582 ")" [] [Whitespace(" ")], + }, + ], + }, + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@582..583 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@583..585 "}" [Newline("\n")] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@585..613 "@" [Newline("\n"), Newline("\n"), Comments("/* Invalid query name */"), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@613..623 "container" [] [Whitespace(" ")], + CssBogus { + items: [ + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@623..624 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@624..630 "width" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@630..632 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@632..635 "300" [] [], + unit_token: IDENT@635..637 "px" [] [], + }, + }, + r_paren_token: R_PAREN@637..639 ")" [] [Whitespace(" ")], + }, + OR_KW@639..642 "or" [] [Whitespace(" ")], + CssBogus { + items: [ + CssBogus { + items: [ + IDENT@642..653 "randomname" [] [Whitespace(" ")], + ], + }, + OR_KW@653..656 "or" [] [Whitespace(" ")], + CssContainerSizeFeatureInParens { + l_paren_token: L_PAREN@656..657 "(" [] [], + feature: CssQueryFeatureRange { + left: CssIdentifier { + value_token: IDENT@657..664 "height" [] [Whitespace(" ")], + }, + comparison: CssQueryFeatureRangeComparison { + operator: R_ANGLE@664..666 ">" [] [Whitespace(" ")], + }, + right: CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@666..669 "200" [] [], + unit_token: IDENT@669..671 "px" [] [], + }, + }, + r_paren_token: R_PAREN@671..673 ")" [] [Whitespace(" ")], + }, + ], + }, + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@673..674 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@674..676 "}" [Newline("\n")] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@676..689 "@" [Newline("\n"), Newline("\n"), Comments("/* not */"), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@689..699 "container" [] [Whitespace(" ")], + CssCustomIdentifier { + value_token: IDENT@699..704 "name" [] [Whitespace(" ")], + }, + CssBogus { + items: [ + NOT_KW@704..708 "not" [] [Whitespace(" ")], + CssBogus { + items: [ + IDENT@708..716 "invalid" [] [Whitespace(" ")], + ], + }, + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@716..717 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@717..719 "}" [Newline("\n")] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@719..722 "@" [Newline("\n"), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@722..732 "container" [] [Whitespace(" ")], + CssCustomIdentifier { + value_token: IDENT@732..737 "name" [] [Whitespace(" ")], + }, + CssBogus { + items: [ + NOT_KW@737..741 "not" [] [Whitespace(" ")], + CssBogus { + items: [ + IDENT@741..748 "invalid" [] [], + ], + }, + ], + }, + CssBogusBlock { + items: [ + CssRuleList [], + R_CURLY@748..750 "}" [Newline("\n")] [], + ], + }, + ], + }, + }, + ], + eof_token: EOF@750..751 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..751 + 0: (empty) + 1: CSS_RULE_LIST@0..750 + 0: CSS_AT_RULE@0..85 + 0: AT@0..53 "@" [Comments("/* or */"), Newline("\n"), Comments("/* No valid container ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@53..85 + 0: CONTAINER_KW@53..63 "container" [] [Whitespace(" ")] + 1: (empty) + 2: CSS_CONTAINER_OR_QUERY@63..82 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@63..79 + 0: L_PAREN@63..64 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@64..77 + 0: CSS_IDENTIFIER@64..70 + 0: IDENT@64..70 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@70..72 + 0: R_ANGLE@70..72 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@72..77 + 0: CSS_NUMBER_LITERAL@72..75 "300" [] [] + 1: IDENT@75..77 "px" [] [] + 2: R_PAREN@77..79 ")" [] [Whitespace(" ")] + 1: OR_KW@79..82 "or" [] [Whitespace(" ")] + 2: (empty) + 3: CSS_RULE_BLOCK@82..85 + 0: L_CURLY@82..83 "{" [] [] + 1: CSS_RULE_LIST@83..83 + 2: R_CURLY@83..85 "}" [Newline("\n")] [] + 1: CSS_AT_RULE@85..171 + 0: AT@85..141 "@" [Newline("\n"), Newline("\n"), Comments("/* No valid container ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@141..171 + 0: CONTAINER_KW@141..151 "container" [] [Whitespace(" ")] + 1: (empty) + 2: CSS_CONTAINER_OR_QUERY@151..169 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@151..167 + 0: L_PAREN@151..152 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@152..165 + 0: CSS_IDENTIFIER@152..158 + 0: IDENT@152..158 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@158..160 + 0: R_ANGLE@158..160 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@160..165 + 0: CSS_NUMBER_LITERAL@160..163 "300" [] [] + 1: IDENT@163..165 "px" [] [] + 2: R_PAREN@165..167 ")" [] [Whitespace(" ")] + 1: OR_KW@167..169 "or" [] [] + 2: (empty) + 3: CSS_BOGUS_BLOCK@169..171 + 0: CSS_RULE_LIST@169..169 + 1: R_CURLY@169..171 "}" [Newline("\n")] [] + 2: CSS_AT_RULE@171..261 + 0: AT@171..223 "@" [Newline("\n"), Newline("\n"), Comments("/* 200px is not a val ..."), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@223..261 + 0: CONTAINER_KW@223..233 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@233..258 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@233..249 + 0: L_PAREN@233..234 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@234..247 + 0: CSS_IDENTIFIER@234..240 + 0: IDENT@234..240 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@240..242 + 0: R_ANGLE@240..242 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@242..247 + 0: CSS_NUMBER_LITERAL@242..245 "300" [] [] + 1: IDENT@245..247 "px" [] [] + 2: R_PAREN@247..249 ")" [] [Whitespace(" ")] + 1: OR_KW@249..252 "or" [] [Whitespace(" ")] + 2: CSS_BOGUS@252..258 + 0: CSS_DIMENSION_VALUE@252..255 "200" [] [] + 1: PX_KW@255..258 "px" [] [Whitespace(" ")] + 2: CSS_RULE_BLOCK@258..261 + 0: L_CURLY@258..259 "{" [] [] + 1: CSS_RULE_LIST@259..259 + 2: R_CURLY@259..261 "}" [Newline("\n")] [] + 3: CSS_AT_RULE@261..362 + 0: AT@261..310 "@" [Newline("\n"), Newline("\n"), Comments("/* The final `or` is ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@310..362 + 0: CONTAINER_KW@310..320 "container" [] [Whitespace(" ")] + 1: (empty) + 2: CSS_CONTAINER_OR_QUERY@320..359 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@320..336 + 0: L_PAREN@320..321 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@321..334 + 0: CSS_IDENTIFIER@321..327 + 0: IDENT@321..327 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@327..329 + 0: R_ANGLE@327..329 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@329..334 + 0: CSS_NUMBER_LITERAL@329..332 "300" [] [] + 1: IDENT@332..334 "px" [] [] + 2: R_PAREN@334..336 ")" [] [Whitespace(" ")] + 1: OR_KW@336..339 "or" [] [Whitespace(" ")] + 2: CSS_CONTAINER_OR_QUERY@339..359 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@339..356 + 0: L_PAREN@339..340 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@340..354 + 0: CSS_IDENTIFIER@340..347 + 0: IDENT@340..347 "height" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@347..349 + 0: R_ANGLE@347..349 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@349..354 + 0: CSS_NUMBER_LITERAL@349..352 "200" [] [] + 1: IDENT@352..354 "px" [] [] + 2: R_PAREN@354..356 ")" [] [Whitespace(" ")] + 1: OR_KW@356..359 "or" [] [Whitespace(" ")] + 2: (empty) + 3: CSS_RULE_BLOCK@359..362 + 0: L_CURLY@359..360 "{" [] [] + 1: CSS_RULE_LIST@360..360 + 2: R_CURLY@360..362 "}" [Newline("\n")] [] + 4: CSS_AT_RULE@362..458 + 0: AT@362..392 "@" [Newline("\n"), Newline("\n"), Comments("/* Missing parenthesi ..."), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@392..458 + 0: CONTAINER_KW@392..402 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@402..455 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@402..418 + 0: L_PAREN@402..403 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@403..416 + 0: CSS_IDENTIFIER@403..409 + 0: IDENT@403..409 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@409..411 + 0: R_ANGLE@409..411 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@411..416 + 0: CSS_NUMBER_LITERAL@411..414 "300" [] [] + 1: IDENT@414..416 "px" [] [] + 2: R_PAREN@416..418 ")" [] [Whitespace(" ")] + 1: OR_KW@418..421 "or" [] [Whitespace(" ")] + 2: CSS_BOGUS@421..455 + 0: CSS_BOGUS@421..435 + 0: IDENT@421..427 "width" [] [Whitespace(" ")] + 1: R_ANGLE@427..429 ">" [] [Whitespace(" ")] + 2: CSS_DIMENSION_VALUE@429..432 "200" [] [] + 3: PX_KW@432..435 "px" [] [Whitespace(" ")] + 1: OR_KW@435..438 "or" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@438..455 + 0: L_PAREN@438..439 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@439..453 + 0: CSS_IDENTIFIER@439..446 + 0: IDENT@439..446 "height" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@446..448 + 0: R_ANGLE@446..448 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@448..453 + 0: CSS_NUMBER_LITERAL@448..451 "200" [] [] + 1: IDENT@451..453 "px" [] [] + 2: R_PAREN@453..455 ")" [] [Whitespace(" ")] + 2: CSS_RULE_BLOCK@455..458 + 0: L_CURLY@455..456 "{" [] [] + 1: CSS_RULE_LIST@456..456 + 2: R_CURLY@456..458 "}" [Newline("\n")] [] + 5: CSS_AT_RULE@458..585 + 0: AT@458..533 "@" [Newline("\n"), Newline("\n"), Comments("/* There's an extra ` ..."), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@533..585 + 0: CONTAINER_KW@533..543 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@543..582 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@543..559 + 0: L_PAREN@543..544 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@544..557 + 0: CSS_IDENTIFIER@544..550 + 0: IDENT@544..550 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@550..552 + 0: R_ANGLE@550..552 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@552..557 + 0: CSS_NUMBER_LITERAL@552..555 "300" [] [] + 1: IDENT@555..557 "px" [] [] + 2: R_PAREN@557..559 ")" [] [Whitespace(" ")] + 1: OR_KW@559..562 "or" [] [Whitespace(" ")] + 2: CSS_BOGUS@562..582 + 0: CSS_BOGUS@562..562 + 1: OR_KW@562..565 "or" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@565..582 + 0: L_PAREN@565..566 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@566..580 + 0: CSS_IDENTIFIER@566..573 + 0: IDENT@566..573 "height" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@573..575 + 0: R_ANGLE@573..575 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@575..580 + 0: CSS_NUMBER_LITERAL@575..578 "200" [] [] + 1: IDENT@578..580 "px" [] [] + 2: R_PAREN@580..582 ")" [] [Whitespace(" ")] + 2: CSS_RULE_BLOCK@582..585 + 0: L_CURLY@582..583 "{" [] [] + 1: CSS_RULE_LIST@583..583 + 2: R_CURLY@583..585 "}" [Newline("\n")] [] + 6: CSS_AT_RULE@585..676 + 0: AT@585..613 "@" [Newline("\n"), Newline("\n"), Comments("/* Invalid query name */"), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@613..676 + 0: CONTAINER_KW@613..623 "container" [] [Whitespace(" ")] + 1: CSS_BOGUS@623..673 + 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@623..639 + 0: L_PAREN@623..624 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@624..637 + 0: CSS_IDENTIFIER@624..630 + 0: IDENT@624..630 "width" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@630..632 + 0: R_ANGLE@630..632 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@632..637 + 0: CSS_NUMBER_LITERAL@632..635 "300" [] [] + 1: IDENT@635..637 "px" [] [] + 2: R_PAREN@637..639 ")" [] [Whitespace(" ")] + 1: OR_KW@639..642 "or" [] [Whitespace(" ")] + 2: CSS_BOGUS@642..673 + 0: CSS_BOGUS@642..653 + 0: IDENT@642..653 "randomname" [] [Whitespace(" ")] + 1: OR_KW@653..656 "or" [] [Whitespace(" ")] + 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@656..673 + 0: L_PAREN@656..657 "(" [] [] + 1: CSS_QUERY_FEATURE_RANGE@657..671 + 0: CSS_IDENTIFIER@657..664 + 0: IDENT@657..664 "height" [] [Whitespace(" ")] + 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@664..666 + 0: R_ANGLE@664..666 ">" [] [Whitespace(" ")] + 2: CSS_REGULAR_DIMENSION@666..671 + 0: CSS_NUMBER_LITERAL@666..669 "200" [] [] + 1: IDENT@669..671 "px" [] [] + 2: R_PAREN@671..673 ")" [] [Whitespace(" ")] + 2: CSS_RULE_BLOCK@673..676 + 0: L_CURLY@673..674 "{" [] [] + 1: CSS_RULE_LIST@674..674 + 2: R_CURLY@674..676 "}" [Newline("\n")] [] + 7: CSS_AT_RULE@676..719 + 0: AT@676..689 "@" [Newline("\n"), Newline("\n"), Comments("/* not */"), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@689..719 + 0: CONTAINER_KW@689..699 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@699..704 + 0: IDENT@699..704 "name" [] [Whitespace(" ")] + 2: CSS_BOGUS@704..716 + 0: NOT_KW@704..708 "not" [] [Whitespace(" ")] + 1: CSS_BOGUS@708..716 + 0: IDENT@708..716 "invalid" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@716..719 + 0: L_CURLY@716..717 "{" [] [] + 1: CSS_RULE_LIST@717..717 + 2: R_CURLY@717..719 "}" [Newline("\n")] [] + 8: CSS_AT_RULE@719..750 + 0: AT@719..722 "@" [Newline("\n"), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@722..750 + 0: CONTAINER_KW@722..732 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@732..737 + 0: IDENT@732..737 "name" [] [Whitespace(" ")] + 2: CSS_BOGUS@737..748 + 0: NOT_KW@737..741 "not" [] [Whitespace(" ")] + 1: CSS_BOGUS@741..748 + 0: IDENT@741..748 "invalid" [] [] + 3: CSS_BOGUS_BLOCK@748..750 + 0: CSS_RULE_LIST@748..748 + 1: R_CURLY@748..750 "}" [Newline("\n")] [] + 2: EOF@750..751 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +at_rule_container_or_query_error.css:3:31 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 1 │ /* or */ + 2 │ /* No valid container query after `and` */ + > 3 │ @container (width > 300px) or { + │ ^ + 4 │ } + 5 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_or_query_error.css:8:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 6 │ /* No valid container query after `and missing {` */ + 7 │ @container (width > 300px) or + > 8 │ } + │ ^ + 9 │ + 10 │ /* 200px is not a valid container query start */ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_or_query_error.css:11:31 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 10 │ /* 200px is not a valid container query start */ + > 11 │ @container (width > 300px) or 200px { + │ ^^^^^ + 12 │ } + 13 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_or_query_error.css:15:51 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 14 │ /* The final `or` is missing its sub-query */ + > 15 │ @container (width > 300px) or (height > 200px) or { + │ ^ + 16 │ } + 17 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_or_query_error.css:19:31 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 18 │ /* Missing parenthesis */ + > 19 │ @container (width > 300px) or width > 200px or (height > 200px) { + │ ^^^^^^^^^^^^^ + 20 │ } + 21 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_or_query_error.css:23:31 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 22 │ /* There's an extra `or` that has no query immediately following it. */ + > 23 │ @container (width > 300px) or or (height > 200px) { + │ ^^ + 24 │ } + 25 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_or_query_error.css:27:31 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 26 │ /* Invalid query name */ + > 27 │ @container (width > 300px) or randomname or (height > 200px) { + │ ^^^^^^^^^^ + 28 │ } + 29 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_or_query_error.css:31:21 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 30 │ /* not */ + > 31 │ @container name not invalid { + │ ^^^^^^^ + 32 │ } + 33 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_or_query_error.css:34:21 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 32 │ } + 33 │ + > 34 │ @container name not invalid + │ ^^^^^^^ + 35 │ } + 36 │ + + i Expected one of: + + - ( ) + - ( ) + - style( ) + +at_rule_container_or_query_error.css:35:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `{` but instead found `}` + + 34 │ @container name not invalid + > 35 │ } + │ ^ + 36 │ + + i Remove } + +``` diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_not_query.css b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_not_query.css new file mode 100644 index 000000000000..c23998ef9dff --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_not_query.css @@ -0,0 +1,41 @@ +/* + ERROR CASE 1: Missing parentheses after "not" + - "not" must be immediately followed by "(" +*/ +@container name style(not) { +} + +/* + ERROR CASE 2: Empty parentheses + - "not()" is missing a valid query or declaration inside +*/ +@container name style(not()) { +} + +/* + ERROR CASE 3: Extra closing parenthesis + - The "(...)) )" leads to unbalanced parentheses +*/ +@container name style(not((color: red)) ) ) { +} + +/* + ERROR CASE 4: Incomplete logical operator + - "and" is started but no query follows +*/ +@container name style(not((color: red) and )) { +} + +/* + ERROR CASE 5: Unexpected token + - "???" doesn't fit a valid property or query expression +*/ +@container name style(not((color: red) ??? (background: blue))) { +} + +/* + ERROR CASE 6: Missing colon in declaration + - "not((color red))" should be "not((color: red))" +*/ +@container name style(not((color red))) { +} diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_not_query.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_not_query.css.snap new file mode 100644 index 000000000000..5f42c8cebaf0 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_not_query.css.snap @@ -0,0 +1,669 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```css +/* + ERROR CASE 1: Missing parentheses after "not" + - "not" must be immediately followed by "(" +*/ +@container name style(not) { +} + +/* + ERROR CASE 2: Empty parentheses + - "not()" is missing a valid query or declaration inside +*/ +@container name style(not()) { +} + +/* + ERROR CASE 3: Extra closing parenthesis + - The "(...)) )" leads to unbalanced parentheses +*/ +@container name style(not((color: red)) ) ) { +} + +/* + ERROR CASE 4: Incomplete logical operator + - "and" is started but no query follows +*/ +@container name style(not((color: red) and )) { +} + +/* + ERROR CASE 5: Unexpected token + - "???" doesn't fit a valid property or query expression +*/ +@container name style(not((color: red) ??? (background: blue))) { +} + +/* + ERROR CASE 6: Missing colon in declaration + - "not((color red))" should be "not((color: red))" +*/ +@container name style(not((color red))) { +} + +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssAtRule { + at_token: AT@0..101 "@" [Comments("/*\n ERROR CASE 1: Mi ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@101..111 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@111..116 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@116..121 "style" [] [], + l_paren_token: L_PAREN@121..122 "(" [] [], + query: CssContainerStyleNotQuery { + not_token: NOT_KW@122..125 "not" [] [], + query: missing (required), + }, + r_paren_token: R_PAREN@125..127 ")" [] [Whitespace(" ")], + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@127..128 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@128..130 "}" [Newline("\n")] [], + }, + }, + }, + CssAtRule { + at_token: AT@130..232 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 2: Em ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@232..242 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@242..247 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@247..252 "style" [] [], + l_paren_token: L_PAREN@252..253 "(" [] [], + query: CssContainerStyleNotQuery { + not_token: NOT_KW@253..256 "not" [] [], + query: CssContainerStyleInParens { + l_paren_token: L_PAREN@256..257 "(" [] [], + query: missing (required), + r_paren_token: R_PAREN@257..258 ")" [] [], + }, + }, + r_paren_token: R_PAREN@258..260 ")" [] [Whitespace(" ")], + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@260..261 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@261..263 "}" [Newline("\n")] [], + }, + }, + }, + CssAtRule { + at_token: AT@263..365 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 3: Ex ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@365..375 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@375..380 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@380..385 "style" [] [], + l_paren_token: L_PAREN@385..386 "(" [] [], + query: CssContainerStyleNotQuery { + not_token: NOT_KW@386..389 "not" [] [], + query: CssContainerStyleInParens { + l_paren_token: L_PAREN@389..390 "(" [] [], + query: CssContainerStyleInParens { + l_paren_token: L_PAREN@390..391 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@391..396 "color" [] [], + }, + colon_token: COLON@396..398 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@398..401 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@401..402 ")" [] [], + }, + r_paren_token: R_PAREN@402..404 ")" [] [Whitespace(" ")], + }, + }, + r_paren_token: R_PAREN@404..406 ")" [] [Whitespace(" ")], + }, + block: CssBogusBlock { + items: [], + }, + }, + }, + CssBogusRule { + items: [ + R_PAREN@406..408 ")" [] [Whitespace(" ")], + L_CURLY@408..409 "{" [] [], + R_CURLY@409..411 "}" [Newline("\n")] [], + ], + }, + CssAtRule { + at_token: AT@411..506 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 4: In ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@506..516 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@516..521 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@521..526 "style" [] [], + l_paren_token: L_PAREN@526..527 "(" [] [], + query: CssContainerStyleNotQuery { + not_token: NOT_KW@527..530 "not" [] [], + query: CssContainerStyleInParens { + l_paren_token: L_PAREN@530..531 "(" [] [], + query: CssContainerStyleAndQuery { + left: CssContainerStyleInParens { + l_paren_token: L_PAREN@531..532 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@532..537 "color" [] [], + }, + colon_token: COLON@537..539 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@539..542 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@542..544 ")" [] [Whitespace(" ")], + }, + and_token: AND_KW@544..548 "and" [] [Whitespace(" ")], + right: missing (required), + }, + r_paren_token: R_PAREN@548..549 ")" [] [], + }, + }, + r_paren_token: R_PAREN@549..551 ")" [] [Whitespace(" ")], + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@551..552 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@552..554 "}" [Newline("\n")] [], + }, + }, + }, + CssAtRule { + at_token: AT@554..655 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 5: Un ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@655..665 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@665..670 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@670..675 "style" [] [], + l_paren_token: L_PAREN@675..676 "(" [] [], + query: CssContainerStyleNotQuery { + not_token: NOT_KW@676..679 "not" [] [], + query: CssContainerStyleInParens { + l_paren_token: L_PAREN@679..680 "(" [] [], + query: CssContainerStyleInParens { + l_paren_token: L_PAREN@680..681 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@681..686 "color" [] [], + }, + colon_token: COLON@686..688 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@688..691 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@691..693 ")" [] [Whitespace(" ")], + }, + r_paren_token: missing (required), + }, + }, + r_paren_token: missing (required), + }, + block: CssBogusBlock { + items: [], + }, + }, + }, + CssBogusRule { + items: [ + ERROR_TOKEN@693..694 "?" [] [], + ERROR_TOKEN@694..695 "?" [] [], + ERROR_TOKEN@695..697 "?" [] [Whitespace(" ")], + L_PAREN@697..698 "(" [] [], + ], + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: CssTypeSelector { + namespace: missing (optional), + ident: CssIdentifier { + value_token: IDENT@698..708 "background" [] [], + }, + }, + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@708..710 ":" [] [Whitespace(" ")], + class: CssPseudoClassIdentifier { + name: CssIdentifier { + value_token: IDENT@710..714 "blue" [] [], + }, + }, + }, + ], + }, + missing separator, + CssBogusSelector { + items: [ + R_PAREN@714..715 ")" [] [], + R_PAREN@715..716 ")" [] [], + R_PAREN@716..718 ")" [] [Whitespace(" ")], + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@718..719 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@719..721 "}" [Newline("\n")] [], + }, + }, + CssAtRule { + at_token: AT@721..828 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 6: Mi ..."), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@828..838 "container" [] [Whitespace(" ")], + CssCustomIdentifier { + value_token: IDENT@838..843 "name" [] [Whitespace(" ")], + }, + CssBogus { + items: [ + STYLE_KW@843..848 "style" [] [], + L_PAREN@848..849 "(" [] [], + CssBogus { + items: [ + NOT_KW@849..852 "not" [] [], + CssBogus { + items: [ + L_PAREN@852..853 "(" [] [], + CssBogus { + items: [ + L_PAREN@853..854 "(" [] [], + CssBogus { + items: [ + IDENT@854..860 "color" [] [Whitespace(" ")], + IDENT@860..863 "red" [] [], + ], + }, + R_PAREN@863..864 ")" [] [], + ], + }, + R_PAREN@864..865 ")" [] [], + ], + }, + ], + }, + R_PAREN@865..867 ")" [] [Whitespace(" ")], + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@867..868 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@868..870 "}" [Newline("\n")] [], + }, + ], + }, + }, + ], + eof_token: EOF@870..871 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..871 + 0: (empty) + 1: CSS_RULE_LIST@0..870 + 0: CSS_AT_RULE@0..130 + 0: AT@0..101 "@" [Comments("/*\n ERROR CASE 1: Mi ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@101..130 + 0: CONTAINER_KW@101..111 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@111..116 + 0: IDENT@111..116 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@116..127 + 0: STYLE_KW@116..121 "style" [] [] + 1: L_PAREN@121..122 "(" [] [] + 2: CSS_CONTAINER_STYLE_NOT_QUERY@122..125 + 0: NOT_KW@122..125 "not" [] [] + 1: (empty) + 3: R_PAREN@125..127 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@127..130 + 0: L_CURLY@127..128 "{" [] [] + 1: CSS_RULE_LIST@128..128 + 2: R_CURLY@128..130 "}" [Newline("\n")] [] + 1: CSS_AT_RULE@130..263 + 0: AT@130..232 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 2: Em ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@232..263 + 0: CONTAINER_KW@232..242 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@242..247 + 0: IDENT@242..247 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@247..260 + 0: STYLE_KW@247..252 "style" [] [] + 1: L_PAREN@252..253 "(" [] [] + 2: CSS_CONTAINER_STYLE_NOT_QUERY@253..258 + 0: NOT_KW@253..256 "not" [] [] + 1: CSS_CONTAINER_STYLE_IN_PARENS@256..258 + 0: L_PAREN@256..257 "(" [] [] + 1: (empty) + 2: R_PAREN@257..258 ")" [] [] + 3: R_PAREN@258..260 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@260..263 + 0: L_CURLY@260..261 "{" [] [] + 1: CSS_RULE_LIST@261..261 + 2: R_CURLY@261..263 "}" [Newline("\n")] [] + 2: CSS_AT_RULE@263..406 + 0: AT@263..365 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 3: Ex ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@365..406 + 0: CONTAINER_KW@365..375 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@375..380 + 0: IDENT@375..380 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@380..406 + 0: STYLE_KW@380..385 "style" [] [] + 1: L_PAREN@385..386 "(" [] [] + 2: CSS_CONTAINER_STYLE_NOT_QUERY@386..404 + 0: NOT_KW@386..389 "not" [] [] + 1: CSS_CONTAINER_STYLE_IN_PARENS@389..404 + 0: L_PAREN@389..390 "(" [] [] + 1: CSS_CONTAINER_STYLE_IN_PARENS@390..402 + 0: L_PAREN@390..391 "(" [] [] + 1: CSS_DECLARATION@391..401 + 0: CSS_GENERIC_PROPERTY@391..401 + 0: CSS_IDENTIFIER@391..396 + 0: IDENT@391..396 "color" [] [] + 1: COLON@396..398 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@398..401 + 0: CSS_IDENTIFIER@398..401 + 0: IDENT@398..401 "red" [] [] + 1: (empty) + 2: R_PAREN@401..402 ")" [] [] + 2: R_PAREN@402..404 ")" [] [Whitespace(" ")] + 3: R_PAREN@404..406 ")" [] [Whitespace(" ")] + 3: CSS_BOGUS_BLOCK@406..406 + 3: CSS_BOGUS_RULE@406..411 + 0: R_PAREN@406..408 ")" [] [Whitespace(" ")] + 1: L_CURLY@408..409 "{" [] [] + 2: R_CURLY@409..411 "}" [Newline("\n")] [] + 4: CSS_AT_RULE@411..554 + 0: AT@411..506 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 4: In ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@506..554 + 0: CONTAINER_KW@506..516 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@516..521 + 0: IDENT@516..521 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@521..551 + 0: STYLE_KW@521..526 "style" [] [] + 1: L_PAREN@526..527 "(" [] [] + 2: CSS_CONTAINER_STYLE_NOT_QUERY@527..549 + 0: NOT_KW@527..530 "not" [] [] + 1: CSS_CONTAINER_STYLE_IN_PARENS@530..549 + 0: L_PAREN@530..531 "(" [] [] + 1: CSS_CONTAINER_STYLE_AND_QUERY@531..548 + 0: CSS_CONTAINER_STYLE_IN_PARENS@531..544 + 0: L_PAREN@531..532 "(" [] [] + 1: CSS_DECLARATION@532..542 + 0: CSS_GENERIC_PROPERTY@532..542 + 0: CSS_IDENTIFIER@532..537 + 0: IDENT@532..537 "color" [] [] + 1: COLON@537..539 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@539..542 + 0: CSS_IDENTIFIER@539..542 + 0: IDENT@539..542 "red" [] [] + 1: (empty) + 2: R_PAREN@542..544 ")" [] [Whitespace(" ")] + 1: AND_KW@544..548 "and" [] [Whitespace(" ")] + 2: (empty) + 2: R_PAREN@548..549 ")" [] [] + 3: R_PAREN@549..551 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@551..554 + 0: L_CURLY@551..552 "{" [] [] + 1: CSS_RULE_LIST@552..552 + 2: R_CURLY@552..554 "}" [Newline("\n")] [] + 5: CSS_AT_RULE@554..693 + 0: AT@554..655 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 5: Un ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@655..693 + 0: CONTAINER_KW@655..665 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@665..670 + 0: IDENT@665..670 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@670..693 + 0: STYLE_KW@670..675 "style" [] [] + 1: L_PAREN@675..676 "(" [] [] + 2: CSS_CONTAINER_STYLE_NOT_QUERY@676..693 + 0: NOT_KW@676..679 "not" [] [] + 1: CSS_CONTAINER_STYLE_IN_PARENS@679..693 + 0: L_PAREN@679..680 "(" [] [] + 1: CSS_CONTAINER_STYLE_IN_PARENS@680..693 + 0: L_PAREN@680..681 "(" [] [] + 1: CSS_DECLARATION@681..691 + 0: CSS_GENERIC_PROPERTY@681..691 + 0: CSS_IDENTIFIER@681..686 + 0: IDENT@681..686 "color" [] [] + 1: COLON@686..688 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@688..691 + 0: CSS_IDENTIFIER@688..691 + 0: IDENT@688..691 "red" [] [] + 1: (empty) + 2: R_PAREN@691..693 ")" [] [Whitespace(" ")] + 2: (empty) + 3: (empty) + 3: CSS_BOGUS_BLOCK@693..693 + 6: CSS_BOGUS_RULE@693..698 + 0: ERROR_TOKEN@693..694 "?" [] [] + 1: ERROR_TOKEN@694..695 "?" [] [] + 2: ERROR_TOKEN@695..697 "?" [] [Whitespace(" ")] + 3: L_PAREN@697..698 "(" [] [] + 7: CSS_QUALIFIED_RULE@698..721 + 0: CSS_SELECTOR_LIST@698..718 + 0: CSS_COMPOUND_SELECTOR@698..714 + 0: CSS_NESTED_SELECTOR_LIST@698..698 + 1: CSS_TYPE_SELECTOR@698..708 + 0: (empty) + 1: CSS_IDENTIFIER@698..708 + 0: IDENT@698..708 "background" [] [] + 2: CSS_SUB_SELECTOR_LIST@708..714 + 0: CSS_PSEUDO_CLASS_SELECTOR@708..714 + 0: COLON@708..710 ":" [] [Whitespace(" ")] + 1: CSS_PSEUDO_CLASS_IDENTIFIER@710..714 + 0: CSS_IDENTIFIER@710..714 + 0: IDENT@710..714 "blue" [] [] + 1: (empty) + 2: CSS_BOGUS_SELECTOR@714..718 + 0: R_PAREN@714..715 ")" [] [] + 1: R_PAREN@715..716 ")" [] [] + 2: R_PAREN@716..718 ")" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@718..721 + 0: L_CURLY@718..719 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@719..719 + 2: R_CURLY@719..721 "}" [Newline("\n")] [] + 8: CSS_AT_RULE@721..870 + 0: AT@721..828 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 6: Mi ..."), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@828..870 + 0: CONTAINER_KW@828..838 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@838..843 + 0: IDENT@838..843 "name" [] [Whitespace(" ")] + 2: CSS_BOGUS@843..867 + 0: STYLE_KW@843..848 "style" [] [] + 1: L_PAREN@848..849 "(" [] [] + 2: CSS_BOGUS@849..865 + 0: NOT_KW@849..852 "not" [] [] + 1: CSS_BOGUS@852..865 + 0: L_PAREN@852..853 "(" [] [] + 1: CSS_BOGUS@853..864 + 0: L_PAREN@853..854 "(" [] [] + 1: CSS_BOGUS@854..863 + 0: IDENT@854..860 "color" [] [Whitespace(" ")] + 1: IDENT@860..863 "red" [] [] + 2: R_PAREN@863..864 ")" [] [] + 2: R_PAREN@864..865 ")" [] [] + 3: R_PAREN@865..867 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@867..870 + 0: L_CURLY@867..868 "{" [] [] + 1: CSS_RULE_LIST@868..868 + 2: R_CURLY@868..870 "}" [Newline("\n")] [] + 2: EOF@870..871 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +at_rule_container_style_not_query.css:5:26 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 3 │ - "not" must be immediately followed by "(" + 4 │ */ + > 5 │ @container name style(not) { + │ ^ + 6 │ } + 7 │ + + i Expected one of: + + - ( ) + - ( ) + +at_rule_container_style_not_query.css:12:27 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 10 │ - "not()" is missing a valid query or declaration inside + 11 │ */ + > 12 │ @container name style(not()) { + │ ^ + 13 │ } + 14 │ + + i Expected one of: + + - not + - + - and + - or + - + +at_rule_container_style_not_query.css:19:43 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `{` but instead found `)` + + 17 │ - The "(...)) )" leads to unbalanced parentheses + 18 │ */ + > 19 │ @container name style(not((color: red)) ) ) { + │ ^ + 20 │ } + 21 │ + + i Remove ) + +at_rule_container_style_not_query.css:26:44 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 24 │ - "and" is started but no query follows + 25 │ */ + > 26 │ @container name style(not((color: red) and )) { + │ ^ + 27 │ } + 28 │ + + i Expected one of: + + - ( ) + - ( ) + +at_rule_container_style_not_query.css:33:40 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × unexpected character `?` + + 31 │ - "???" doesn't fit a valid property or query expression + 32 │ */ + > 33 │ @container name style(not((color: red) ??? (background: blue))) { + │ ^ + 34 │ } + 35 │ + +at_rule_container_style_not_query.css:33:41 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × unexpected character `?` + + 31 │ - "???" doesn't fit a valid property or query expression + 32 │ */ + > 33 │ @container name style(not((color: red) ??? (background: blue))) { + │ ^ + 34 │ } + 35 │ + +at_rule_container_style_not_query.css:33:42 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × unexpected character `?` + + 31 │ - "???" doesn't fit a valid property or query expression + 32 │ */ + > 33 │ @container name style(not((color: red) ??? (background: blue))) { + │ ^ + 34 │ } + 35 │ + +at_rule_container_style_not_query.css:33:61 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `,` but instead found `)` + + 31 │ - "???" doesn't fit a valid property or query expression + 32 │ */ + > 33 │ @container name style(not((color: red) ??? (background: blue))) { + │ ^ + 34 │ } + 35 │ + + i Remove ) + +at_rule_container_style_not_query.css:40:28 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 38 │ - "not((color red))" should be "not((color: red))" + 39 │ */ + > 40 │ @container name style(not((color red))) { + │ ^^^^^^^^^ + 41 │ } + 42 │ + + i Expected one of: + + - not + - + - and + - or + - + +``` diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_query_error.css b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_query_error.css new file mode 100644 index 000000000000..05bfa6d6b71b --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_query_error.css @@ -0,0 +1,69 @@ +/* + ERROR CASE 1: Missing closing parenthesis + - Missing ")" after (--b: blue) +*/ +@container name style((--b: red) or (--b: blue { +} + +/* + ERROR CASE 2: Extra closing parenthesis + - The double ")) )" leads to unbalanced parentheses +*/ +@container name style((--b: red) or ((--b: red) and (--b: red)) ) ) { +} + +/* + ERROR CASE 3: Incomplete logical operator + - There's an "or" but nothing follows +*/ +@container name style((--b: red) or ) { +} + +/* + ERROR CASE 4: Empty parentheses + - "()": no valid declaration inside +*/ +@container name style( () ) { +} + +/* + ERROR CASE 5: Missing parentheses after "style" + - "style" must be followed by "(" +*/ +@container name style --b: red { +} + +/* + ERROR CASE 6: Invalid property value + - "#red" isn't a recognized color token in standard CSS +*/ +@container name style((color: #red)) { +} + +/* + ERROR CASE 7: Unexpected tokens + - "???" doesn't fit valid CSS property or logical operator syntax +*/ +@container name style((--b: red) ??? (--b: blue)) { +} + +/* + ERROR CASE 8: Missing colon in a declaration + - "(--b red)" should be "(--b: red)" +*/ +@container name style((--b red)) { +} + +/* + ERROR CASE 9: Incorrect nesting of logical operators + - "and or" in direct sequence is invalid +*/ +@container name style((--b: red) and or (--c: red)) { +} + +/* + ERROR CASE 10: Extraneous characters after closing parenthesis + - "??" is unexpected after "((--b: red))" +*/ +@container name style((--b: red))?? { +} diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_query_error.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_query_error.css.snap new file mode 100644 index 000000000000..00c2d8de7c65 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container/at_rule_container_style_query_error.css.snap @@ -0,0 +1,1281 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- +## Input + +```css +/* + ERROR CASE 1: Missing closing parenthesis + - Missing ")" after (--b: blue) +*/ +@container name style((--b: red) or (--b: blue { +} + +/* + ERROR CASE 2: Extra closing parenthesis + - The double ")) )" leads to unbalanced parentheses +*/ +@container name style((--b: red) or ((--b: red) and (--b: red)) ) ) { +} + +/* + ERROR CASE 3: Incomplete logical operator + - There's an "or" but nothing follows +*/ +@container name style((--b: red) or ) { +} + +/* + ERROR CASE 4: Empty parentheses + - "()": no valid declaration inside +*/ +@container name style( () ) { +} + +/* + ERROR CASE 5: Missing parentheses after "style" + - "style" must be followed by "(" +*/ +@container name style --b: red { +} + +/* + ERROR CASE 6: Invalid property value + - "#red" isn't a recognized color token in standard CSS +*/ +@container name style((color: #red)) { +} + +/* + ERROR CASE 7: Unexpected tokens + - "???" doesn't fit valid CSS property or logical operator syntax +*/ +@container name style((--b: red) ??? (--b: blue)) { +} + +/* + ERROR CASE 8: Missing colon in a declaration + - "(--b red)" should be "(--b: red)" +*/ +@container name style((--b red)) { +} + +/* + ERROR CASE 9: Incorrect nesting of logical operators + - "and or" in direct sequence is invalid +*/ +@container name style((--b: red) and or (--c: red)) { +} + +/* + ERROR CASE 10: Extraneous characters after closing parenthesis + - "??" is unexpected after "((--b: red))" +*/ +@container name style((--b: red))?? { +} + +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssAtRule { + at_token: AT@0..85 "@" [Comments("/*\n ERROR CASE 1: Mi ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@85..95 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@95..100 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@100..105 "style" [] [], + l_paren_token: L_PAREN@105..106 "(" [] [], + query: CssContainerStyleOrQuery { + left: CssContainerStyleInParens { + l_paren_token: L_PAREN@106..107 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssDashedIdentifier { + value_token: IDENT@107..110 "--b" [] [], + }, + colon_token: COLON@110..112 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@112..115 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@115..117 ")" [] [Whitespace(" ")], + }, + or_token: OR_KW@117..120 "or" [] [Whitespace(" ")], + right: CssContainerStyleInParens { + l_paren_token: L_PAREN@120..121 "(" [] [], + query: CssDeclaration { + property: CssBogusProperty { + items: [ + CssDashedIdentifier { + value_token: IDENT@121..124 "--b" [] [], + }, + COLON@124..126 ":" [] [Whitespace(" ")], + CssBogus { + items: [ + CssIdentifier { + value_token: IDENT@126..131 "blue" [] [Whitespace(" ")], + }, + CssBogusPropertyValue { + items: [ + L_CURLY@131..132 "{" [] [], + ], + }, + ], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: missing (required), + }, + }, + r_paren_token: missing (required), + }, + block: CssBogusBlock { + items: [ + CssRuleList [], + R_CURLY@132..134 "}" [Newline("\n")] [], + ], + }, + }, + }, + CssAtRule { + at_token: AT@134..239 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 2: Ex ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@239..249 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@249..254 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@254..259 "style" [] [], + l_paren_token: L_PAREN@259..260 "(" [] [], + query: CssContainerStyleOrQuery { + left: CssContainerStyleInParens { + l_paren_token: L_PAREN@260..261 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssDashedIdentifier { + value_token: IDENT@261..264 "--b" [] [], + }, + colon_token: COLON@264..266 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@266..269 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@269..271 ")" [] [Whitespace(" ")], + }, + or_token: OR_KW@271..274 "or" [] [Whitespace(" ")], + right: CssContainerStyleInParens { + l_paren_token: L_PAREN@274..275 "(" [] [], + query: CssContainerStyleAndQuery { + left: CssContainerStyleInParens { + l_paren_token: L_PAREN@275..276 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssDashedIdentifier { + value_token: IDENT@276..279 "--b" [] [], + }, + colon_token: COLON@279..281 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@281..284 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@284..286 ")" [] [Whitespace(" ")], + }, + and_token: AND_KW@286..290 "and" [] [Whitespace(" ")], + right: CssContainerStyleInParens { + l_paren_token: L_PAREN@290..291 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssDashedIdentifier { + value_token: IDENT@291..294 "--b" [] [], + }, + colon_token: COLON@294..296 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@296..299 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@299..300 ")" [] [], + }, + }, + r_paren_token: R_PAREN@300..302 ")" [] [Whitespace(" ")], + }, + }, + r_paren_token: R_PAREN@302..304 ")" [] [Whitespace(" ")], + }, + block: CssBogusBlock { + items: [], + }, + }, + }, + CssBogusRule { + items: [ + R_PAREN@304..306 ")" [] [Whitespace(" ")], + L_CURLY@306..307 "{" [] [], + R_CURLY@307..309 "}" [Newline("\n")] [], + ], + }, + CssAtRule { + at_token: AT@309..402 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 3: In ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@402..412 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@412..417 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@417..422 "style" [] [], + l_paren_token: L_PAREN@422..423 "(" [] [], + query: CssContainerStyleOrQuery { + left: CssContainerStyleInParens { + l_paren_token: L_PAREN@423..424 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssDashedIdentifier { + value_token: IDENT@424..427 "--b" [] [], + }, + colon_token: COLON@427..429 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@429..432 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@432..434 ")" [] [Whitespace(" ")], + }, + or_token: OR_KW@434..437 "or" [] [Whitespace(" ")], + right: missing (required), + }, + r_paren_token: R_PAREN@437..439 ")" [] [Whitespace(" ")], + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@439..440 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@440..442 "}" [Newline("\n")] [], + }, + }, + }, + CssAtRule { + at_token: AT@442..523 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 4: Em ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@523..533 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@533..538 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@538..543 "style" [] [], + l_paren_token: L_PAREN@543..545 "(" [] [Whitespace(" ")], + query: CssContainerStyleInParens { + l_paren_token: L_PAREN@545..546 "(" [] [], + query: missing (required), + r_paren_token: R_PAREN@546..548 ")" [] [Whitespace(" ")], + }, + r_paren_token: R_PAREN@548..550 ")" [] [Whitespace(" ")], + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@550..551 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@551..553 "}" [Newline("\n")] [], + }, + }, + }, + CssAtRule { + at_token: AT@553..648 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 5: Mi ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@648..658 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@658..663 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@663..669 "style" [] [Whitespace(" ")], + l_paren_token: missing (required), + query: CssDeclaration { + property: CssBogusProperty { + items: [ + CssDashedIdentifier { + value_token: IDENT@669..672 "--b" [] [], + }, + COLON@672..674 ":" [] [Whitespace(" ")], + CssBogus { + items: [ + CssIdentifier { + value_token: IDENT@674..678 "red" [] [Whitespace(" ")], + }, + CssBogusPropertyValue { + items: [ + L_CURLY@678..679 "{" [] [], + ], + }, + ], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: missing (required), + }, + block: CssBogusBlock { + items: [ + CssRuleList [], + R_CURLY@679..681 "}" [Newline("\n")] [], + ], + }, + }, + }, + CssAtRule { + at_token: AT@681..787 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 6: In ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@787..797 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@797..802 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@802..807 "style" [] [], + l_paren_token: L_PAREN@807..808 "(" [] [], + query: CssContainerStyleInParens { + l_paren_token: L_PAREN@808..809 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@809..814 "color" [] [], + }, + colon_token: COLON@814..816 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssColor { + hash_token: HASH@816..817 "#" [] [], + value_token: missing (required), + }, + CssIdentifier { + value_token: IDENT@817..820 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@820..821 ")" [] [], + }, + r_paren_token: R_PAREN@821..823 ")" [] [Whitespace(" ")], + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@823..824 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@824..826 "}" [Newline("\n")] [], + }, + }, + }, + CssAtRule { + at_token: AT@826..937 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 7: Un ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@937..947 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@947..952 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@952..957 "style" [] [], + l_paren_token: L_PAREN@957..958 "(" [] [], + query: CssContainerStyleInParens { + l_paren_token: L_PAREN@958..959 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssDashedIdentifier { + value_token: IDENT@959..962 "--b" [] [], + }, + colon_token: COLON@962..964 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@964..967 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@967..969 ")" [] [Whitespace(" ")], + }, + r_paren_token: missing (required), + }, + block: CssBogusBlock { + items: [], + }, + }, + }, + CssBogusRule { + items: [ + ERROR_TOKEN@969..970 "?" [] [], + ERROR_TOKEN@970..971 "?" [] [], + ERROR_TOKEN@971..973 "?" [] [Whitespace(" ")], + L_PAREN@973..974 "(" [] [], + ], + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: CssTypeSelector { + namespace: missing (optional), + ident: CssIdentifier { + value_token: IDENT@974..977 "--b" [] [], + }, + }, + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@977..979 ":" [] [Whitespace(" ")], + class: CssPseudoClassIdentifier { + name: CssIdentifier { + value_token: IDENT@979..983 "blue" [] [], + }, + }, + }, + ], + }, + missing separator, + CssBogusSelector { + items: [ + R_PAREN@983..984 ")" [] [], + R_PAREN@984..986 ")" [] [Whitespace(" ")], + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@986..987 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@987..989 "}" [Newline("\n")] [], + }, + }, + CssAtRule { + at_token: AT@989..1084 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 8: Mi ..."), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@1084..1094 "container" [] [Whitespace(" ")], + CssCustomIdentifier { + value_token: IDENT@1094..1099 "name" [] [Whitespace(" ")], + }, + CssBogus { + items: [ + STYLE_KW@1099..1104 "style" [] [], + L_PAREN@1104..1105 "(" [] [], + CssBogus { + items: [ + L_PAREN@1105..1106 "(" [] [], + CssBogus { + items: [ + IDENT@1106..1110 "--b" [] [Whitespace(" ")], + IDENT@1110..1113 "red" [] [], + ], + }, + R_PAREN@1113..1114 ")" [] [], + ], + }, + R_PAREN@1114..1116 ")" [] [Whitespace(" ")], + ], + }, + CssRuleBlock { + l_curly_token: L_CURLY@1116..1117 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@1117..1119 "}" [Newline("\n")] [], + }, + ], + }, + }, + CssAtRule { + at_token: AT@1119..1226 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 9: In ..."), Newline("\n")] [], + rule: CssBogusAtRule { + items: [ + CONTAINER_KW@1226..1236 "container" [] [Whitespace(" ")], + CssCustomIdentifier { + value_token: IDENT@1236..1241 "name" [] [Whitespace(" ")], + }, + CssBogus { + items: [ + STYLE_KW@1241..1246 "style" [] [], + L_PAREN@1246..1247 "(" [] [], + CssBogus { + items: [ + CssContainerStyleInParens { + l_paren_token: L_PAREN@1247..1248 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssDashedIdentifier { + value_token: IDENT@1248..1251 "--b" [] [], + }, + colon_token: COLON@1251..1253 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@1253..1256 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@1256..1258 ")" [] [Whitespace(" ")], + }, + AND_KW@1258..1262 "and" [] [Whitespace(" ")], + CssBogus { + items: [ + OR_KW@1262..1265 "or" [] [Whitespace(" ")], + ], + }, + ], + }, + ], + }, + CssBogusBlock { + items: [], + }, + ], + }, + }, + CssBogusRule { + items: [ + L_PAREN@1265..1266 "(" [] [], + ], + }, + CssQualifiedRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selectors: CssNestedSelectorList [], + simple_selector: CssTypeSelector { + namespace: missing (optional), + ident: CssIdentifier { + value_token: IDENT@1266..1269 "--c" [] [], + }, + }, + sub_selectors: CssSubSelectorList [ + CssPseudoClassSelector { + colon_token: COLON@1269..1271 ":" [] [Whitespace(" ")], + class: CssPseudoClassIdentifier { + name: CssIdentifier { + value_token: IDENT@1271..1274 "red" [] [], + }, + }, + }, + ], + }, + missing separator, + CssBogusSelector { + items: [ + R_PAREN@1274..1275 ")" [] [], + R_PAREN@1275..1277 ")" [] [Whitespace(" ")], + ], + }, + ], + block: CssDeclarationOrRuleBlock { + l_curly_token: L_CURLY@1277..1278 "{" [] [], + items: CssDeclarationOrRuleList [], + r_curly_token: R_CURLY@1278..1280 "}" [Newline("\n")] [], + }, + }, + CssAtRule { + at_token: AT@1280..1398 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 10: E ..."), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@1398..1408 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@1408..1413 "name" [] [Whitespace(" ")], + }, + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@1413..1418 "style" [] [], + l_paren_token: L_PAREN@1418..1419 "(" [] [], + query: CssContainerStyleInParens { + l_paren_token: L_PAREN@1419..1420 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssDashedIdentifier { + value_token: IDENT@1420..1423 "--b" [] [], + }, + colon_token: COLON@1423..1425 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@1425..1428 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@1428..1429 ")" [] [], + }, + r_paren_token: R_PAREN@1429..1430 ")" [] [], + }, + block: CssBogusBlock { + items: [], + }, + }, + }, + CssBogusRule { + items: [ + ERROR_TOKEN@1430..1431 "?" [] [], + ERROR_TOKEN@1431..1433 "?" [] [Whitespace(" ")], + L_CURLY@1433..1434 "{" [] [], + R_CURLY@1434..1436 "}" [Newline("\n")] [], + ], + }, + ], + eof_token: EOF@1436..1437 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..1437 + 0: (empty) + 1: CSS_RULE_LIST@0..1436 + 0: CSS_AT_RULE@0..134 + 0: AT@0..85 "@" [Comments("/*\n ERROR CASE 1: Mi ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@85..134 + 0: CONTAINER_KW@85..95 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@95..100 + 0: IDENT@95..100 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@100..132 + 0: STYLE_KW@100..105 "style" [] [] + 1: L_PAREN@105..106 "(" [] [] + 2: CSS_CONTAINER_STYLE_OR_QUERY@106..132 + 0: CSS_CONTAINER_STYLE_IN_PARENS@106..117 + 0: L_PAREN@106..107 "(" [] [] + 1: CSS_DECLARATION@107..115 + 0: CSS_GENERIC_PROPERTY@107..115 + 0: CSS_DASHED_IDENTIFIER@107..110 + 0: IDENT@107..110 "--b" [] [] + 1: COLON@110..112 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@112..115 + 0: CSS_IDENTIFIER@112..115 + 0: IDENT@112..115 "red" [] [] + 1: (empty) + 2: R_PAREN@115..117 ")" [] [Whitespace(" ")] + 1: OR_KW@117..120 "or" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_IN_PARENS@120..132 + 0: L_PAREN@120..121 "(" [] [] + 1: CSS_DECLARATION@121..132 + 0: CSS_BOGUS_PROPERTY@121..132 + 0: CSS_DASHED_IDENTIFIER@121..124 + 0: IDENT@121..124 "--b" [] [] + 1: COLON@124..126 ":" [] [Whitespace(" ")] + 2: CSS_BOGUS@126..132 + 0: CSS_IDENTIFIER@126..131 + 0: IDENT@126..131 "blue" [] [Whitespace(" ")] + 1: CSS_BOGUS_PROPERTY_VALUE@131..132 + 0: L_CURLY@131..132 "{" [] [] + 1: (empty) + 2: (empty) + 3: (empty) + 3: CSS_BOGUS_BLOCK@132..134 + 0: CSS_RULE_LIST@132..132 + 1: R_CURLY@132..134 "}" [Newline("\n")] [] + 1: CSS_AT_RULE@134..304 + 0: AT@134..239 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 2: Ex ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@239..304 + 0: CONTAINER_KW@239..249 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@249..254 + 0: IDENT@249..254 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@254..304 + 0: STYLE_KW@254..259 "style" [] [] + 1: L_PAREN@259..260 "(" [] [] + 2: CSS_CONTAINER_STYLE_OR_QUERY@260..302 + 0: CSS_CONTAINER_STYLE_IN_PARENS@260..271 + 0: L_PAREN@260..261 "(" [] [] + 1: CSS_DECLARATION@261..269 + 0: CSS_GENERIC_PROPERTY@261..269 + 0: CSS_DASHED_IDENTIFIER@261..264 + 0: IDENT@261..264 "--b" [] [] + 1: COLON@264..266 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@266..269 + 0: CSS_IDENTIFIER@266..269 + 0: IDENT@266..269 "red" [] [] + 1: (empty) + 2: R_PAREN@269..271 ")" [] [Whitespace(" ")] + 1: OR_KW@271..274 "or" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_IN_PARENS@274..302 + 0: L_PAREN@274..275 "(" [] [] + 1: CSS_CONTAINER_STYLE_AND_QUERY@275..300 + 0: CSS_CONTAINER_STYLE_IN_PARENS@275..286 + 0: L_PAREN@275..276 "(" [] [] + 1: CSS_DECLARATION@276..284 + 0: CSS_GENERIC_PROPERTY@276..284 + 0: CSS_DASHED_IDENTIFIER@276..279 + 0: IDENT@276..279 "--b" [] [] + 1: COLON@279..281 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@281..284 + 0: CSS_IDENTIFIER@281..284 + 0: IDENT@281..284 "red" [] [] + 1: (empty) + 2: R_PAREN@284..286 ")" [] [Whitespace(" ")] + 1: AND_KW@286..290 "and" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_IN_PARENS@290..300 + 0: L_PAREN@290..291 "(" [] [] + 1: CSS_DECLARATION@291..299 + 0: CSS_GENERIC_PROPERTY@291..299 + 0: CSS_DASHED_IDENTIFIER@291..294 + 0: IDENT@291..294 "--b" [] [] + 1: COLON@294..296 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@296..299 + 0: CSS_IDENTIFIER@296..299 + 0: IDENT@296..299 "red" [] [] + 1: (empty) + 2: R_PAREN@299..300 ")" [] [] + 2: R_PAREN@300..302 ")" [] [Whitespace(" ")] + 3: R_PAREN@302..304 ")" [] [Whitespace(" ")] + 3: CSS_BOGUS_BLOCK@304..304 + 2: CSS_BOGUS_RULE@304..309 + 0: R_PAREN@304..306 ")" [] [Whitespace(" ")] + 1: L_CURLY@306..307 "{" [] [] + 2: R_CURLY@307..309 "}" [Newline("\n")] [] + 3: CSS_AT_RULE@309..442 + 0: AT@309..402 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 3: In ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@402..442 + 0: CONTAINER_KW@402..412 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@412..417 + 0: IDENT@412..417 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@417..439 + 0: STYLE_KW@417..422 "style" [] [] + 1: L_PAREN@422..423 "(" [] [] + 2: CSS_CONTAINER_STYLE_OR_QUERY@423..437 + 0: CSS_CONTAINER_STYLE_IN_PARENS@423..434 + 0: L_PAREN@423..424 "(" [] [] + 1: CSS_DECLARATION@424..432 + 0: CSS_GENERIC_PROPERTY@424..432 + 0: CSS_DASHED_IDENTIFIER@424..427 + 0: IDENT@424..427 "--b" [] [] + 1: COLON@427..429 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@429..432 + 0: CSS_IDENTIFIER@429..432 + 0: IDENT@429..432 "red" [] [] + 1: (empty) + 2: R_PAREN@432..434 ")" [] [Whitespace(" ")] + 1: OR_KW@434..437 "or" [] [Whitespace(" ")] + 2: (empty) + 3: R_PAREN@437..439 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@439..442 + 0: L_CURLY@439..440 "{" [] [] + 1: CSS_RULE_LIST@440..440 + 2: R_CURLY@440..442 "}" [Newline("\n")] [] + 4: CSS_AT_RULE@442..553 + 0: AT@442..523 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 4: Em ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@523..553 + 0: CONTAINER_KW@523..533 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@533..538 + 0: IDENT@533..538 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@538..550 + 0: STYLE_KW@538..543 "style" [] [] + 1: L_PAREN@543..545 "(" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_IN_PARENS@545..548 + 0: L_PAREN@545..546 "(" [] [] + 1: (empty) + 2: R_PAREN@546..548 ")" [] [Whitespace(" ")] + 3: R_PAREN@548..550 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@550..553 + 0: L_CURLY@550..551 "{" [] [] + 1: CSS_RULE_LIST@551..551 + 2: R_CURLY@551..553 "}" [Newline("\n")] [] + 5: CSS_AT_RULE@553..681 + 0: AT@553..648 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 5: Mi ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@648..681 + 0: CONTAINER_KW@648..658 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@658..663 + 0: IDENT@658..663 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@663..679 + 0: STYLE_KW@663..669 "style" [] [Whitespace(" ")] + 1: (empty) + 2: CSS_DECLARATION@669..679 + 0: CSS_BOGUS_PROPERTY@669..679 + 0: CSS_DASHED_IDENTIFIER@669..672 + 0: IDENT@669..672 "--b" [] [] + 1: COLON@672..674 ":" [] [Whitespace(" ")] + 2: CSS_BOGUS@674..679 + 0: CSS_IDENTIFIER@674..678 + 0: IDENT@674..678 "red" [] [Whitespace(" ")] + 1: CSS_BOGUS_PROPERTY_VALUE@678..679 + 0: L_CURLY@678..679 "{" [] [] + 1: (empty) + 3: (empty) + 3: CSS_BOGUS_BLOCK@679..681 + 0: CSS_RULE_LIST@679..679 + 1: R_CURLY@679..681 "}" [Newline("\n")] [] + 6: CSS_AT_RULE@681..826 + 0: AT@681..787 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 6: In ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@787..826 + 0: CONTAINER_KW@787..797 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@797..802 + 0: IDENT@797..802 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@802..823 + 0: STYLE_KW@802..807 "style" [] [] + 1: L_PAREN@807..808 "(" [] [] + 2: CSS_CONTAINER_STYLE_IN_PARENS@808..821 + 0: L_PAREN@808..809 "(" [] [] + 1: CSS_DECLARATION@809..820 + 0: CSS_GENERIC_PROPERTY@809..820 + 0: CSS_IDENTIFIER@809..814 + 0: IDENT@809..814 "color" [] [] + 1: COLON@814..816 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@816..820 + 0: CSS_COLOR@816..817 + 0: HASH@816..817 "#" [] [] + 1: (empty) + 1: CSS_IDENTIFIER@817..820 + 0: IDENT@817..820 "red" [] [] + 1: (empty) + 2: R_PAREN@820..821 ")" [] [] + 3: R_PAREN@821..823 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@823..826 + 0: L_CURLY@823..824 "{" [] [] + 1: CSS_RULE_LIST@824..824 + 2: R_CURLY@824..826 "}" [Newline("\n")] [] + 7: CSS_AT_RULE@826..969 + 0: AT@826..937 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 7: Un ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@937..969 + 0: CONTAINER_KW@937..947 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@947..952 + 0: IDENT@947..952 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@952..969 + 0: STYLE_KW@952..957 "style" [] [] + 1: L_PAREN@957..958 "(" [] [] + 2: CSS_CONTAINER_STYLE_IN_PARENS@958..969 + 0: L_PAREN@958..959 "(" [] [] + 1: CSS_DECLARATION@959..967 + 0: CSS_GENERIC_PROPERTY@959..967 + 0: CSS_DASHED_IDENTIFIER@959..962 + 0: IDENT@959..962 "--b" [] [] + 1: COLON@962..964 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@964..967 + 0: CSS_IDENTIFIER@964..967 + 0: IDENT@964..967 "red" [] [] + 1: (empty) + 2: R_PAREN@967..969 ")" [] [Whitespace(" ")] + 3: (empty) + 3: CSS_BOGUS_BLOCK@969..969 + 8: CSS_BOGUS_RULE@969..974 + 0: ERROR_TOKEN@969..970 "?" [] [] + 1: ERROR_TOKEN@970..971 "?" [] [] + 2: ERROR_TOKEN@971..973 "?" [] [Whitespace(" ")] + 3: L_PAREN@973..974 "(" [] [] + 9: CSS_QUALIFIED_RULE@974..989 + 0: CSS_SELECTOR_LIST@974..986 + 0: CSS_COMPOUND_SELECTOR@974..983 + 0: CSS_NESTED_SELECTOR_LIST@974..974 + 1: CSS_TYPE_SELECTOR@974..977 + 0: (empty) + 1: CSS_IDENTIFIER@974..977 + 0: IDENT@974..977 "--b" [] [] + 2: CSS_SUB_SELECTOR_LIST@977..983 + 0: CSS_PSEUDO_CLASS_SELECTOR@977..983 + 0: COLON@977..979 ":" [] [Whitespace(" ")] + 1: CSS_PSEUDO_CLASS_IDENTIFIER@979..983 + 0: CSS_IDENTIFIER@979..983 + 0: IDENT@979..983 "blue" [] [] + 1: (empty) + 2: CSS_BOGUS_SELECTOR@983..986 + 0: R_PAREN@983..984 ")" [] [] + 1: R_PAREN@984..986 ")" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@986..989 + 0: L_CURLY@986..987 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@987..987 + 2: R_CURLY@987..989 "}" [Newline("\n")] [] + 10: CSS_AT_RULE@989..1119 + 0: AT@989..1084 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 8: Mi ..."), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@1084..1119 + 0: CONTAINER_KW@1084..1094 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@1094..1099 + 0: IDENT@1094..1099 "name" [] [Whitespace(" ")] + 2: CSS_BOGUS@1099..1116 + 0: STYLE_KW@1099..1104 "style" [] [] + 1: L_PAREN@1104..1105 "(" [] [] + 2: CSS_BOGUS@1105..1114 + 0: L_PAREN@1105..1106 "(" [] [] + 1: CSS_BOGUS@1106..1113 + 0: IDENT@1106..1110 "--b" [] [Whitespace(" ")] + 1: IDENT@1110..1113 "red" [] [] + 2: R_PAREN@1113..1114 ")" [] [] + 3: R_PAREN@1114..1116 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@1116..1119 + 0: L_CURLY@1116..1117 "{" [] [] + 1: CSS_RULE_LIST@1117..1117 + 2: R_CURLY@1117..1119 "}" [Newline("\n")] [] + 11: CSS_AT_RULE@1119..1265 + 0: AT@1119..1226 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 9: In ..."), Newline("\n")] [] + 1: CSS_BOGUS_AT_RULE@1226..1265 + 0: CONTAINER_KW@1226..1236 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@1236..1241 + 0: IDENT@1236..1241 "name" [] [Whitespace(" ")] + 2: CSS_BOGUS@1241..1265 + 0: STYLE_KW@1241..1246 "style" [] [] + 1: L_PAREN@1246..1247 "(" [] [] + 2: CSS_BOGUS@1247..1265 + 0: CSS_CONTAINER_STYLE_IN_PARENS@1247..1258 + 0: L_PAREN@1247..1248 "(" [] [] + 1: CSS_DECLARATION@1248..1256 + 0: CSS_GENERIC_PROPERTY@1248..1256 + 0: CSS_DASHED_IDENTIFIER@1248..1251 + 0: IDENT@1248..1251 "--b" [] [] + 1: COLON@1251..1253 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@1253..1256 + 0: CSS_IDENTIFIER@1253..1256 + 0: IDENT@1253..1256 "red" [] [] + 1: (empty) + 2: R_PAREN@1256..1258 ")" [] [Whitespace(" ")] + 1: AND_KW@1258..1262 "and" [] [Whitespace(" ")] + 2: CSS_BOGUS@1262..1265 + 0: OR_KW@1262..1265 "or" [] [Whitespace(" ")] + 3: CSS_BOGUS_BLOCK@1265..1265 + 12: CSS_BOGUS_RULE@1265..1266 + 0: L_PAREN@1265..1266 "(" [] [] + 13: CSS_QUALIFIED_RULE@1266..1280 + 0: CSS_SELECTOR_LIST@1266..1277 + 0: CSS_COMPOUND_SELECTOR@1266..1274 + 0: CSS_NESTED_SELECTOR_LIST@1266..1266 + 1: CSS_TYPE_SELECTOR@1266..1269 + 0: (empty) + 1: CSS_IDENTIFIER@1266..1269 + 0: IDENT@1266..1269 "--c" [] [] + 2: CSS_SUB_SELECTOR_LIST@1269..1274 + 0: CSS_PSEUDO_CLASS_SELECTOR@1269..1274 + 0: COLON@1269..1271 ":" [] [Whitespace(" ")] + 1: CSS_PSEUDO_CLASS_IDENTIFIER@1271..1274 + 0: CSS_IDENTIFIER@1271..1274 + 0: IDENT@1271..1274 "red" [] [] + 1: (empty) + 2: CSS_BOGUS_SELECTOR@1274..1277 + 0: R_PAREN@1274..1275 ")" [] [] + 1: R_PAREN@1275..1277 ")" [] [Whitespace(" ")] + 1: CSS_DECLARATION_OR_RULE_BLOCK@1277..1280 + 0: L_CURLY@1277..1278 "{" [] [] + 1: CSS_DECLARATION_OR_RULE_LIST@1278..1278 + 2: R_CURLY@1278..1280 "}" [Newline("\n")] [] + 14: CSS_AT_RULE@1280..1430 + 0: AT@1280..1398 "@" [Newline("\n"), Newline("\n"), Comments("/*\n ERROR CASE 10: E ..."), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@1398..1430 + 0: CONTAINER_KW@1398..1408 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@1408..1413 + 0: IDENT@1408..1413 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@1413..1430 + 0: STYLE_KW@1413..1418 "style" [] [] + 1: L_PAREN@1418..1419 "(" [] [] + 2: CSS_CONTAINER_STYLE_IN_PARENS@1419..1429 + 0: L_PAREN@1419..1420 "(" [] [] + 1: CSS_DECLARATION@1420..1428 + 0: CSS_GENERIC_PROPERTY@1420..1428 + 0: CSS_DASHED_IDENTIFIER@1420..1423 + 0: IDENT@1420..1423 "--b" [] [] + 1: COLON@1423..1425 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@1425..1428 + 0: CSS_IDENTIFIER@1425..1428 + 0: IDENT@1425..1428 "red" [] [] + 1: (empty) + 2: R_PAREN@1428..1429 ")" [] [] + 3: R_PAREN@1429..1430 ")" [] [] + 3: CSS_BOGUS_BLOCK@1430..1430 + 15: CSS_BOGUS_RULE@1430..1436 + 0: ERROR_TOKEN@1430..1431 "?" [] [] + 1: ERROR_TOKEN@1431..1433 "?" [] [Whitespace(" ")] + 2: L_CURLY@1433..1434 "{" [] [] + 3: R_CURLY@1434..1436 "}" [Newline("\n")] [] + 2: EOF@1436..1437 "" [Newline("\n")] [] + +``` + +## Diagnostics + +``` +at_rule_container_style_query_error.css:5:48 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 3 │ - Missing ")" after (--b: blue) + 4 │ */ + > 5 │ @container name style((--b: red) or (--b: blue { + │ ^ + 6 │ } + 7 │ + + i Expected one of: + + - identifier + - string + - number + - dimension + - ratio + - custom property + - function + +at_rule_container_style_query_error.css:6:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `)` but instead found `}` + + 4 │ */ + 5 │ @container name style((--b: red) or (--b: blue { + > 6 │ } + │ ^ + 7 │ + 8 │ /* + + i Remove } + +at_rule_container_style_query_error.css:12:67 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `{` but instead found `)` + + 10 │ - The double ")) )" leads to unbalanced parentheses + 11 │ */ + > 12 │ @container name style((--b: red) or ((--b: red) and (--b: red)) ) ) { + │ ^ + 13 │ } + 14 │ + + i Remove ) + +at_rule_container_style_query_error.css:19:37 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 17 │ - There's an "or" but nothing follows + 18 │ */ + > 19 │ @container name style((--b: red) or ) { + │ ^ + 20 │ } + 21 │ + + i Expected one of: + + - ( ) + - ( ) + +at_rule_container_style_query_error.css:26:25 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 24 │ - "()": no valid declaration inside + 25 │ */ + > 26 │ @container name style( () ) { + │ ^ + 27 │ } + 28 │ + + i Expected one of: + + - not + - + - and + - or + - + +at_rule_container_style_query_error.css:33:23 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `(` but instead found `--b` + + 31 │ - "style" must be followed by "(" + 32 │ */ + > 33 │ @container name style --b: red { + │ ^^^ + 34 │ } + 35 │ + + i Remove --b + +at_rule_container_style_query_error.css:33:32 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 31 │ - "style" must be followed by "(" + 32 │ */ + > 33 │ @container name style --b: red { + │ ^ + 34 │ } + 35 │ + + i Expected one of: + + - identifier + - string + - number + - dimension + - ratio + - custom property + - function + +at_rule_container_style_query_error.css:34:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `)` but instead found `}` + + 32 │ */ + 33 │ @container name style --b: red { + > 34 │ } + │ ^ + 35 │ + 36 │ /* + + i Remove } + +at_rule_container_style_query_error.css:40:31 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a color but instead found '#'. + + 38 │ - "#red" isn't a recognized color token in standard CSS + 39 │ */ + > 40 │ @container name style((color: #red)) { + │ ^ + 41 │ } + 42 │ + + i Expected a color here. + + 38 │ - "#red" isn't a recognized color token in standard CSS + 39 │ */ + > 40 │ @container name style((color: #red)) { + │ ^ + 41 │ } + 42 │ + + i Ensure the color is specified in a valid hexadecimal format. Examples: #000, #000f, #ffffff, #ffffffff + +at_rule_container_style_query_error.css:47:34 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × unexpected character `?` + + 45 │ - "???" doesn't fit valid CSS property or logical operator syntax + 46 │ */ + > 47 │ @container name style((--b: red) ??? (--b: blue)) { + │ ^ + 48 │ } + 49 │ + +at_rule_container_style_query_error.css:47:35 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × unexpected character `?` + + 45 │ - "???" doesn't fit valid CSS property or logical operator syntax + 46 │ */ + > 47 │ @container name style((--b: red) ??? (--b: blue)) { + │ ^ + 48 │ } + 49 │ + +at_rule_container_style_query_error.css:47:36 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × unexpected character `?` + + 45 │ - "???" doesn't fit valid CSS property or logical operator syntax + 46 │ */ + > 47 │ @container name style((--b: red) ??? (--b: blue)) { + │ ^ + 48 │ } + 49 │ + +at_rule_container_style_query_error.css:47:48 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `,` but instead found `)` + + 45 │ - "???" doesn't fit valid CSS property or logical operator syntax + 46 │ */ + > 47 │ @container name style((--b: red) ??? (--b: blue)) { + │ ^ + 48 │ } + 49 │ + + i Remove ) + +at_rule_container_style_query_error.css:54:24 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 52 │ - "(--b red)" should be "(--b: red)" + 53 │ */ + > 54 │ @container name style((--b red)) { + │ ^^^^^^^ + 55 │ } + 56 │ + + i Expected one of: + + - not + - + - and + - or + - + +at_rule_container_style_query_error.css:61:38 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Unexpected value or character. + + 59 │ - "and or" in direct sequence is invalid + 60 │ */ + > 61 │ @container name style((--b: red) and or (--c: red)) { + │ ^^ + 62 │ } + 63 │ + + i Expected one of: + + - ( ) + - ( ) + +at_rule_container_style_query_error.css:61:41 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `)` but instead found `(` + + 59 │ - "and or" in direct sequence is invalid + 60 │ */ + > 61 │ @container name style((--b: red) and or (--c: red)) { + │ ^ + 62 │ } + 63 │ + + i Remove ( + +at_rule_container_style_query_error.css:61:50 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `,` but instead found `)` + + 59 │ - "and or" in direct sequence is invalid + 60 │ */ + > 61 │ @container name style((--b: red) and or (--c: red)) { + │ ^ + 62 │ } + 63 │ + + i Remove ) + +at_rule_container_style_query_error.css:68:34 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × unexpected character `?` + + 66 │ - "??" is unexpected after "((--b: red))" + 67 │ */ + > 68 │ @container name style((--b: red))?? { + │ ^ + 69 │ } + 70 │ + +at_rule_container_style_query_error.css:68:35 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × unexpected character `?` + + 66 │ - "??" is unexpected after "((--b: red))" + 67 │ */ + > 68 │ @container name style((--b: red))?? { + │ ^ + 69 │ } + 70 │ + +``` diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container_error.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container_error.css.snap deleted file mode 100644 index d834d074896e..000000000000 --- a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container_error.css.snap +++ /dev/null @@ -1,1115 +0,0 @@ ---- -source: crates/biome_css_parser/tests/spec_test.rs -expression: snapshot ---- -## Input - -```css -@container inherit (width <= 500px) { } -@container initial (width <= 500px) { } -@container unset (width <= 500px) { } -@container revert (width <= 500px) { } -@container revert-layer (width <= 500px) { } -@container inherit width <= 500px) { } - -@container not width <= 500px) { } - -@container not (width <= 500px { } -@container not (width <=) { } -@container not { } - -@container my-layout (inline-size > 45em) { } - -@container card (inline-size > 30em) or { } - -@container (inline-size >= 0px) } - -@container { } -@container () { } - -``` - - -## AST - -``` -CssRoot { - bom_token: missing (optional), - rules: CssRuleList [ - CssAtRule { - at_token: AT@0..1 "@" [] [], - rule: CssBogusAtRule { - items: [ - CONTAINER_KW@1..11 "container" [] [Whitespace(" ")], - CssBogus { - items: [ - INHERIT_KW@11..19 "inherit" [] [Whitespace(" ")], - ], - }, - CssContainerSizeFeatureInParens { - l_paren_token: L_PAREN@19..20 "(" [] [], - feature: CssQueryFeatureRange { - left: CssIdentifier { - value_token: IDENT@20..26 "width" [] [Whitespace(" ")], - }, - comparison: CssQueryFeatureRangeComparison { - operator: LTEQ@26..29 "<=" [] [Whitespace(" ")], - }, - right: CssRegularDimension { - value_token: CSS_NUMBER_LITERAL@29..32 "500" [] [], - unit_token: IDENT@32..34 "px" [] [], - }, - }, - r_paren_token: R_PAREN@34..36 ")" [] [Whitespace(" ")], - }, - CssRuleBlock { - l_curly_token: L_CURLY@36..38 "{" [] [Whitespace(" ")], - rules: CssRuleList [], - r_curly_token: R_CURLY@38..39 "}" [] [], - }, - ], - }, - }, - CssAtRule { - at_token: AT@39..41 "@" [Newline("\n")] [], - rule: CssBogusAtRule { - items: [ - CONTAINER_KW@41..51 "container" [] [Whitespace(" ")], - CssBogus { - items: [ - INITIAL_KW@51..59 "initial" [] [Whitespace(" ")], - ], - }, - CssContainerSizeFeatureInParens { - l_paren_token: L_PAREN@59..60 "(" [] [], - feature: CssQueryFeatureRange { - left: CssIdentifier { - value_token: IDENT@60..66 "width" [] [Whitespace(" ")], - }, - comparison: CssQueryFeatureRangeComparison { - operator: LTEQ@66..69 "<=" [] [Whitespace(" ")], - }, - right: CssRegularDimension { - value_token: CSS_NUMBER_LITERAL@69..72 "500" [] [], - unit_token: IDENT@72..74 "px" [] [], - }, - }, - r_paren_token: R_PAREN@74..76 ")" [] [Whitespace(" ")], - }, - CssRuleBlock { - l_curly_token: L_CURLY@76..78 "{" [] [Whitespace(" ")], - rules: CssRuleList [], - r_curly_token: R_CURLY@78..79 "}" [] [], - }, - ], - }, - }, - CssAtRule { - at_token: AT@79..81 "@" [Newline("\n")] [], - rule: CssBogusAtRule { - items: [ - CONTAINER_KW@81..91 "container" [] [Whitespace(" ")], - CssBogus { - items: [ - UNSET_KW@91..97 "unset" [] [Whitespace(" ")], - ], - }, - CssContainerSizeFeatureInParens { - l_paren_token: L_PAREN@97..98 "(" [] [], - feature: CssQueryFeatureRange { - left: CssIdentifier { - value_token: IDENT@98..104 "width" [] [Whitespace(" ")], - }, - comparison: CssQueryFeatureRangeComparison { - operator: LTEQ@104..107 "<=" [] [Whitespace(" ")], - }, - right: CssRegularDimension { - value_token: CSS_NUMBER_LITERAL@107..110 "500" [] [], - unit_token: IDENT@110..112 "px" [] [], - }, - }, - r_paren_token: R_PAREN@112..114 ")" [] [Whitespace(" ")], - }, - CssRuleBlock { - l_curly_token: L_CURLY@114..116 "{" [] [Whitespace(" ")], - rules: CssRuleList [], - r_curly_token: R_CURLY@116..117 "}" [] [], - }, - ], - }, - }, - CssAtRule { - at_token: AT@117..119 "@" [Newline("\n")] [], - rule: CssBogusAtRule { - items: [ - CONTAINER_KW@119..129 "container" [] [Whitespace(" ")], - CssBogus { - items: [ - REVERT_KW@129..136 "revert" [] [Whitespace(" ")], - ], - }, - CssContainerSizeFeatureInParens { - l_paren_token: L_PAREN@136..137 "(" [] [], - feature: CssQueryFeatureRange { - left: CssIdentifier { - value_token: IDENT@137..143 "width" [] [Whitespace(" ")], - }, - comparison: CssQueryFeatureRangeComparison { - operator: LTEQ@143..146 "<=" [] [Whitespace(" ")], - }, - right: CssRegularDimension { - value_token: CSS_NUMBER_LITERAL@146..149 "500" [] [], - unit_token: IDENT@149..151 "px" [] [], - }, - }, - r_paren_token: R_PAREN@151..153 ")" [] [Whitespace(" ")], - }, - CssRuleBlock { - l_curly_token: L_CURLY@153..155 "{" [] [Whitespace(" ")], - rules: CssRuleList [], - r_curly_token: R_CURLY@155..156 "}" [] [], - }, - ], - }, - }, - CssAtRule { - at_token: AT@156..158 "@" [Newline("\n")] [], - rule: CssBogusAtRule { - items: [ - CONTAINER_KW@158..168 "container" [] [Whitespace(" ")], - CssBogus { - items: [ - REVERT_LAYER_KW@168..181 "revert-layer" [] [Whitespace(" ")], - ], - }, - CssContainerSizeFeatureInParens { - l_paren_token: L_PAREN@181..182 "(" [] [], - feature: CssQueryFeatureRange { - left: CssIdentifier { - value_token: IDENT@182..188 "width" [] [Whitespace(" ")], - }, - comparison: CssQueryFeatureRangeComparison { - operator: LTEQ@188..191 "<=" [] [Whitespace(" ")], - }, - right: CssRegularDimension { - value_token: CSS_NUMBER_LITERAL@191..194 "500" [] [], - unit_token: IDENT@194..196 "px" [] [], - }, - }, - r_paren_token: R_PAREN@196..198 ")" [] [Whitespace(" ")], - }, - CssRuleBlock { - l_curly_token: L_CURLY@198..200 "{" [] [Whitespace(" ")], - rules: CssRuleList [], - r_curly_token: R_CURLY@200..201 "}" [] [], - }, - ], - }, - }, - CssAtRule { - at_token: AT@201..203 "@" [Newline("\n")] [], - rule: CssBogusAtRule { - items: [ - CONTAINER_KW@203..213 "container" [] [Whitespace(" ")], - CssBogus { - items: [ - INHERIT_KW@213..221 "inherit" [] [Whitespace(" ")], - ], - }, - CssBogusBlock { - items: [ - CssRuleList [ - CssQualifiedRule { - prelude: CssSelectorList [ - CssComplexSelector { - left: CssCompoundSelector { - nesting_selectors: CssNestedSelectorList [], - simple_selector: CssTypeSelector { - namespace: missing (optional), - ident: CssIdentifier { - value_token: IDENT@221..226 "width" [] [], - }, - }, - sub_selectors: CssSubSelectorList [], - }, - combinator: CSS_SPACE_LITERAL@226..227 " " [] [], - right: missing (required), - }, - missing separator, - CssBogusSelector { - items: [ - LTEQ@227..230 "<=" [] [Whitespace(" ")], - CSS_DIMENSION_VALUE@230..233 "500" [] [], - ], - }, - missing separator, - CssCompoundSelector { - nesting_selectors: CssNestedSelectorList [], - simple_selector: CssTypeSelector { - namespace: missing (optional), - ident: CssIdentifier { - value_token: IDENT@233..235 "px" [] [], - }, - }, - sub_selectors: CssSubSelectorList [], - }, - missing separator, - CssBogusSelector { - items: [ - R_PAREN@235..237 ")" [] [Whitespace(" ")], - ], - }, - ], - block: CssDeclarationOrRuleBlock { - l_curly_token: L_CURLY@237..239 "{" [] [Whitespace(" ")], - items: CssDeclarationOrRuleList [], - r_curly_token: R_CURLY@239..240 "}" [] [], - }, - }, - CssAtRule { - at_token: AT@240..243 "@" [Newline("\n"), Newline("\n")] [], - rule: CssContainerAtRule { - container_token: CONTAINER_KW@243..253 "container" [] [Whitespace(" ")], - name: CssCustomIdentifier { - value_token: IDENT@253..257 "not" [] [Whitespace(" ")], - }, - query: missing (required), - block: CssBogusBlock { - items: [ - CssDeclarationOrRuleList [ - CssNestedQualifiedRule { - prelude: CssRelativeSelectorList [ - CssRelativeSelector { - combinator: missing (optional), - selector: CssComplexSelector { - left: CssCompoundSelector { - nesting_selectors: CssNestedSelectorList [], - simple_selector: CssTypeSelector { - namespace: missing (optional), - ident: CssIdentifier { - value_token: IDENT@257..262 "width" [] [], - }, - }, - sub_selectors: CssSubSelectorList [], - }, - combinator: CSS_SPACE_LITERAL@262..263 " " [] [], - right: missing (required), - }, - }, - missing separator, - CssBogusSelector { - items: [ - LTEQ@263..266 "<=" [] [Whitespace(" ")], - CSS_DIMENSION_VALUE@266..269 "500" [] [], - ], - }, - missing separator, - CssRelativeSelector { - combinator: missing (optional), - selector: CssCompoundSelector { - nesting_selectors: CssNestedSelectorList [], - simple_selector: CssTypeSelector { - namespace: missing (optional), - ident: CssIdentifier { - value_token: IDENT@269..271 "px" [] [], - }, - }, - sub_selectors: CssSubSelectorList [], - }, - }, - missing separator, - CssBogusSelector { - items: [ - R_PAREN@271..273 ")" [] [Whitespace(" ")], - ], - }, - ], - block: CssDeclarationOrRuleBlock { - l_curly_token: L_CURLY@273..276 "{" [] [Whitespace(" ")], - items: CssDeclarationOrRuleList [], - r_curly_token: R_CURLY@276..277 "}" [] [], - }, - }, - CssAtRule { - at_token: AT@277..280 "@" [Newline("\n"), Newline("\n")] [], - rule: CssContainerAtRule { - container_token: CONTAINER_KW@280..290 "container" [] [Whitespace(" ")], - name: CssCustomIdentifier { - value_token: IDENT@290..294 "not" [] [Whitespace(" ")], - }, - query: CssContainerSizeFeatureInParens { - l_paren_token: L_PAREN@294..295 "(" [] [], - feature: CssQueryFeatureRange { - left: CssIdentifier { - value_token: IDENT@295..301 "width" [] [Whitespace(" ")], - }, - comparison: CssQueryFeatureRangeComparison { - operator: LTEQ@301..304 "<=" [] [Whitespace(" ")], - }, - right: CssRegularDimension { - value_token: CSS_NUMBER_LITERAL@304..307 "500" [] [], - unit_token: IDENT@307..310 "px" [] [Whitespace(" ")], - }, - }, - r_paren_token: missing (required), - }, - block: CssDeclarationOrRuleBlock { - l_curly_token: L_CURLY@310..313 "{" [] [Whitespace(" ")], - items: CssDeclarationOrRuleList [], - r_curly_token: R_CURLY@313..314 "}" [] [], - }, - }, - }, - CssAtRule { - at_token: AT@314..316 "@" [Newline("\n")] [], - rule: CssContainerAtRule { - container_token: CONTAINER_KW@316..326 "container" [] [Whitespace(" ")], - name: CssCustomIdentifier { - value_token: IDENT@326..330 "not" [] [Whitespace(" ")], - }, - query: CssContainerSizeFeatureInParens { - l_paren_token: L_PAREN@330..331 "(" [] [], - feature: CssQueryFeatureRange { - left: CssIdentifier { - value_token: IDENT@331..337 "width" [] [Whitespace(" ")], - }, - comparison: CssQueryFeatureRangeComparison { - operator: LTEQ@337..339 "<=" [] [], - }, - right: missing (required), - }, - r_paren_token: R_PAREN@339..341 ")" [] [Whitespace(" ")], - }, - block: CssDeclarationOrRuleBlock { - l_curly_token: L_CURLY@341..344 "{" [] [Whitespace(" ")], - items: CssDeclarationOrRuleList [], - r_curly_token: R_CURLY@344..345 "}" [] [], - }, - }, - }, - CssAtRule { - at_token: AT@345..347 "@" [Newline("\n")] [], - rule: CssContainerAtRule { - container_token: CONTAINER_KW@347..357 "container" [] [Whitespace(" ")], - name: CssCustomIdentifier { - value_token: IDENT@357..361 "not" [] [Whitespace(" ")], - }, - query: missing (required), - block: CssDeclarationOrRuleBlock { - l_curly_token: L_CURLY@361..364 "{" [] [Whitespace(" ")], - items: CssDeclarationOrRuleList [], - r_curly_token: R_CURLY@364..365 "}" [] [], - }, - }, - }, - CssAtRule { - at_token: AT@365..368 "@" [Newline("\n"), Newline("\n")] [], - rule: CssContainerAtRule { - container_token: CONTAINER_KW@368..378 "container" [] [Whitespace(" ")], - name: CssCustomIdentifier { - value_token: IDENT@378..388 "my-layout" [] [Whitespace(" ")], - }, - query: CssContainerSizeFeatureInParens { - l_paren_token: L_PAREN@388..389 "(" [] [], - feature: CssQueryFeatureRange { - left: CssIdentifier { - value_token: IDENT@389..401 "inline-size" [] [Whitespace(" ")], - }, - comparison: CssQueryFeatureRangeComparison { - operator: R_ANGLE@401..403 ">" [] [Whitespace(" ")], - }, - right: CssRegularDimension { - value_token: CSS_NUMBER_LITERAL@403..405 "45" [] [], - unit_token: IDENT@405..407 "em" [] [], - }, - }, - r_paren_token: R_PAREN@407..409 ")" [] [Whitespace(" ")], - }, - block: CssDeclarationOrRuleBlock { - l_curly_token: L_CURLY@409..412 "{" [] [Whitespace(" ")], - items: CssDeclarationOrRuleList [], - r_curly_token: R_CURLY@412..413 "}" [] [], - }, - }, - }, - CssAtRule { - at_token: AT@413..416 "@" [Newline("\n"), Newline("\n")] [], - rule: CssContainerAtRule { - container_token: CONTAINER_KW@416..426 "container" [] [Whitespace(" ")], - name: CssCustomIdentifier { - value_token: IDENT@426..431 "card" [] [Whitespace(" ")], - }, - query: CssContainerOrQuery { - left: CssContainerSizeFeatureInParens { - l_paren_token: L_PAREN@431..432 "(" [] [], - feature: CssQueryFeatureRange { - left: CssIdentifier { - value_token: IDENT@432..444 "inline-size" [] [Whitespace(" ")], - }, - comparison: CssQueryFeatureRangeComparison { - operator: R_ANGLE@444..446 ">" [] [Whitespace(" ")], - }, - right: CssRegularDimension { - value_token: CSS_NUMBER_LITERAL@446..448 "30" [] [], - unit_token: IDENT@448..450 "em" [] [], - }, - }, - r_paren_token: R_PAREN@450..452 ")" [] [Whitespace(" ")], - }, - or_token: OR_KW@452..455 "or" [] [Whitespace(" ")], - right: missing (required), - }, - block: CssDeclarationOrRuleBlock { - l_curly_token: L_CURLY@455..458 "{" [] [Whitespace(" ")], - items: CssDeclarationOrRuleList [], - r_curly_token: R_CURLY@458..459 "}" [] [], - }, - }, - }, - CssAtRule { - at_token: AT@459..462 "@" [Newline("\n"), Newline("\n")] [], - rule: CssContainerAtRule { - container_token: CONTAINER_KW@462..472 "container" [] [Whitespace(" ")], - name: missing (optional), - query: CssContainerSizeFeatureInParens { - l_paren_token: L_PAREN@472..473 "(" [] [], - feature: CssQueryFeatureRange { - left: CssIdentifier { - value_token: IDENT@473..485 "inline-size" [] [Whitespace(" ")], - }, - comparison: CssQueryFeatureRangeComparison { - operator: GTEQ@485..488 ">=" [] [Whitespace(" ")], - }, - right: CssRegularDimension { - value_token: CSS_NUMBER_LITERAL@488..489 "0" [] [], - unit_token: IDENT@489..491 "px" [] [], - }, - }, - r_paren_token: R_PAREN@491..494 ")" [] [Whitespace(" ")], - }, - block: CssBogusBlock { - items: [], - }, - }, - }, - ], - R_CURLY@494..495 "}" [] [], - ], - }, - }, - }, - CssAtRule { - at_token: AT@495..498 "@" [Newline("\n"), Newline("\n")] [], - rule: CssContainerAtRule { - container_token: CONTAINER_KW@498..508 "container" [] [Whitespace(" ")], - name: missing (optional), - query: missing (required), - block: CssDeclarationOrRuleBlock { - l_curly_token: L_CURLY@508..510 "{" [] [Whitespace(" ")], - items: CssDeclarationOrRuleList [], - r_curly_token: R_CURLY@510..511 "}" [] [], - }, - }, - }, - CssAtRule { - at_token: AT@511..513 "@" [Newline("\n")] [], - rule: CssContainerAtRule { - container_token: CONTAINER_KW@513..523 "container" [] [Whitespace(" ")], - name: missing (optional), - query: CssContainerSizeFeatureInParens { - l_paren_token: L_PAREN@523..524 "(" [] [], - feature: missing (required), - r_paren_token: R_PAREN@524..526 ")" [] [Whitespace(" ")], - }, - block: CssDeclarationOrRuleBlock { - l_curly_token: L_CURLY@526..528 "{" [] [Whitespace(" ")], - items: CssDeclarationOrRuleList [], - r_curly_token: R_CURLY@528..529 "}" [] [], - }, - }, - }, - ], - ], - }, - ], - }, - }, - ], - eof_token: EOF@529..530 "" [Newline("\n")] [], -} -``` - -## CST - -``` -0: CSS_ROOT@0..530 - 0: (empty) - 1: CSS_RULE_LIST@0..529 - 0: CSS_AT_RULE@0..39 - 0: AT@0..1 "@" [] [] - 1: CSS_BOGUS_AT_RULE@1..39 - 0: CONTAINER_KW@1..11 "container" [] [Whitespace(" ")] - 1: CSS_BOGUS@11..19 - 0: INHERIT_KW@11..19 "inherit" [] [Whitespace(" ")] - 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@19..36 - 0: L_PAREN@19..20 "(" [] [] - 1: CSS_QUERY_FEATURE_RANGE@20..34 - 0: CSS_IDENTIFIER@20..26 - 0: IDENT@20..26 "width" [] [Whitespace(" ")] - 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@26..29 - 0: LTEQ@26..29 "<=" [] [Whitespace(" ")] - 2: CSS_REGULAR_DIMENSION@29..34 - 0: CSS_NUMBER_LITERAL@29..32 "500" [] [] - 1: IDENT@32..34 "px" [] [] - 2: R_PAREN@34..36 ")" [] [Whitespace(" ")] - 3: CSS_RULE_BLOCK@36..39 - 0: L_CURLY@36..38 "{" [] [Whitespace(" ")] - 1: CSS_RULE_LIST@38..38 - 2: R_CURLY@38..39 "}" [] [] - 1: CSS_AT_RULE@39..79 - 0: AT@39..41 "@" [Newline("\n")] [] - 1: CSS_BOGUS_AT_RULE@41..79 - 0: CONTAINER_KW@41..51 "container" [] [Whitespace(" ")] - 1: CSS_BOGUS@51..59 - 0: INITIAL_KW@51..59 "initial" [] [Whitespace(" ")] - 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@59..76 - 0: L_PAREN@59..60 "(" [] [] - 1: CSS_QUERY_FEATURE_RANGE@60..74 - 0: CSS_IDENTIFIER@60..66 - 0: IDENT@60..66 "width" [] [Whitespace(" ")] - 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@66..69 - 0: LTEQ@66..69 "<=" [] [Whitespace(" ")] - 2: CSS_REGULAR_DIMENSION@69..74 - 0: CSS_NUMBER_LITERAL@69..72 "500" [] [] - 1: IDENT@72..74 "px" [] [] - 2: R_PAREN@74..76 ")" [] [Whitespace(" ")] - 3: CSS_RULE_BLOCK@76..79 - 0: L_CURLY@76..78 "{" [] [Whitespace(" ")] - 1: CSS_RULE_LIST@78..78 - 2: R_CURLY@78..79 "}" [] [] - 2: CSS_AT_RULE@79..117 - 0: AT@79..81 "@" [Newline("\n")] [] - 1: CSS_BOGUS_AT_RULE@81..117 - 0: CONTAINER_KW@81..91 "container" [] [Whitespace(" ")] - 1: CSS_BOGUS@91..97 - 0: UNSET_KW@91..97 "unset" [] [Whitespace(" ")] - 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@97..114 - 0: L_PAREN@97..98 "(" [] [] - 1: CSS_QUERY_FEATURE_RANGE@98..112 - 0: CSS_IDENTIFIER@98..104 - 0: IDENT@98..104 "width" [] [Whitespace(" ")] - 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@104..107 - 0: LTEQ@104..107 "<=" [] [Whitespace(" ")] - 2: CSS_REGULAR_DIMENSION@107..112 - 0: CSS_NUMBER_LITERAL@107..110 "500" [] [] - 1: IDENT@110..112 "px" [] [] - 2: R_PAREN@112..114 ")" [] [Whitespace(" ")] - 3: CSS_RULE_BLOCK@114..117 - 0: L_CURLY@114..116 "{" [] [Whitespace(" ")] - 1: CSS_RULE_LIST@116..116 - 2: R_CURLY@116..117 "}" [] [] - 3: CSS_AT_RULE@117..156 - 0: AT@117..119 "@" [Newline("\n")] [] - 1: CSS_BOGUS_AT_RULE@119..156 - 0: CONTAINER_KW@119..129 "container" [] [Whitespace(" ")] - 1: CSS_BOGUS@129..136 - 0: REVERT_KW@129..136 "revert" [] [Whitespace(" ")] - 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@136..153 - 0: L_PAREN@136..137 "(" [] [] - 1: CSS_QUERY_FEATURE_RANGE@137..151 - 0: CSS_IDENTIFIER@137..143 - 0: IDENT@137..143 "width" [] [Whitespace(" ")] - 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@143..146 - 0: LTEQ@143..146 "<=" [] [Whitespace(" ")] - 2: CSS_REGULAR_DIMENSION@146..151 - 0: CSS_NUMBER_LITERAL@146..149 "500" [] [] - 1: IDENT@149..151 "px" [] [] - 2: R_PAREN@151..153 ")" [] [Whitespace(" ")] - 3: CSS_RULE_BLOCK@153..156 - 0: L_CURLY@153..155 "{" [] [Whitespace(" ")] - 1: CSS_RULE_LIST@155..155 - 2: R_CURLY@155..156 "}" [] [] - 4: CSS_AT_RULE@156..201 - 0: AT@156..158 "@" [Newline("\n")] [] - 1: CSS_BOGUS_AT_RULE@158..201 - 0: CONTAINER_KW@158..168 "container" [] [Whitespace(" ")] - 1: CSS_BOGUS@168..181 - 0: REVERT_LAYER_KW@168..181 "revert-layer" [] [Whitespace(" ")] - 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@181..198 - 0: L_PAREN@181..182 "(" [] [] - 1: CSS_QUERY_FEATURE_RANGE@182..196 - 0: CSS_IDENTIFIER@182..188 - 0: IDENT@182..188 "width" [] [Whitespace(" ")] - 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@188..191 - 0: LTEQ@188..191 "<=" [] [Whitespace(" ")] - 2: CSS_REGULAR_DIMENSION@191..196 - 0: CSS_NUMBER_LITERAL@191..194 "500" [] [] - 1: IDENT@194..196 "px" [] [] - 2: R_PAREN@196..198 ")" [] [Whitespace(" ")] - 3: CSS_RULE_BLOCK@198..201 - 0: L_CURLY@198..200 "{" [] [Whitespace(" ")] - 1: CSS_RULE_LIST@200..200 - 2: R_CURLY@200..201 "}" [] [] - 5: CSS_AT_RULE@201..529 - 0: AT@201..203 "@" [Newline("\n")] [] - 1: CSS_BOGUS_AT_RULE@203..529 - 0: CONTAINER_KW@203..213 "container" [] [Whitespace(" ")] - 1: CSS_BOGUS@213..221 - 0: INHERIT_KW@213..221 "inherit" [] [Whitespace(" ")] - 2: CSS_BOGUS_BLOCK@221..529 - 0: CSS_RULE_LIST@221..529 - 0: CSS_QUALIFIED_RULE@221..240 - 0: CSS_SELECTOR_LIST@221..237 - 0: CSS_COMPLEX_SELECTOR@221..227 - 0: CSS_COMPOUND_SELECTOR@221..226 - 0: CSS_NESTED_SELECTOR_LIST@221..221 - 1: CSS_TYPE_SELECTOR@221..226 - 0: (empty) - 1: CSS_IDENTIFIER@221..226 - 0: IDENT@221..226 "width" [] [] - 2: CSS_SUB_SELECTOR_LIST@226..226 - 1: CSS_SPACE_LITERAL@226..227 " " [] [] - 2: (empty) - 1: (empty) - 2: CSS_BOGUS_SELECTOR@227..233 - 0: LTEQ@227..230 "<=" [] [Whitespace(" ")] - 1: CSS_DIMENSION_VALUE@230..233 "500" [] [] - 3: (empty) - 4: CSS_COMPOUND_SELECTOR@233..235 - 0: CSS_NESTED_SELECTOR_LIST@233..233 - 1: CSS_TYPE_SELECTOR@233..235 - 0: (empty) - 1: CSS_IDENTIFIER@233..235 - 0: IDENT@233..235 "px" [] [] - 2: CSS_SUB_SELECTOR_LIST@235..235 - 5: (empty) - 6: CSS_BOGUS_SELECTOR@235..237 - 0: R_PAREN@235..237 ")" [] [Whitespace(" ")] - 1: CSS_DECLARATION_OR_RULE_BLOCK@237..240 - 0: L_CURLY@237..239 "{" [] [Whitespace(" ")] - 1: CSS_DECLARATION_OR_RULE_LIST@239..239 - 2: R_CURLY@239..240 "}" [] [] - 1: CSS_AT_RULE@240..495 - 0: AT@240..243 "@" [Newline("\n"), Newline("\n")] [] - 1: CSS_CONTAINER_AT_RULE@243..495 - 0: CONTAINER_KW@243..253 "container" [] [Whitespace(" ")] - 1: CSS_CUSTOM_IDENTIFIER@253..257 - 0: IDENT@253..257 "not" [] [Whitespace(" ")] - 2: (empty) - 3: CSS_BOGUS_BLOCK@257..495 - 0: CSS_DECLARATION_OR_RULE_LIST@257..494 - 0: CSS_NESTED_QUALIFIED_RULE@257..277 - 0: CSS_RELATIVE_SELECTOR_LIST@257..273 - 0: CSS_RELATIVE_SELECTOR@257..263 - 0: (empty) - 1: CSS_COMPLEX_SELECTOR@257..263 - 0: CSS_COMPOUND_SELECTOR@257..262 - 0: CSS_NESTED_SELECTOR_LIST@257..257 - 1: CSS_TYPE_SELECTOR@257..262 - 0: (empty) - 1: CSS_IDENTIFIER@257..262 - 0: IDENT@257..262 "width" [] [] - 2: CSS_SUB_SELECTOR_LIST@262..262 - 1: CSS_SPACE_LITERAL@262..263 " " [] [] - 2: (empty) - 1: (empty) - 2: CSS_BOGUS_SELECTOR@263..269 - 0: LTEQ@263..266 "<=" [] [Whitespace(" ")] - 1: CSS_DIMENSION_VALUE@266..269 "500" [] [] - 3: (empty) - 4: CSS_RELATIVE_SELECTOR@269..271 - 0: (empty) - 1: CSS_COMPOUND_SELECTOR@269..271 - 0: CSS_NESTED_SELECTOR_LIST@269..269 - 1: CSS_TYPE_SELECTOR@269..271 - 0: (empty) - 1: CSS_IDENTIFIER@269..271 - 0: IDENT@269..271 "px" [] [] - 2: CSS_SUB_SELECTOR_LIST@271..271 - 5: (empty) - 6: CSS_BOGUS_SELECTOR@271..273 - 0: R_PAREN@271..273 ")" [] [Whitespace(" ")] - 1: CSS_DECLARATION_OR_RULE_BLOCK@273..277 - 0: L_CURLY@273..276 "{" [] [Whitespace(" ")] - 1: CSS_DECLARATION_OR_RULE_LIST@276..276 - 2: R_CURLY@276..277 "}" [] [] - 1: CSS_AT_RULE@277..314 - 0: AT@277..280 "@" [Newline("\n"), Newline("\n")] [] - 1: CSS_CONTAINER_AT_RULE@280..314 - 0: CONTAINER_KW@280..290 "container" [] [Whitespace(" ")] - 1: CSS_CUSTOM_IDENTIFIER@290..294 - 0: IDENT@290..294 "not" [] [Whitespace(" ")] - 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@294..310 - 0: L_PAREN@294..295 "(" [] [] - 1: CSS_QUERY_FEATURE_RANGE@295..310 - 0: CSS_IDENTIFIER@295..301 - 0: IDENT@295..301 "width" [] [Whitespace(" ")] - 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@301..304 - 0: LTEQ@301..304 "<=" [] [Whitespace(" ")] - 2: CSS_REGULAR_DIMENSION@304..310 - 0: CSS_NUMBER_LITERAL@304..307 "500" [] [] - 1: IDENT@307..310 "px" [] [Whitespace(" ")] - 2: (empty) - 3: CSS_DECLARATION_OR_RULE_BLOCK@310..314 - 0: L_CURLY@310..313 "{" [] [Whitespace(" ")] - 1: CSS_DECLARATION_OR_RULE_LIST@313..313 - 2: R_CURLY@313..314 "}" [] [] - 2: CSS_AT_RULE@314..345 - 0: AT@314..316 "@" [Newline("\n")] [] - 1: CSS_CONTAINER_AT_RULE@316..345 - 0: CONTAINER_KW@316..326 "container" [] [Whitespace(" ")] - 1: CSS_CUSTOM_IDENTIFIER@326..330 - 0: IDENT@326..330 "not" [] [Whitespace(" ")] - 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@330..341 - 0: L_PAREN@330..331 "(" [] [] - 1: CSS_QUERY_FEATURE_RANGE@331..339 - 0: CSS_IDENTIFIER@331..337 - 0: IDENT@331..337 "width" [] [Whitespace(" ")] - 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@337..339 - 0: LTEQ@337..339 "<=" [] [] - 2: (empty) - 2: R_PAREN@339..341 ")" [] [Whitespace(" ")] - 3: CSS_DECLARATION_OR_RULE_BLOCK@341..345 - 0: L_CURLY@341..344 "{" [] [Whitespace(" ")] - 1: CSS_DECLARATION_OR_RULE_LIST@344..344 - 2: R_CURLY@344..345 "}" [] [] - 3: CSS_AT_RULE@345..365 - 0: AT@345..347 "@" [Newline("\n")] [] - 1: CSS_CONTAINER_AT_RULE@347..365 - 0: CONTAINER_KW@347..357 "container" [] [Whitespace(" ")] - 1: CSS_CUSTOM_IDENTIFIER@357..361 - 0: IDENT@357..361 "not" [] [Whitespace(" ")] - 2: (empty) - 3: CSS_DECLARATION_OR_RULE_BLOCK@361..365 - 0: L_CURLY@361..364 "{" [] [Whitespace(" ")] - 1: CSS_DECLARATION_OR_RULE_LIST@364..364 - 2: R_CURLY@364..365 "}" [] [] - 4: CSS_AT_RULE@365..413 - 0: AT@365..368 "@" [Newline("\n"), Newline("\n")] [] - 1: CSS_CONTAINER_AT_RULE@368..413 - 0: CONTAINER_KW@368..378 "container" [] [Whitespace(" ")] - 1: CSS_CUSTOM_IDENTIFIER@378..388 - 0: IDENT@378..388 "my-layout" [] [Whitespace(" ")] - 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@388..409 - 0: L_PAREN@388..389 "(" [] [] - 1: CSS_QUERY_FEATURE_RANGE@389..407 - 0: CSS_IDENTIFIER@389..401 - 0: IDENT@389..401 "inline-size" [] [Whitespace(" ")] - 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@401..403 - 0: R_ANGLE@401..403 ">" [] [Whitespace(" ")] - 2: CSS_REGULAR_DIMENSION@403..407 - 0: CSS_NUMBER_LITERAL@403..405 "45" [] [] - 1: IDENT@405..407 "em" [] [] - 2: R_PAREN@407..409 ")" [] [Whitespace(" ")] - 3: CSS_DECLARATION_OR_RULE_BLOCK@409..413 - 0: L_CURLY@409..412 "{" [] [Whitespace(" ")] - 1: CSS_DECLARATION_OR_RULE_LIST@412..412 - 2: R_CURLY@412..413 "}" [] [] - 5: CSS_AT_RULE@413..459 - 0: AT@413..416 "@" [Newline("\n"), Newline("\n")] [] - 1: CSS_CONTAINER_AT_RULE@416..459 - 0: CONTAINER_KW@416..426 "container" [] [Whitespace(" ")] - 1: CSS_CUSTOM_IDENTIFIER@426..431 - 0: IDENT@426..431 "card" [] [Whitespace(" ")] - 2: CSS_CONTAINER_OR_QUERY@431..455 - 0: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@431..452 - 0: L_PAREN@431..432 "(" [] [] - 1: CSS_QUERY_FEATURE_RANGE@432..450 - 0: CSS_IDENTIFIER@432..444 - 0: IDENT@432..444 "inline-size" [] [Whitespace(" ")] - 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@444..446 - 0: R_ANGLE@444..446 ">" [] [Whitespace(" ")] - 2: CSS_REGULAR_DIMENSION@446..450 - 0: CSS_NUMBER_LITERAL@446..448 "30" [] [] - 1: IDENT@448..450 "em" [] [] - 2: R_PAREN@450..452 ")" [] [Whitespace(" ")] - 1: OR_KW@452..455 "or" [] [Whitespace(" ")] - 2: (empty) - 3: CSS_DECLARATION_OR_RULE_BLOCK@455..459 - 0: L_CURLY@455..458 "{" [] [Whitespace(" ")] - 1: CSS_DECLARATION_OR_RULE_LIST@458..458 - 2: R_CURLY@458..459 "}" [] [] - 6: CSS_AT_RULE@459..494 - 0: AT@459..462 "@" [Newline("\n"), Newline("\n")] [] - 1: CSS_CONTAINER_AT_RULE@462..494 - 0: CONTAINER_KW@462..472 "container" [] [Whitespace(" ")] - 1: (empty) - 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@472..494 - 0: L_PAREN@472..473 "(" [] [] - 1: CSS_QUERY_FEATURE_RANGE@473..491 - 0: CSS_IDENTIFIER@473..485 - 0: IDENT@473..485 "inline-size" [] [Whitespace(" ")] - 1: CSS_QUERY_FEATURE_RANGE_COMPARISON@485..488 - 0: GTEQ@485..488 ">=" [] [Whitespace(" ")] - 2: CSS_REGULAR_DIMENSION@488..491 - 0: CSS_NUMBER_LITERAL@488..489 "0" [] [] - 1: IDENT@489..491 "px" [] [] - 2: R_PAREN@491..494 ")" [] [Whitespace(" ")] - 3: CSS_BOGUS_BLOCK@494..494 - 1: R_CURLY@494..495 "}" [] [] - 2: CSS_AT_RULE@495..511 - 0: AT@495..498 "@" [Newline("\n"), Newline("\n")] [] - 1: CSS_CONTAINER_AT_RULE@498..511 - 0: CONTAINER_KW@498..508 "container" [] [Whitespace(" ")] - 1: (empty) - 2: (empty) - 3: CSS_DECLARATION_OR_RULE_BLOCK@508..511 - 0: L_CURLY@508..510 "{" [] [Whitespace(" ")] - 1: CSS_DECLARATION_OR_RULE_LIST@510..510 - 2: R_CURLY@510..511 "}" [] [] - 3: CSS_AT_RULE@511..529 - 0: AT@511..513 "@" [Newline("\n")] [] - 1: CSS_CONTAINER_AT_RULE@513..529 - 0: CONTAINER_KW@513..523 "container" [] [Whitespace(" ")] - 1: (empty) - 2: CSS_CONTAINER_SIZE_FEATURE_IN_PARENS@523..526 - 0: L_PAREN@523..524 "(" [] [] - 1: (empty) - 2: R_PAREN@524..526 ")" [] [Whitespace(" ")] - 3: CSS_DECLARATION_OR_RULE_BLOCK@526..529 - 0: L_CURLY@526..528 "{" [] [Whitespace(" ")] - 1: CSS_DECLARATION_OR_RULE_LIST@528..528 - 2: R_CURLY@528..529 "}" [] [] - 2: EOF@529..530 "" [Newline("\n")] [] - -``` - -## Diagnostics - -``` -at_rule_container_error.css:1:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Expected an identifier but instead found 'inherit' - - > 1 │ @container inherit (width <= 500px) { } - │ ^^^^^^^ - 2 │ @container initial (width <= 500px) { } - 3 │ @container unset (width <= 500px) { } - - i 'inherit' is a CSS-wide keyword that cannot be used here - -at_rule_container_error.css:2:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Expected an identifier but instead found 'initial' - - 1 │ @container inherit (width <= 500px) { } - > 2 │ @container initial (width <= 500px) { } - │ ^^^^^^^ - 3 │ @container unset (width <= 500px) { } - 4 │ @container revert (width <= 500px) { } - - i 'initial' is a CSS-wide keyword that cannot be used here - -at_rule_container_error.css:3:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Expected an identifier but instead found 'unset' - - 1 │ @container inherit (width <= 500px) { } - 2 │ @container initial (width <= 500px) { } - > 3 │ @container unset (width <= 500px) { } - │ ^^^^^ - 4 │ @container revert (width <= 500px) { } - 5 │ @container revert-layer (width <= 500px) { } - - i 'unset' is a CSS-wide keyword that cannot be used here - -at_rule_container_error.css:4:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Expected an identifier but instead found 'revert' - - 2 │ @container initial (width <= 500px) { } - 3 │ @container unset (width <= 500px) { } - > 4 │ @container revert (width <= 500px) { } - │ ^^^^^^ - 5 │ @container revert-layer (width <= 500px) { } - 6 │ @container inherit width <= 500px) { } - - i 'revert' is a CSS-wide keyword that cannot be used here - -at_rule_container_error.css:5:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Expected an identifier but instead found 'revert-layer' - - 3 │ @container unset (width <= 500px) { } - 4 │ @container revert (width <= 500px) { } - > 5 │ @container revert-layer (width <= 500px) { } - │ ^^^^^^^^^^^^ - 6 │ @container inherit width <= 500px) { } - 7 │ - - i 'revert-layer' is a CSS-wide keyword that cannot be used here - -at_rule_container_error.css:6:12 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Expected an identifier but instead found 'inherit' - - 4 │ @container revert (width <= 500px) { } - 5 │ @container revert-layer (width <= 500px) { } - > 6 │ @container inherit width <= 500px) { } - │ ^^^^^^^ - 7 │ - 8 │ @container not width <= 500px) { } - - i 'inherit' is a CSS-wide keyword that cannot be used here - -at_rule_container_error.css:6:20 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `{` but instead found `width` - - 4 │ @container revert (width <= 500px) { } - 5 │ @container revert-layer (width <= 500px) { } - > 6 │ @container inherit width <= 500px) { } - │ ^^^^^ - 7 │ - 8 │ @container not width <= 500px) { } - - i Remove width - -at_rule_container_error.css:6:26 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Expected a compound selector but instead found '<='. - - 4 │ @container revert (width <= 500px) { } - 5 │ @container revert-layer (width <= 500px) { } - > 6 │ @container inherit width <= 500px) { } - │ ^^ - 7 │ - 8 │ @container not width <= 500px) { } - - i Expected a compound selector here. - - 4 │ @container revert (width <= 500px) { } - 5 │ @container revert-layer (width <= 500px) { } - > 6 │ @container inherit width <= 500px) { } - │ ^^ - 7 │ - 8 │ @container not width <= 500px) { } - -at_rule_container_error.css:6:32 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `,` but instead found `px` - - 4 │ @container revert (width <= 500px) { } - 5 │ @container revert-layer (width <= 500px) { } - > 6 │ @container inherit width <= 500px) { } - │ ^^ - 7 │ - 8 │ @container not width <= 500px) { } - - i Remove px - -at_rule_container_error.css:6:34 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `,` but instead found `)` - - 4 │ @container revert (width <= 500px) { } - 5 │ @container revert-layer (width <= 500px) { } - > 6 │ @container inherit width <= 500px) { } - │ ^ - 7 │ - 8 │ @container not width <= 500px) { } - - i Remove ) - -at_rule_container_error.css:8:16 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `{` but instead found `width` - - 6 │ @container inherit width <= 500px) { } - 7 │ - > 8 │ @container not width <= 500px) { } - │ ^^^^^ - 9 │ - 10 │ @container not (width <= 500px { } - - i Remove width - -at_rule_container_error.css:8:22 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Expected a compound selector but instead found '<='. - - 6 │ @container inherit width <= 500px) { } - 7 │ - > 8 │ @container not width <= 500px) { } - │ ^^ - 9 │ - 10 │ @container not (width <= 500px { } - - i Expected a compound selector here. - - 6 │ @container inherit width <= 500px) { } - 7 │ - > 8 │ @container not width <= 500px) { } - │ ^^ - 9 │ - 10 │ @container not (width <= 500px { } - -at_rule_container_error.css:8:28 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `,` but instead found `px` - - 6 │ @container inherit width <= 500px) { } - 7 │ - > 8 │ @container not width <= 500px) { } - │ ^^ - 9 │ - 10 │ @container not (width <= 500px { } - - i Remove px - -at_rule_container_error.css:8:30 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `,` but instead found `)` - - 6 │ @container inherit width <= 500px) { } - 7 │ - > 8 │ @container not width <= 500px) { } - │ ^ - 9 │ - 10 │ @container not (width <= 500px { } - - i Remove ) - -at_rule_container_error.css:10:32 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `)` but instead found `{` - - 8 │ @container not width <= 500px) { } - 9 │ - > 10 │ @container not (width <= 500px { } - │ ^ - 11 │ @container not (width <=) { } - 12 │ @container not { } - - i Remove { - -at_rule_container_error.css:18:34 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `{` but instead found `}` - - 16 │ @container card (inline-size > 30em) or { } - 17 │ - > 18 │ @container (inline-size >= 0px) } - │ ^ - 19 │ - 20 │ @container { } - - i Remove } - -at_rule_container_error.css:22:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `}` but instead the file ends - - 20 │ @container { } - 21 │ @container () { } - > 22 │ - │ - - i the file ends here - - 20 │ @container { } - 21 │ @container () { } - > 22 │ - │ - -``` diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes/at_rule_keyframes_1.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes/at_rule_keyframes_1.css.snap index fef66a688187..0868f0d50b91 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes/at_rule_keyframes_1.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes/at_rule_keyframes_1.css.snap @@ -145,56 +145,47 @@ CssRoot { }, ], block: CssBogusBlock { - items: [], + items: [ + CssDeclarationList [], + R_CURLY@93..96 "}" [Newline("\n"), Whitespace("\t")] [], + ], }, }, - ], - r_curly_token: R_CURLY@93..96 "}" [Newline("\n"), Whitespace("\t")] [], - }, - }, - }, - CssQualifiedRule { - prelude: CssSelectorList [ - CssCompoundSelector { - nesting_selectors: CssNestedSelectorList [], - simple_selector: CssTypeSelector { - namespace: missing (optional), - ident: CssIdentifier { - value_token: IDENT@96..101 "to" [Newline("\n"), Whitespace("\t")] [Whitespace(" ")], - }, - }, - sub_selectors: CssSubSelectorList [], - }, - ], - block: CssDeclarationOrRuleBlock { - l_curly_token: L_CURLY@101..102 "{" [] [], - items: CssDeclarationOrRuleList [ - CssDeclarationWithSemicolon { - declaration: CssDeclaration { - property: CssGenericProperty { - name: CssIdentifier { - value_token: IDENT@102..110 "color" [Newline("\n"), Whitespace("\t\t")] [], + CssKeyframesItem { + selectors: CssKeyframesSelectorList [ + CssKeyframesIdentSelector { + selector: TO_KW@96..101 "to" [Newline("\n"), Whitespace("\t")] [Whitespace(" ")], }, - colon_token: COLON@110..112 ":" [] [Whitespace(" ")], - value: CssGenericComponentValueList [ - CssIdentifier { - value_token: IDENT@112..116 "blue" [] [], + ], + block: CssDeclarationBlock { + l_curly_token: L_CURLY@101..102 "{" [] [], + declarations: CssDeclarationList [ + CssDeclarationWithSemicolon { + declaration: CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@102..110 "color" [Newline("\n"), Whitespace("\t\t")] [], + }, + colon_token: COLON@110..112 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@112..116 "blue" [] [], + }, + ], + }, + important: missing (optional), + }, + semicolon_token: SEMICOLON@116..117 ";" [] [], }, ], + r_curly_token: R_CURLY@117..120 "}" [Newline("\n"), Whitespace("\t")] [], }, - important: missing (optional), }, - semicolon_token: SEMICOLON@116..117 ";" [] [], - }, - ], - r_curly_token: R_CURLY@117..120 "}" [Newline("\n"), Whitespace("\t")] [], + ], + r_curly_token: R_CURLY@120..122 "}" [Newline("\n")] [], + }, }, }, - CssBogusRule { - items: [ - R_CURLY@120..122 "}" [Newline("\n")] [], - ], - }, CssAtRule { at_token: AT@122..125 "@" [Newline("\n"), Newline("\n")] [], rule: CssKeyframesAtRule { @@ -448,48 +439,43 @@ CssRoot { 1: SEMICOLON@61..62 ";" [] [] 2: R_CURLY@62..65 "}" [Newline("\n"), Whitespace("\t")] [] 2: R_CURLY@65..67 "}" [Newline("\n")] [] - 1: CSS_AT_RULE@67..96 + 1: CSS_AT_RULE@67..122 0: AT@67..70 "@" [Newline("\n"), Newline("\n")] [] - 1: CSS_KEYFRAMES_AT_RULE@70..96 + 1: CSS_KEYFRAMES_AT_RULE@70..122 0: KEYFRAMES_KW@70..80 "keyframes" [] [Whitespace(" ")] 1: CSS_CUSTOM_IDENTIFIER@80..86 0: IDENT@80..86 "name1" [] [Whitespace(" ")] - 2: CSS_KEYFRAMES_BLOCK@86..96 + 2: CSS_KEYFRAMES_BLOCK@86..122 0: L_CURLY@86..87 "{" [] [] - 1: CSS_KEYFRAMES_ITEM_LIST@87..93 - 0: CSS_KEYFRAMES_ITEM@87..93 + 1: CSS_KEYFRAMES_ITEM_LIST@87..120 + 0: CSS_KEYFRAMES_ITEM@87..96 0: CSS_KEYFRAMES_SELECTOR_LIST@87..93 0: CSS_KEYFRAMES_IDENT_SELECTOR@87..93 0: FROM_KW@87..93 "from" [Newline("\n"), Whitespace("\t")] [] - 1: CSS_BOGUS_BLOCK@93..93 - 2: R_CURLY@93..96 "}" [Newline("\n"), Whitespace("\t")] [] - 2: CSS_QUALIFIED_RULE@96..120 - 0: CSS_SELECTOR_LIST@96..101 - 0: CSS_COMPOUND_SELECTOR@96..101 - 0: CSS_NESTED_SELECTOR_LIST@96..96 - 1: CSS_TYPE_SELECTOR@96..101 - 0: (empty) - 1: CSS_IDENTIFIER@96..101 - 0: IDENT@96..101 "to" [Newline("\n"), Whitespace("\t")] [Whitespace(" ")] - 2: CSS_SUB_SELECTOR_LIST@101..101 - 1: CSS_DECLARATION_OR_RULE_BLOCK@101..120 - 0: L_CURLY@101..102 "{" [] [] - 1: CSS_DECLARATION_OR_RULE_LIST@102..117 - 0: CSS_DECLARATION_WITH_SEMICOLON@102..117 - 0: CSS_DECLARATION@102..116 - 0: CSS_GENERIC_PROPERTY@102..116 - 0: CSS_IDENTIFIER@102..110 - 0: IDENT@102..110 "color" [Newline("\n"), Whitespace("\t\t")] [] - 1: COLON@110..112 ":" [] [Whitespace(" ")] - 2: CSS_GENERIC_COMPONENT_VALUE_LIST@112..116 - 0: CSS_IDENTIFIER@112..116 - 0: IDENT@112..116 "blue" [] [] - 1: (empty) - 1: SEMICOLON@116..117 ";" [] [] - 2: R_CURLY@117..120 "}" [Newline("\n"), Whitespace("\t")] [] - 3: CSS_BOGUS_RULE@120..122 - 0: R_CURLY@120..122 "}" [Newline("\n")] [] - 4: CSS_AT_RULE@122..190 + 1: CSS_BOGUS_BLOCK@93..96 + 0: CSS_DECLARATION_LIST@93..93 + 1: R_CURLY@93..96 "}" [Newline("\n"), Whitespace("\t")] [] + 1: CSS_KEYFRAMES_ITEM@96..120 + 0: CSS_KEYFRAMES_SELECTOR_LIST@96..101 + 0: CSS_KEYFRAMES_IDENT_SELECTOR@96..101 + 0: TO_KW@96..101 "to" [Newline("\n"), Whitespace("\t")] [Whitespace(" ")] + 1: CSS_DECLARATION_BLOCK@101..120 + 0: L_CURLY@101..102 "{" [] [] + 1: CSS_DECLARATION_LIST@102..117 + 0: CSS_DECLARATION_WITH_SEMICOLON@102..117 + 0: CSS_DECLARATION@102..116 + 0: CSS_GENERIC_PROPERTY@102..116 + 0: CSS_IDENTIFIER@102..110 + 0: IDENT@102..110 "color" [Newline("\n"), Whitespace("\t\t")] [] + 1: COLON@110..112 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@112..116 + 0: CSS_IDENTIFIER@112..116 + 0: IDENT@112..116 "blue" [] [] + 1: (empty) + 1: SEMICOLON@116..117 ";" [] [] + 2: R_CURLY@117..120 "}" [Newline("\n"), Whitespace("\t")] [] + 2: R_CURLY@120..122 "}" [Newline("\n")] [] + 2: CSS_AT_RULE@122..190 0: AT@122..125 "@" [Newline("\n"), Newline("\n")] [] 1: CSS_KEYFRAMES_AT_RULE@125..190 0: KEYFRAMES_KW@125..135 "keyframes" [] [Whitespace(" ")] @@ -525,7 +511,7 @@ CssRoot { 5: SEMICOLON@184..185 ";" [] [] 2: R_CURLY@185..188 "}" [Newline("\n"), Whitespace("\t")] [] 2: R_CURLY@188..190 "}" [Newline("\n")] [] - 5: CSS_AT_RULE@190..334 + 3: CSS_AT_RULE@190..334 0: AT@190..193 "@" [Newline("\n"), Newline("\n")] [] 1: CSS_KEYFRAMES_AT_RULE@193..334 0: KEYFRAMES_KW@193..203 "keyframes" [] [Whitespace(" ")] @@ -643,26 +629,6 @@ at_rule_keyframes_1.css:12:2 parse ━━━━━━━━━━━━━━━ i Remove } -at_rule_keyframes_1.css:16:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Expected a qualified rule, or an at rule but instead found '}'. - - 14 │ color: blue; - 15 │ } - > 16 │ } - │ ^ - 17 │ - 18 │ @keyframes name2 { - - i Expected a qualified rule, or an at rule here. - - 14 │ color: blue; - 15 │ } - > 16 │ } - │ ^ - 17 │ - 18 │ @keyframes name2 { - at_rule_keyframes_1.css:22:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ × Expected a declaration item but instead found 'to { diff --git a/crates/biome_css_parser/tests/css_test_suite/error/block/css_unfinished_block.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/block/css_unfinished_block.css.snap index a568545beb2f..eba90be0d6e8 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/block/css_unfinished_block.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/block/css_unfinished_block.css.snap @@ -35,14 +35,12 @@ CssRoot { }, ], block: CssBogusBlock { - items: [], + items: [ + CssDeclarationOrRuleList [], + R_CURLY@4..5 "}" [] [], + ], }, }, - CssBogusRule { - items: [ - R_CURLY@4..5 "}" [] [], - ], - }, CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { @@ -76,7 +74,7 @@ CssRoot { 0: CSS_ROOT@0..16 0: (empty) 1: CSS_RULE_LIST@0..15 - 0: CSS_QUALIFIED_RULE@0..4 + 0: CSS_QUALIFIED_RULE@0..5 0: CSS_SELECTOR_LIST@0..4 0: CSS_COMPLEX_SELECTOR@0..4 0: CSS_COMPOUND_SELECTOR@0..3 @@ -88,10 +86,10 @@ CssRoot { 2: CSS_SUB_SELECTOR_LIST@3..3 1: CSS_SPACE_LITERAL@3..4 " " [] [] 2: (empty) - 1: CSS_BOGUS_BLOCK@4..4 - 1: CSS_BOGUS_RULE@4..5 - 0: R_CURLY@4..5 "}" [] [] - 2: CSS_QUALIFIED_RULE@5..15 + 1: CSS_BOGUS_BLOCK@4..5 + 0: CSS_DECLARATION_OR_RULE_LIST@4..4 + 1: R_CURLY@4..5 "}" [] [] + 1: CSS_QUALIFIED_RULE@5..15 0: CSS_SELECTOR_LIST@5..14 0: CSS_COMPOUND_SELECTOR@5..14 0: CSS_NESTED_SELECTOR_LIST@5..5 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container.css b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container.css index 75e1b5662868..12595485707b 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container.css +++ b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container.css @@ -31,4 +31,6 @@ @container ( WIDTH <= 150px ) { } @container ( 150px <= WIDTH ) { } -@container --dashed-name not (width <= 500px) { } \ No newline at end of file +@container --dashed-name not (width <= 500px) { } + +@container name not style(color: red) {} diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container.css.snap index 4aa1775a6669..f4fd87f04569 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container.css.snap @@ -39,6 +39,9 @@ expression: snapshot @container ( 150px <= WIDTH ) { } @container --dashed-name not (width <= 500px) { } + +@container name not style(color: red) {} + ``` @@ -645,17 +648,53 @@ CssRoot { }, }, }, + CssAtRule { + at_token: AT@805..808 "@" [Newline("\n"), Newline("\n")] [], + rule: CssContainerAtRule { + container_token: CONTAINER_KW@808..818 "container" [] [Whitespace(" ")], + name: CssCustomIdentifier { + value_token: IDENT@818..823 "name" [] [Whitespace(" ")], + }, + query: CssContainerNotQuery { + not_token: NOT_KW@823..827 "not" [] [Whitespace(" ")], + query: CssContainerStyleQueryInParens { + style_token: STYLE_KW@827..832 "style" [] [], + l_paren_token: L_PAREN@832..833 "(" [] [], + query: CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@833..838 "color" [] [], + }, + colon_token: COLON@838..840 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@840..843 "red" [] [], + }, + ], + }, + important: missing (optional), + }, + r_paren_token: R_PAREN@843..845 ")" [] [Whitespace(" ")], + }, + }, + block: CssRuleBlock { + l_curly_token: L_CURLY@845..846 "{" [] [], + rules: CssRuleList [], + r_curly_token: R_CURLY@846..847 "}" [] [], + }, + }, + }, ], - eof_token: EOF@805..805 "" [] [], + eof_token: EOF@847..848 "" [Newline("\n")] [], } ``` ## CST ``` -0: CSS_ROOT@0..805 +0: CSS_ROOT@0..848 0: (empty) - 1: CSS_RULE_LIST@0..805 + 1: CSS_RULE_LIST@0..847 0: CSS_AT_RULE@0..41 0: AT@0..1 "@" [] [] 1: CSS_CONTAINER_AT_RULE@1..41 @@ -1076,6 +1115,31 @@ CssRoot { 0: L_CURLY@801..804 "{" [] [Whitespace(" ")] 1: CSS_RULE_LIST@804..804 2: R_CURLY@804..805 "}" [] [] - 2: EOF@805..805 "" [] [] + 18: CSS_AT_RULE@805..847 + 0: AT@805..808 "@" [Newline("\n"), Newline("\n")] [] + 1: CSS_CONTAINER_AT_RULE@808..847 + 0: CONTAINER_KW@808..818 "container" [] [Whitespace(" ")] + 1: CSS_CUSTOM_IDENTIFIER@818..823 + 0: IDENT@818..823 "name" [] [Whitespace(" ")] + 2: CSS_CONTAINER_NOT_QUERY@823..845 + 0: NOT_KW@823..827 "not" [] [Whitespace(" ")] + 1: CSS_CONTAINER_STYLE_QUERY_IN_PARENS@827..845 + 0: STYLE_KW@827..832 "style" [] [] + 1: L_PAREN@832..833 "(" [] [] + 2: CSS_DECLARATION@833..843 + 0: CSS_GENERIC_PROPERTY@833..843 + 0: CSS_IDENTIFIER@833..838 + 0: IDENT@833..838 "color" [] [] + 1: COLON@838..840 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@840..843 + 0: CSS_IDENTIFIER@840..843 + 0: IDENT@840..843 "red" [] [] + 1: (empty) + 3: R_PAREN@843..845 ")" [] [Whitespace(" ")] + 3: CSS_RULE_BLOCK@845..847 + 0: L_CURLY@845..846 "{" [] [] + 1: CSS_RULE_LIST@846..846 + 2: R_CURLY@846..847 "}" [] [] + 2: EOF@847..848 "" [Newline("\n")] [] ``` diff --git a/crates/biome_css_parser/tests/spec_test.rs b/crates/biome_css_parser/tests/spec_test.rs index 278464320d38..5ed09d1a5674 100644 --- a/crates/biome_css_parser/tests/spec_test.rs +++ b/crates/biome_css_parser/tests/spec_test.rs @@ -178,9 +178,10 @@ pub fn run(test_case: &str, _snapshot_name: &str, test_directory: &str, outcome_ #[test] pub fn quick_test() { let code = r#" - .foo { - color: blue;; - } +@container name style(not((color: red)) ) ) { +background: red +} + "#; let root = parse_css(