From fc638301d588387110ab50350f1bbbdcbb43dbc9 Mon Sep 17 00:00:00 2001 From: Jon Egeland Date: Wed, 3 Jan 2024 00:20:58 +0000 Subject: [PATCH] Add some properties and comments to the grammar wip parsing properties properly parse and format `all` and `z-index` fix comment in ungram feedback clippy more clippy doctest --- .../src/generated/node_factory.rs | 60 ++ .../src/generated/syntax_factory.rs | 129 +++ .../src/css/any/all_property_value.rs | 16 + crates/biome_css_formatter/src/css/any/mod.rs | 2 + .../src/css/any/property.rs | 2 + .../src/css/any/z_index_property_value.rs | 18 + .../src/css/auxiliary/auto.rs | 13 + .../src/css/auxiliary/generic_delimiter.rs | 9 +- .../src/css/auxiliary/mod.rs | 3 + .../css/auxiliary/unknown_property_value.rs | 15 + .../src/css/auxiliary/wide_keyword.rs | 13 + .../src/css/bogus/bogus_property_value.rs | 5 + .../biome_css_formatter/src/css/bogus/mod.rs | 1 + .../src/css/properties/all_property.rs | 20 + .../src/css/properties/mod.rs | 2 + .../src/css/properties/z_index_property.rs | 20 + crates/biome_css_formatter/src/generated.rs | 280 ++++++ .../tests/specs/css/atrule/font_face.css.snap | 10 - .../tests/specs/css/properties/all.css | 12 + .../tests/specs/css/properties/all.css.snap | 49 ++ .../tests/specs/css/properties/custom.css | 16 + .../specs/css/properties/custom.css.snap | 53 ++ .../tests/specs/css/properties/generic.css | 16 + .../specs/css/properties/generic.css.snap | 53 ++ .../tests/specs/css/properties/z-index.css | 13 + .../specs/css/properties/z-index.css.snap | 51 ++ crates/biome_css_parser/src/lexer/mod.rs | 1 + crates/biome_css_parser/src/syntax/mod.rs | 19 +- .../src/syntax/property/all.rs | 35 + .../src/syntax/property/mod.rs | 145 +++- .../src/syntax/property/z_index.rs | 32 + .../error/property/property_generic_error.css | 5 + .../property/property_generic_error.css.snap | 185 ++++ .../ok/property/property_all.css | 17 + .../ok/property/property_all.css.snap | 433 ++++++++++ .../ok/property/property_generic.css | 26 + .../ok/property/property_generic.css.snap | 782 +++++++++++++++++ .../ok/property/property_z-index.css | 27 + .../ok/property/property_z-index.css.snap | 576 +++++++++++++ crates/biome_css_syntax/src/generated/kind.rs | 12 +- .../biome_css_syntax/src/generated/macros.rs | 24 + .../biome_css_syntax/src/generated/nodes.rs | 815 +++++++++++++++++- .../src/generated/nodes_mut.rs | 67 ++ crates/biome_css_syntax/src/lib.rs | 1 + xtask/codegen/css.ungram | 138 +++ xtask/codegen/src/ast.rs | 49 +- xtask/codegen/src/css_kinds_src.rs | 9 +- 47 files changed, 4234 insertions(+), 45 deletions(-) create mode 100644 crates/biome_css_formatter/src/css/any/all_property_value.rs create mode 100644 crates/biome_css_formatter/src/css/any/z_index_property_value.rs create mode 100644 crates/biome_css_formatter/src/css/auxiliary/auto.rs create mode 100644 crates/biome_css_formatter/src/css/auxiliary/unknown_property_value.rs create mode 100644 crates/biome_css_formatter/src/css/auxiliary/wide_keyword.rs create mode 100644 crates/biome_css_formatter/src/css/bogus/bogus_property_value.rs create mode 100644 crates/biome_css_formatter/src/css/properties/all_property.rs create mode 100644 crates/biome_css_formatter/src/css/properties/z_index_property.rs create mode 100644 crates/biome_css_formatter/tests/specs/css/properties/all.css create mode 100644 crates/biome_css_formatter/tests/specs/css/properties/all.css.snap create mode 100644 crates/biome_css_formatter/tests/specs/css/properties/custom.css create mode 100644 crates/biome_css_formatter/tests/specs/css/properties/custom.css.snap create mode 100644 crates/biome_css_formatter/tests/specs/css/properties/generic.css create mode 100644 crates/biome_css_formatter/tests/specs/css/properties/generic.css.snap create mode 100644 crates/biome_css_formatter/tests/specs/css/properties/z-index.css create mode 100644 crates/biome_css_formatter/tests/specs/css/properties/z-index.css.snap create mode 100644 crates/biome_css_parser/src/syntax/property/all.rs create mode 100644 crates/biome_css_parser/src/syntax/property/z_index.rs create mode 100644 crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css create mode 100644 crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css.snap create mode 100644 crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css create mode 100644 crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css.snap create mode 100644 crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css create mode 100644 crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css.snap create mode 100644 crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css create mode 100644 crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css.snap diff --git a/crates/biome_css_factory/src/generated/node_factory.rs b/crates/biome_css_factory/src/generated/node_factory.rs index 25bce7f20f21..cd6df4cc7979 100644 --- a/crates/biome_css_factory/src/generated/node_factory.rs +++ b/crates/biome_css_factory/src/generated/node_factory.rs @@ -7,6 +7,20 @@ use biome_css_syntax::{ *, }; use biome_rowan::AstNode; +pub fn css_all_property( + name: CssIdentifier, + colon_token: SyntaxToken, + value: AnyCssAllPropertyValue, +) -> CssAllProperty { + CssAllProperty::unwrap_cast(SyntaxNode::new_detached( + CssSyntaxKind::CSS_ALL_PROPERTY, + [ + Some(SyntaxElement::Node(name.into_syntax())), + Some(SyntaxElement::Token(colon_token)), + Some(SyntaxElement::Node(value.into_syntax())), + ], + )) +} pub fn css_at_rule(at_token: SyntaxToken, rule: AnyCssAtRule) -> CssAtRule { CssAtRule::unwrap_cast(SyntaxNode::new_detached( CssSyntaxKind::CSS_AT_RULE, @@ -115,6 +129,12 @@ impl CssAttributeSelectorBuilder { )) } } +pub fn css_auto(value_token: SyntaxToken) -> CssAuto { + CssAuto::unwrap_cast(SyntaxNode::new_detached( + CssSyntaxKind::CSS_AUTO, + [Some(SyntaxElement::Token(value_token))], + )) +} pub fn css_binary_expression( left: AnyCssExpression, operator_token_token: SyntaxToken, @@ -1799,6 +1819,16 @@ pub fn css_unknown_dimension( ], )) } +pub fn css_unknown_property_value( + css_generic_component_value_list: CssGenericComponentValueList, +) -> CssUnknownPropertyValue { + CssUnknownPropertyValue::unwrap_cast(SyntaxNode::new_detached( + CssSyntaxKind::CSS_UNKNOWN_PROPERTY_VALUE, + [Some(SyntaxElement::Node( + css_generic_component_value_list.into_syntax(), + ))], + )) +} pub fn css_url_function( url_token: SyntaxToken, l_paren_token: SyntaxToken, @@ -1841,6 +1871,26 @@ pub fn css_url_value_raw(value_token: SyntaxToken) -> CssUrlValueRaw { [Some(SyntaxElement::Token(value_token))], )) } +pub fn css_wide_keyword(value_token: SyntaxToken) -> CssWideKeyword { + CssWideKeyword::unwrap_cast(SyntaxNode::new_detached( + CssSyntaxKind::CSS_WIDE_KEYWORD, + [Some(SyntaxElement::Token(value_token))], + )) +} +pub fn css_z_index_property( + name: CssIdentifier, + colon_token: SyntaxToken, + value: AnyCssZIndexPropertyValue, +) -> CssZIndexProperty { + CssZIndexProperty::unwrap_cast(SyntaxNode::new_detached( + CssSyntaxKind::CSS_Z_INDEX_PROPERTY, + [ + Some(SyntaxElement::Node(name.into_syntax())), + Some(SyntaxElement::Token(colon_token)), + Some(SyntaxElement::Node(value.into_syntax())), + ], + )) +} pub fn css_component_value_list(items: I) -> CssComponentValueList where I: IntoIterator, @@ -2265,6 +2315,16 @@ where slots, )) } +pub fn css_bogus_property_value(slots: I) -> CssBogusPropertyValue +where + I: IntoIterator>, + I::IntoIter: ExactSizeIterator, +{ + CssBogusPropertyValue::unwrap_cast(SyntaxNode::new_detached( + CssSyntaxKind::CSS_BOGUS_PROPERTY_VALUE, + slots, + )) +} pub fn css_bogus_pseudo_class(slots: I) -> CssBogusPseudoClass where I: IntoIterator>, diff --git a/crates/biome_css_factory/src/generated/syntax_factory.rs b/crates/biome_css_factory/src/generated/syntax_factory.rs index f30445969a9b..a070a371fd48 100644 --- a/crates/biome_css_factory/src/generated/syntax_factory.rs +++ b/crates/biome_css_factory/src/generated/syntax_factory.rs @@ -24,12 +24,46 @@ impl SyntaxFactory for CssSyntaxFactory { | CSS_BOGUS_PAGE_SELECTOR_PSEUDO | CSS_BOGUS_PARAMETER | CSS_BOGUS_PROPERTY + | CSS_BOGUS_PROPERTY_VALUE | CSS_BOGUS_PSEUDO_CLASS | CSS_BOGUS_PSEUDO_ELEMENT | CSS_BOGUS_RULE | CSS_BOGUS_SCOPE_RANGE | CSS_BOGUS_SELECTOR | CSS_BOGUS_SUB_SELECTOR => RawSyntaxNode::new(kind, children.into_iter().map(Some)), + CSS_ALL_PROPERTY => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<3usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if CssIdentifier::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [:] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if AnyCssAllPropertyValue::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + CSS_ALL_PROPERTY.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(CSS_ALL_PROPERTY, children) + } CSS_AT_RULE => { let mut elements = (&children).into_iter(); let mut slots: RawNodeSlots<2usize> = RawNodeSlots::default(); @@ -177,6 +211,22 @@ impl SyntaxFactory for CssSyntaxFactory { } slots.into_node(CSS_ATTRIBUTE_SELECTOR, children) } + CSS_AUTO => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<1usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if element.kind() == T![auto] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new(CSS_AUTO.to_bogus(), children.into_iter().map(Some)); + } + slots.into_node(CSS_AUTO, children) + } CSS_BINARY_EXPRESSION => { let mut elements = (&children).into_iter(); let mut slots: RawNodeSlots<3usize> = RawNodeSlots::default(); @@ -3663,6 +3713,25 @@ impl SyntaxFactory for CssSyntaxFactory { } slots.into_node(CSS_UNKNOWN_DIMENSION, children) } + CSS_UNKNOWN_PROPERTY_VALUE => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<1usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if CssGenericComponentValueList::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + CSS_UNKNOWN_PROPERTY_VALUE.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(CSS_UNKNOWN_PROPERTY_VALUE, children) + } CSS_URL_FUNCTION => { let mut elements = (&children).into_iter(); let mut slots: RawNodeSlots<4usize> = RawNodeSlots::default(); @@ -3722,6 +3791,66 @@ impl SyntaxFactory for CssSyntaxFactory { } slots.into_node(CSS_URL_VALUE_RAW, children) } + CSS_WIDE_KEYWORD => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<1usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if matches!( + element.kind(), + T![inherit] + | T![initial] + | T![unset] + | T![revert] + | T![revert_layer] + | T![default] + ) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + CSS_WIDE_KEYWORD.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(CSS_WIDE_KEYWORD, children) + } + CSS_Z_INDEX_PROPERTY => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<3usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if CssIdentifier::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [:] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if AnyCssZIndexPropertyValue::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + CSS_Z_INDEX_PROPERTY.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(CSS_Z_INDEX_PROPERTY, children) + } CSS_COMPONENT_VALUE_LIST => { Self::make_node_list_syntax(kind, children, AnyCssValue::can_cast) } diff --git a/crates/biome_css_formatter/src/css/any/all_property_value.rs b/crates/biome_css_formatter/src/css/any/all_property_value.rs new file mode 100644 index 000000000000..72a3e743c9ed --- /dev/null +++ b/crates/biome_css_formatter/src/css/any/all_property_value.rs @@ -0,0 +1,16 @@ +//! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file. + +use crate::prelude::*; +use biome_css_syntax::AnyCssAllPropertyValue; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatAnyCssAllPropertyValue; +impl FormatRule for FormatAnyCssAllPropertyValue { + type Context = CssFormatContext; + fn fmt(&self, node: &AnyCssAllPropertyValue, f: &mut CssFormatter) -> FormatResult<()> { + match node { + AnyCssAllPropertyValue::CssWideKeyword(node) => node.format().fmt(f), + AnyCssAllPropertyValue::CssUnknownPropertyValue(node) => node.format().fmt(f), + AnyCssAllPropertyValue::CssBogusPropertyValue(node) => node.format().fmt(f), + } + } +} diff --git a/crates/biome_css_formatter/src/css/any/mod.rs b/crates/biome_css_formatter/src/css/any/mod.rs index 34b62d602f81..35b4430dbaeb 100644 --- a/crates/biome_css_formatter/src/css/any/mod.rs +++ b/crates/biome_css_formatter/src/css/any/mod.rs @@ -1,5 +1,6 @@ //! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file. +pub(crate) mod all_property_value; pub(crate) mod at_rule; pub(crate) mod attribute_matcher_value; pub(crate) mod compound_selector; @@ -59,3 +60,4 @@ pub(crate) mod supports_in_parens; pub(crate) mod supports_or_combinable_condition; pub(crate) mod url_value; pub(crate) mod value; +pub(crate) mod z_index_property_value; diff --git a/crates/biome_css_formatter/src/css/any/property.rs b/crates/biome_css_formatter/src/css/any/property.rs index 43c9c0e10f83..e2cfac41196d 100644 --- a/crates/biome_css_formatter/src/css/any/property.rs +++ b/crates/biome_css_formatter/src/css/any/property.rs @@ -10,6 +10,8 @@ impl FormatRule for FormatAnyCssProperty { match node { AnyCssProperty::CssGenericProperty(node) => node.format().fmt(f), AnyCssProperty::CssBogusProperty(node) => node.format().fmt(f), + AnyCssProperty::CssAllProperty(node) => node.format().fmt(f), + AnyCssProperty::CssZIndexProperty(node) => node.format().fmt(f), } } } diff --git a/crates/biome_css_formatter/src/css/any/z_index_property_value.rs b/crates/biome_css_formatter/src/css/any/z_index_property_value.rs new file mode 100644 index 000000000000..cfb05ba152fb --- /dev/null +++ b/crates/biome_css_formatter/src/css/any/z_index_property_value.rs @@ -0,0 +1,18 @@ +//! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file. + +use crate::prelude::*; +use biome_css_syntax::AnyCssZIndexPropertyValue; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatAnyCssZIndexPropertyValue; +impl FormatRule for FormatAnyCssZIndexPropertyValue { + type Context = CssFormatContext; + fn fmt(&self, node: &AnyCssZIndexPropertyValue, f: &mut CssFormatter) -> FormatResult<()> { + match node { + AnyCssZIndexPropertyValue::CssAuto(node) => node.format().fmt(f), + AnyCssZIndexPropertyValue::CssNumber(node) => node.format().fmt(f), + AnyCssZIndexPropertyValue::CssWideKeyword(node) => node.format().fmt(f), + AnyCssZIndexPropertyValue::CssUnknownPropertyValue(node) => node.format().fmt(f), + AnyCssZIndexPropertyValue::CssBogusPropertyValue(node) => node.format().fmt(f), + } + } +} diff --git a/crates/biome_css_formatter/src/css/auxiliary/auto.rs b/crates/biome_css_formatter/src/css/auxiliary/auto.rs new file mode 100644 index 000000000000..bda03c4f8fca --- /dev/null +++ b/crates/biome_css_formatter/src/css/auxiliary/auto.rs @@ -0,0 +1,13 @@ +use crate::prelude::*; +use biome_css_syntax::{CssAuto, CssAutoFields}; +use biome_formatter::write; + +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatCssAuto; +impl FormatNodeRule for FormatCssAuto { + fn fmt_fields(&self, node: &CssAuto, f: &mut CssFormatter) -> FormatResult<()> { + let CssAutoFields { value_token } = node.as_fields(); + + write!(f, [value_token.format()]) + } +} diff --git a/crates/biome_css_formatter/src/css/auxiliary/generic_delimiter.rs b/crates/biome_css_formatter/src/css/auxiliary/generic_delimiter.rs index 1c72e21ab4b9..bfffa5146df3 100644 --- a/crates/biome_css_formatter/src/css/auxiliary/generic_delimiter.rs +++ b/crates/biome_css_formatter/src/css/auxiliary/generic_delimiter.rs @@ -1,10 +1,13 @@ use crate::prelude::*; -use biome_css_syntax::CssGenericDelimiter; -use biome_rowan::AstNode; +use biome_css_syntax::{CssGenericDelimiter, CssGenericDelimiterFields}; +use biome_formatter::write; + #[derive(Debug, Clone, Default)] pub(crate) struct FormatCssGenericDelimiter; impl FormatNodeRule for FormatCssGenericDelimiter { fn fmt_fields(&self, node: &CssGenericDelimiter, f: &mut CssFormatter) -> FormatResult<()> { - format_verbatim_node(node.syntax()).fmt(f) + let CssGenericDelimiterFields { value } = node.as_fields(); + + write!(f, [value.format()]) } } diff --git a/crates/biome_css_formatter/src/css/auxiliary/mod.rs b/crates/biome_css_formatter/src/css/auxiliary/mod.rs index 0e52ffad14c6..9f49bf035216 100644 --- a/crates/biome_css_formatter/src/css/auxiliary/mod.rs +++ b/crates/biome_css_formatter/src/css/auxiliary/mod.rs @@ -3,6 +3,7 @@ pub(crate) mod attribute_matcher; pub(crate) mod attribute_matcher_value; pub(crate) mod attribute_name; +pub(crate) mod auto; pub(crate) mod binary_expression; pub(crate) mod container_and_query; pub(crate) mod container_not_query; @@ -63,4 +64,6 @@ pub(crate) mod supports_feature_declaration; pub(crate) mod supports_not_condition; pub(crate) mod supports_or_condition; pub(crate) mod universal_namespace_prefix; +pub(crate) mod unknown_property_value; pub(crate) mod url_function; +pub(crate) mod wide_keyword; diff --git a/crates/biome_css_formatter/src/css/auxiliary/unknown_property_value.rs b/crates/biome_css_formatter/src/css/auxiliary/unknown_property_value.rs new file mode 100644 index 000000000000..b56f9d9185fc --- /dev/null +++ b/crates/biome_css_formatter/src/css/auxiliary/unknown_property_value.rs @@ -0,0 +1,15 @@ +use crate::prelude::*; +use biome_css_syntax::{CssUnknownPropertyValue, CssUnknownPropertyValueFields}; +use biome_formatter::write; + +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatCssUnknownPropertyValue; +impl FormatNodeRule for FormatCssUnknownPropertyValue { + fn fmt_fields(&self, node: &CssUnknownPropertyValue, f: &mut CssFormatter) -> FormatResult<()> { + let CssUnknownPropertyValueFields { + css_generic_component_value_list, + } = node.as_fields(); + + write!(f, [css_generic_component_value_list.format()]) + } +} diff --git a/crates/biome_css_formatter/src/css/auxiliary/wide_keyword.rs b/crates/biome_css_formatter/src/css/auxiliary/wide_keyword.rs new file mode 100644 index 000000000000..8762af2f53af --- /dev/null +++ b/crates/biome_css_formatter/src/css/auxiliary/wide_keyword.rs @@ -0,0 +1,13 @@ +use crate::prelude::*; +use biome_css_syntax::{CssWideKeyword, CssWideKeywordFields}; +use biome_formatter::write; + +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatCssWideKeyword; +impl FormatNodeRule for FormatCssWideKeyword { + fn fmt_fields(&self, node: &CssWideKeyword, f: &mut CssFormatter) -> FormatResult<()> { + let CssWideKeywordFields { value } = node.as_fields(); + + write!(f, [value.format()]) + } +} diff --git a/crates/biome_css_formatter/src/css/bogus/bogus_property_value.rs b/crates/biome_css_formatter/src/css/bogus/bogus_property_value.rs new file mode 100644 index 000000000000..1bef2b2d71a6 --- /dev/null +++ b/crates/biome_css_formatter/src/css/bogus/bogus_property_value.rs @@ -0,0 +1,5 @@ +use crate::FormatBogusNodeRule; +use biome_css_syntax::CssBogusPropertyValue; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatCssBogusPropertyValue; +impl FormatBogusNodeRule for FormatCssBogusPropertyValue {} diff --git a/crates/biome_css_formatter/src/css/bogus/mod.rs b/crates/biome_css_formatter/src/css/bogus/mod.rs index a274e49083c7..2c0a28445366 100644 --- a/crates/biome_css_formatter/src/css/bogus/mod.rs +++ b/crates/biome_css_formatter/src/css/bogus/mod.rs @@ -11,6 +11,7 @@ pub(crate) mod bogus_media_query; pub(crate) mod bogus_page_selector_pseudo; pub(crate) mod bogus_parameter; pub(crate) mod bogus_property; +pub(crate) mod bogus_property_value; pub(crate) mod bogus_pseudo_class; pub(crate) mod bogus_pseudo_element; pub(crate) mod bogus_rule; diff --git a/crates/biome_css_formatter/src/css/properties/all_property.rs b/crates/biome_css_formatter/src/css/properties/all_property.rs new file mode 100644 index 000000000000..7acee8b51436 --- /dev/null +++ b/crates/biome_css_formatter/src/css/properties/all_property.rs @@ -0,0 +1,20 @@ +use crate::prelude::*; +use biome_css_syntax::{CssAllProperty, CssAllPropertyFields}; +use biome_formatter::write; + +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatCssAllProperty; +impl FormatNodeRule for FormatCssAllProperty { + fn fmt_fields(&self, node: &CssAllProperty, f: &mut CssFormatter) -> FormatResult<()> { + let CssAllPropertyFields { + name, + colon_token, + value, + } = node.as_fields(); + + write!( + f, + [name.format(), colon_token.format(), space(), value.format()] + ) + } +} diff --git a/crates/biome_css_formatter/src/css/properties/mod.rs b/crates/biome_css_formatter/src/css/properties/mod.rs index cdad64da9ef9..d88cca43e616 100644 --- a/crates/biome_css_formatter/src/css/properties/mod.rs +++ b/crates/biome_css_formatter/src/css/properties/mod.rs @@ -1,3 +1,5 @@ //! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file. +pub(crate) mod all_property; pub(crate) mod generic_property; +pub(crate) mod z_index_property; diff --git a/crates/biome_css_formatter/src/css/properties/z_index_property.rs b/crates/biome_css_formatter/src/css/properties/z_index_property.rs new file mode 100644 index 000000000000..85db2abec504 --- /dev/null +++ b/crates/biome_css_formatter/src/css/properties/z_index_property.rs @@ -0,0 +1,20 @@ +use crate::prelude::*; +use biome_css_syntax::{CssZIndexProperty, CssZIndexPropertyFields}; +use biome_formatter::write; + +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatCssZIndexProperty; +impl FormatNodeRule for FormatCssZIndexProperty { + fn fmt_fields(&self, node: &CssZIndexProperty, f: &mut CssFormatter) -> FormatResult<()> { + let CssZIndexPropertyFields { + name, + colon_token, + value, + } = node.as_fields(); + + write!( + f, + [name.format(), colon_token.format(), space(), value.format()] + ) + } +} diff --git a/crates/biome_css_formatter/src/generated.rs b/crates/biome_css_formatter/src/generated.rs index 8391e59954b5..2cd7ee16974c 100644 --- a/crates/biome_css_formatter/src/generated.rs +++ b/crates/biome_css_formatter/src/generated.rs @@ -1647,6 +1647,192 @@ impl IntoFormat for biome_css_syntax::CssGenericProperty { ) } } +impl FormatRule + for crate::css::properties::all_property::FormatCssAllProperty +{ + type Context = CssFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_css_syntax::CssAllProperty, + f: &mut CssFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_css_syntax::CssAllProperty { + type Format<'a> = FormatRefWithRule< + 'a, + biome_css_syntax::CssAllProperty, + crate::css::properties::all_property::FormatCssAllProperty, + >; + fn format(&self) -> Self::Format<'_> { + #![allow(clippy::default_constructed_unit_structs)] + FormatRefWithRule::new( + self, + crate::css::properties::all_property::FormatCssAllProperty::default(), + ) + } +} +impl IntoFormat for biome_css_syntax::CssAllProperty { + type Format = FormatOwnedWithRule< + biome_css_syntax::CssAllProperty, + crate::css::properties::all_property::FormatCssAllProperty, + >; + fn into_format(self) -> Self::Format { + #![allow(clippy::default_constructed_unit_structs)] + FormatOwnedWithRule::new( + self, + crate::css::properties::all_property::FormatCssAllProperty::default(), + ) + } +} +impl FormatRule + for crate::css::properties::z_index_property::FormatCssZIndexProperty +{ + type Context = CssFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_css_syntax::CssZIndexProperty, + f: &mut CssFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_css_syntax::CssZIndexProperty { + type Format<'a> = FormatRefWithRule< + 'a, + biome_css_syntax::CssZIndexProperty, + crate::css::properties::z_index_property::FormatCssZIndexProperty, + >; + fn format(&self) -> Self::Format<'_> { + #![allow(clippy::default_constructed_unit_structs)] + FormatRefWithRule::new( + self, + crate::css::properties::z_index_property::FormatCssZIndexProperty::default(), + ) + } +} +impl IntoFormat for biome_css_syntax::CssZIndexProperty { + type Format = FormatOwnedWithRule< + biome_css_syntax::CssZIndexProperty, + crate::css::properties::z_index_property::FormatCssZIndexProperty, + >; + fn into_format(self) -> Self::Format { + #![allow(clippy::default_constructed_unit_structs)] + FormatOwnedWithRule::new( + self, + crate::css::properties::z_index_property::FormatCssZIndexProperty::default(), + ) + } +} +impl FormatRule + for crate::css::auxiliary::wide_keyword::FormatCssWideKeyword +{ + type Context = CssFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_css_syntax::CssWideKeyword, + f: &mut CssFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_css_syntax::CssWideKeyword { + type Format<'a> = FormatRefWithRule< + 'a, + biome_css_syntax::CssWideKeyword, + crate::css::auxiliary::wide_keyword::FormatCssWideKeyword, + >; + fn format(&self) -> Self::Format<'_> { + #![allow(clippy::default_constructed_unit_structs)] + FormatRefWithRule::new( + self, + crate::css::auxiliary::wide_keyword::FormatCssWideKeyword::default(), + ) + } +} +impl IntoFormat for biome_css_syntax::CssWideKeyword { + type Format = FormatOwnedWithRule< + biome_css_syntax::CssWideKeyword, + crate::css::auxiliary::wide_keyword::FormatCssWideKeyword, + >; + fn into_format(self) -> Self::Format { + #![allow(clippy::default_constructed_unit_structs)] + FormatOwnedWithRule::new( + self, + crate::css::auxiliary::wide_keyword::FormatCssWideKeyword::default(), + ) + } +} +impl FormatRule for crate::css::auxiliary::auto::FormatCssAuto { + type Context = CssFormatContext; + #[inline(always)] + fn fmt(&self, node: &biome_css_syntax::CssAuto, f: &mut CssFormatter) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_css_syntax::CssAuto { + type Format<'a> = FormatRefWithRule< + 'a, + biome_css_syntax::CssAuto, + crate::css::auxiliary::auto::FormatCssAuto, + >; + fn format(&self) -> Self::Format<'_> { + #![allow(clippy::default_constructed_unit_structs)] + FormatRefWithRule::new(self, crate::css::auxiliary::auto::FormatCssAuto::default()) + } +} +impl IntoFormat for biome_css_syntax::CssAuto { + type Format = + FormatOwnedWithRule; + fn into_format(self) -> Self::Format { + #![allow(clippy::default_constructed_unit_structs)] + FormatOwnedWithRule::new(self, crate::css::auxiliary::auto::FormatCssAuto::default()) + } +} +impl FormatRule + for crate::css::auxiliary::unknown_property_value::FormatCssUnknownPropertyValue +{ + type Context = CssFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_css_syntax::CssUnknownPropertyValue, + f: &mut CssFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_css_syntax::CssUnknownPropertyValue { + type Format<'a> = FormatRefWithRule< + 'a, + biome_css_syntax::CssUnknownPropertyValue, + crate::css::auxiliary::unknown_property_value::FormatCssUnknownPropertyValue, + >; + fn format(&self) -> Self::Format<'_> { + #![allow(clippy::default_constructed_unit_structs)] + FormatRefWithRule::new( + self, + crate::css::auxiliary::unknown_property_value::FormatCssUnknownPropertyValue::default(), + ) + } +} +impl IntoFormat for biome_css_syntax::CssUnknownPropertyValue { + type Format = FormatOwnedWithRule< + biome_css_syntax::CssUnknownPropertyValue, + crate::css::auxiliary::unknown_property_value::FormatCssUnknownPropertyValue, + >; + fn into_format(self) -> Self::Format { + #![allow(clippy::default_constructed_unit_structs)] + FormatOwnedWithRule::new( + self, + crate::css::auxiliary::unknown_property_value::FormatCssUnknownPropertyValue::default(), + ) + } +} impl FormatRule for crate::css::auxiliary::generic_delimiter::FormatCssGenericDelimiter { @@ -5560,6 +5746,46 @@ impl IntoFormat for biome_css_syntax::CssBogusProperty { ) } } +impl FormatRule + for crate::css::bogus::bogus_property_value::FormatCssBogusPropertyValue +{ + type Context = CssFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &biome_css_syntax::CssBogusPropertyValue, + f: &mut CssFormatter, + ) -> FormatResult<()> { + FormatBogusNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for biome_css_syntax::CssBogusPropertyValue { + type Format<'a> = FormatRefWithRule< + 'a, + biome_css_syntax::CssBogusPropertyValue, + crate::css::bogus::bogus_property_value::FormatCssBogusPropertyValue, + >; + fn format(&self) -> Self::Format<'_> { + #![allow(clippy::default_constructed_unit_structs)] + FormatRefWithRule::new( + self, + crate::css::bogus::bogus_property_value::FormatCssBogusPropertyValue::default(), + ) + } +} +impl IntoFormat for biome_css_syntax::CssBogusPropertyValue { + type Format = FormatOwnedWithRule< + biome_css_syntax::CssBogusPropertyValue, + crate::css::bogus::bogus_property_value::FormatCssBogusPropertyValue, + >; + fn into_format(self) -> Self::Format { + #![allow(clippy::default_constructed_unit_structs)] + FormatOwnedWithRule::new( + self, + crate::css::bogus::bogus_property_value::FormatCssBogusPropertyValue::default(), + ) + } +} impl AsFormat for biome_css_syntax::AnyCssRule { type Format<'a> = FormatRefWithRule< 'a, @@ -6013,6 +6239,60 @@ impl IntoFormat for biome_css_syntax::AnyCssProperty { ) } } +impl AsFormat for biome_css_syntax::AnyCssAllPropertyValue { + type Format<'a> = FormatRefWithRule< + 'a, + biome_css_syntax::AnyCssAllPropertyValue, + crate::css::any::all_property_value::FormatAnyCssAllPropertyValue, + >; + fn format(&self) -> Self::Format<'_> { + #![allow(clippy::default_constructed_unit_structs)] + FormatRefWithRule::new( + self, + crate::css::any::all_property_value::FormatAnyCssAllPropertyValue::default(), + ) + } +} +impl IntoFormat for biome_css_syntax::AnyCssAllPropertyValue { + type Format = FormatOwnedWithRule< + biome_css_syntax::AnyCssAllPropertyValue, + crate::css::any::all_property_value::FormatAnyCssAllPropertyValue, + >; + fn into_format(self) -> Self::Format { + #![allow(clippy::default_constructed_unit_structs)] + FormatOwnedWithRule::new( + self, + crate::css::any::all_property_value::FormatAnyCssAllPropertyValue::default(), + ) + } +} +impl AsFormat for biome_css_syntax::AnyCssZIndexPropertyValue { + type Format<'a> = FormatRefWithRule< + 'a, + biome_css_syntax::AnyCssZIndexPropertyValue, + crate::css::any::z_index_property_value::FormatAnyCssZIndexPropertyValue, + >; + fn format(&self) -> Self::Format<'_> { + #![allow(clippy::default_constructed_unit_structs)] + FormatRefWithRule::new( + self, + crate::css::any::z_index_property_value::FormatAnyCssZIndexPropertyValue::default(), + ) + } +} +impl IntoFormat for biome_css_syntax::AnyCssZIndexPropertyValue { + type Format = FormatOwnedWithRule< + biome_css_syntax::AnyCssZIndexPropertyValue, + crate::css::any::z_index_property_value::FormatAnyCssZIndexPropertyValue, + >; + fn into_format(self) -> Self::Format { + #![allow(clippy::default_constructed_unit_structs)] + FormatOwnedWithRule::new( + self, + crate::css::any::z_index_property_value::FormatAnyCssZIndexPropertyValue::default(), + ) + } +} impl AsFormat for biome_css_syntax::AnyCssDeclarationName { type Format<'a> = FormatRefWithRule< 'a, diff --git a/crates/biome_css_formatter/tests/specs/css/atrule/font_face.css.snap b/crates/biome_css_formatter/tests/specs/css/atrule/font_face.css.snap index fbb215557663..d551818ed647 100644 --- a/crates/biome_css_formatter/tests/specs/css/atrule/font_face.css.snap +++ b/crates/biome_css_formatter/tests/specs/css/atrule/font_face.css.snap @@ -147,13 +147,3 @@ Quote style: Double Quotes ``` - -## Unimplemented nodes/tokens - -" " => 106..107 -" " => 279..280 -" " => 452..453 -" " => 625..626 -" ," => 798..800 -" ,\n" => 972..975 - diff --git a/crates/biome_css_formatter/tests/specs/css/properties/all.css b/crates/biome_css_formatter/tests/specs/css/properties/all.css new file mode 100644 index 000000000000..e01a0b4573c8 --- /dev/null +++ b/crates/biome_css_formatter/tests/specs/css/properties/all.css @@ -0,0 +1,12 @@ +div { + all: InItial; + all : inherIT; + all + : + revert-layer + ; + + all : unknown-value ; + all : a, + value list ; +} \ No newline at end of file diff --git a/crates/biome_css_formatter/tests/specs/css/properties/all.css.snap b/crates/biome_css_formatter/tests/specs/css/properties/all.css.snap new file mode 100644 index 000000000000..7063948187b7 --- /dev/null +++ b/crates/biome_css_formatter/tests/specs/css/properties/all.css.snap @@ -0,0 +1,49 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: css/properties/all.css +--- + +# Input + +```css +div { + all: InItial; + all : inherIT; + all + : + revert-layer + ; + + all : unknown-value ; + all : a, + value list ; +} +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Quote style: Double Quotes +----- + +```css +div { + all: initial; + all: inherit; + all: revert-layer; + + all: unknown-value; + all: a , value list; +} +``` + + diff --git a/crates/biome_css_formatter/tests/specs/css/properties/custom.css b/crates/biome_css_formatter/tests/specs/css/properties/custom.css new file mode 100644 index 000000000000..35720af8727e --- /dev/null +++ b/crates/biome_css_formatter/tests/specs/css/properties/custom.css @@ -0,0 +1,16 @@ +div { + /* Custom property, always generic */ + --custom-property + : + one-value ; + --custom-property: multiple + values; + --custom-property: delimited + , values + ; + --custom-property : + delimited / slash / values; + --custom-property: mixed, delimiters/can be , + used + ; +} \ No newline at end of file diff --git a/crates/biome_css_formatter/tests/specs/css/properties/custom.css.snap b/crates/biome_css_formatter/tests/specs/css/properties/custom.css.snap new file mode 100644 index 000000000000..272bebc74f7e --- /dev/null +++ b/crates/biome_css_formatter/tests/specs/css/properties/custom.css.snap @@ -0,0 +1,53 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: css/properties/custom.css +--- + +# Input + +```css +div { + /* Custom property, always generic */ + --custom-property + : + one-value ; + --custom-property: multiple + values; + --custom-property: delimited + , values + ; + --custom-property : + delimited / slash / values; + --custom-property: mixed, delimiters/can be , + used + ; +} +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Quote style: Double Quotes +----- + +```css +div { + /* Custom property, always generic */ + --custom-property: one-value; + --custom-property: multiple values; + --custom-property: delimited , values; + --custom-property: delimited / slash / values; + --custom-property: mixed , delimiters / can be , used; +} +``` + + diff --git a/crates/biome_css_formatter/tests/specs/css/properties/generic.css b/crates/biome_css_formatter/tests/specs/css/properties/generic.css new file mode 100644 index 000000000000..ea598bc65565 --- /dev/null +++ b/crates/biome_css_formatter/tests/specs/css/properties/generic.css @@ -0,0 +1,16 @@ +div { + /* Custom property, always generic */ + unknown-property + : + one-value ; + unknown-property: multiple + values; + unknown-property: delimited + , values + ; + unknown-property : + delimited / slash / values; + unknown-property: mixed, delimiters/can be , + used + ; +} \ No newline at end of file diff --git a/crates/biome_css_formatter/tests/specs/css/properties/generic.css.snap b/crates/biome_css_formatter/tests/specs/css/properties/generic.css.snap new file mode 100644 index 000000000000..59e8fbfee097 --- /dev/null +++ b/crates/biome_css_formatter/tests/specs/css/properties/generic.css.snap @@ -0,0 +1,53 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: css/properties/generic.css +--- + +# Input + +```css +div { + /* Custom property, always generic */ + unknown-property + : + one-value ; + unknown-property: multiple + values; + unknown-property: delimited + , values + ; + unknown-property : + delimited / slash / values; + unknown-property: mixed, delimiters/can be , + used + ; +} +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Quote style: Double Quotes +----- + +```css +div { + /* Custom property, always generic */ + unknown-property: one-value; + unknown-property: multiple values; + unknown-property: delimited , values; + unknown-property: delimited / slash / values; + unknown-property: mixed , delimiters / can be , used; +} +``` + + diff --git a/crates/biome_css_formatter/tests/specs/css/properties/z-index.css b/crates/biome_css_formatter/tests/specs/css/properties/z-index.css new file mode 100644 index 000000000000..333ecd3a40cd --- /dev/null +++ b/crates/biome_css_formatter/tests/specs/css/properties/z-index.css @@ -0,0 +1,13 @@ +div { + z-index : INherit + + ; + + z-index + : + Auto ; + + z-index : -44; + z-index: 0 ; + z-index: 1 ; +} \ No newline at end of file diff --git a/crates/biome_css_formatter/tests/specs/css/properties/z-index.css.snap b/crates/biome_css_formatter/tests/specs/css/properties/z-index.css.snap new file mode 100644 index 000000000000..e1ab1fbf82c9 --- /dev/null +++ b/crates/biome_css_formatter/tests/specs/css/properties/z-index.css.snap @@ -0,0 +1,51 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: css/properties/z-index.css +--- + +# Input + +```css +div { + z-index : INherit + + ; + + z-index + : + Auto ; + + z-index : -44; + z-index: 0 ; + z-index: 1 ; +} +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Quote style: Double Quotes +----- + +```css +div { + z-index: inherit; + + z-index: auto; + + z-index: -44; + z-index: 0; + z-index: 1; +} +``` + + diff --git a/crates/biome_css_parser/src/lexer/mod.rs b/crates/biome_css_parser/src/lexer/mod.rs index 9708f0d36e7d..c7fd35d134f5 100644 --- a/crates/biome_css_parser/src/lexer/mod.rs +++ b/crates/biome_css_parser/src/lexer/mod.rs @@ -862,6 +862,7 @@ impl<'src> CssLexer<'src> { b"style" => STYLE_KW, b"font-face" => FONT_FACE_KW, b"font-palette-values" => FONT_PALETTE_VALUES_KW, + b"auto" => AUTO_KW, // CSS-Wide keywords b"initial" => INITIAL_KW, b"inherit" => INHERIT_KW, diff --git a/crates/biome_css_parser/src/syntax/mod.rs b/crates/biome_css_parser/src/syntax/mod.rs index b1b43a795b74..c216f1199c64 100644 --- a/crates/biome_css_parser/src/syntax/mod.rs +++ b/crates/biome_css_parser/src/syntax/mod.rs @@ -606,11 +606,28 @@ fn is_at_string(p: &mut CssParser) -> bool { p.at(CSS_STRING_LITERAL) } +#[inline] +pub(crate) fn parse_css_auto(p: &mut CssParser) -> ParsedSyntax { + if !is_at_css_auto(p) { + return Absent; + } + + let m = p.start(); + + p.bump(AUTO_KW); + + Present(m.complete(p, CSS_AUTO)) +} + +fn is_at_css_auto(p: &mut CssParser) -> bool { + p.at(AUTO_KW) +} + /// Attempt to parse some input with the given parsing function. If parsing /// succeeds, `Ok` is returned with the result of the parse and the state is /// preserved. If parsing fails, this function rewinds the parser back to /// where it was before attempting the parse and the `Err` value is returned. -#[allow(dead_code)] // TODO: Remove this allow once it's actually used +#[must_use = "The result of try_parse contains information about whether the parse succeeded and should not be ignored"] pub(crate) fn try_parse( p: &mut CssParser, func: impl FnOnce(&mut CssParser) -> Result, diff --git a/crates/biome_css_parser/src/syntax/property/all.rs b/crates/biome_css_parser/src/syntax/property/all.rs new file mode 100644 index 000000000000..d4d3fb5a8e39 --- /dev/null +++ b/crates/biome_css_parser/src/syntax/property/all.rs @@ -0,0 +1,35 @@ +use crate::parser::CssParser; +use crate::syntax::parse_regular_identifier; +use biome_css_syntax::{CssSyntaxKind::*, T}; +use biome_parser::prelude::ParsedSyntax::Present; +use biome_parser::prelude::*; + +use super::parse_any_implicit_property_value; + +/// https://drafts.csswg.org/css-cascade/#all-shorthand +/// +/// ```ebnf +/// all = +/// initial | +/// inherit | +/// unset | +/// revert +/// ``` +/// +/// The only valid values are `CssWideKeyword`s. The gramamr doesn't include +/// all of them because some are still drafts (`revert-layer`) or have been +/// renamed (`default` -> `revert`). +#[inline] +pub(crate) fn parse_all_property(p: &mut CssParser) -> ParsedSyntax { + // Assumes the parent has confirmed we're at the `all` identifier. + let m = p.start(); + parse_regular_identifier(p).ok(); + p.expect(T![:]); + + // The `all` property _only_ accepts keyword values as valid input, so we + // can skip `parse_property_value_with_fallbacks`, since it will just + // re-check the same case. + parse_any_implicit_property_value(p).ok(); + + Present(m.complete(p, CSS_ALL_PROPERTY)) +} diff --git a/crates/biome_css_parser/src/syntax/property/mod.rs b/crates/biome_css_parser/src/syntax/property/mod.rs index 9bb44a39458c..ed36385cef82 100644 --- a/crates/biome_css_parser/src/syntax/property/mod.rs +++ b/crates/biome_css_parser/src/syntax/property/mod.rs @@ -1,6 +1,11 @@ +mod all; +mod z_index; + use crate::parser::CssParser; use crate::syntax::parse_error::expected_component_value; -use crate::syntax::{is_at_any_value, is_at_identifier, parse_any_value, parse_regular_identifier}; +use crate::syntax::{ + is_at_any_value, is_at_identifier, parse_any_value, parse_regular_identifier, try_parse, +}; use biome_css_syntax::CssSyntaxKind::*; use biome_css_syntax::{CssSyntaxKind, T}; use biome_parser::parse_lists::ParseNodeList; @@ -9,6 +14,9 @@ use biome_parser::prelude::ParsedSyntax; use biome_parser::prelude::ParsedSyntax::{Absent, Present}; use biome_parser::{token_set, Parser, TokenSet}; +use self::all::parse_all_property; +use self::z_index::parse_z_index_property; + pub(crate) fn is_at_any_property(p: &mut CssParser) -> bool { is_at_generic_property(p) } @@ -18,10 +26,10 @@ pub(crate) fn parse_any_property(p: &mut CssParser) -> ParsedSyntax { return Absent; } - if is_at_generic_property(p) { - parse_generic_property(p) - } else { - Absent + match p.cur_text() { + "all" => parse_all_property(p), + "z-index" => parse_z_index_property(p), + _ => parse_generic_property(p), } } @@ -46,6 +54,122 @@ pub(crate) fn parse_generic_property(p: &mut CssParser) -> ParsedSyntax { Present(m.complete(p, CSS_GENERIC_PROPERTY)) } +/// Attempt to parse the value of a property using the provided parse function. +/// If the parsing succeeds, then check if the entire value definition has been +/// consumed. If it has, return the parsed content as the value for the +/// property. If more content remains, then rewind and re-parse the value +/// definition as either a CSS-wide keyword value (like `width: unset;`), or +/// fallback to a generic component value list otherwise. +/// +/// This function is guaranteed to return Present syntax, handling all cases +/// including Bogus values. See [parse_any_implicit_property_value] for more +/// information. +/// +/// ```rust,ignore +/// /// This function parses a property with the defined grammar of: +/// /// my_property : | +/// /// `parse_property_value_with_fallbacks` takes care of handling syntax +/// /// errors, invalid values, and css-wide keyword values. +/// fn parse_my_property(p: &mut CssParser) -> ParsedSyntax { +/// let m = p.start(); +/// parse_regular_identifer(p).ok(); +/// p.expect(T![:]) +/// +/// parse_property_value_with_fallbacks(p, |p| { +/// parse_length(p).or_else(|| parse_percentage(p)) +/// }).ok(); +/// +/// Present(m.complete(p, CSS_MY_PROPERTY)) +/// } +/// ``` +#[inline] +pub(crate) fn parse_property_value_with_fallbacks( + p: &mut CssParser, + func: impl FnOnce(&mut CssParser) -> ParsedSyntax, +) -> ParsedSyntax { + let result = try_parse(p, |p| { + let parsed = func(p); + + if parsed.is_present() && is_at_end_of_property_value(p) { + return Ok(parsed); + } + + Err(()) + }); + + match result { + Ok(parsed) => parsed, + Err(_) => parse_any_implicit_property_value(p), + } +} + +/// Parse any property value other than what is explicitly defined in the formal syntax grammar +/// for that property. It is guaranteed to always return `Present`, as it handles Bogus nodes +/// internally. This includes: +/// - Any of the CSS-wide keywords, which are implicitly part of all property value definitions. +/// These become a `CssWideKeyword` node and are valid as children. +/// - Any syntactically-correct value list that does _not_ match the explicit grammar for the +/// node, which become `CssUnknownPropertyValue` (a wrapper around `CssGenericComponentValueList`). +/// - Syntactically-_incorrect_ values, which become `CssBogusPropertyValue`. +/// +/// This function is automatically called when using [parse_property_value_with_fallbacks] to +/// guarantee that a value is always fully parsed and consumed. +pub(crate) fn parse_any_implicit_property_value(p: &mut CssParser) -> ParsedSyntax { + // Attempt to parse a single keyword value as a valid definition. + let keyword_result = try_parse(p, |p| { + let parsed = parse_css_wide_keyword(p); + if is_at_end_of_property_value(p) { + return Ok(parsed); + } + + Err(()) + }); + + if let Ok(parsed) = keyword_result { + return parsed; + } + + // If the keyword value didn't fully consume the value, then fallback to + // parsing a generic value list. + let m = p.start(); + GenericComponentValueList.parse_list(p); + Present(m.complete(p, CSS_UNKNOWN_PROPERTY_VALUE)) +} + +const CSS_WIDE_KEYWORD_TOKEN_SET: TokenSet = token_set![ + T![initial], + T![inherit], + T![unset], + T![revert], + T![revert_layer], + T![default] +]; + +/// Parse any of the CSS-wide keywords to be used as a property value. +pub(crate) fn parse_css_wide_keyword(p: &mut CssParser) -> ParsedSyntax { + if !p.at_ts(CSS_WIDE_KEYWORD_TOKEN_SET) { + return Absent; + } + + let m = p.start(); + p.bump_any(); + Present(m.complete(p, CSS_WIDE_KEYWORD)) +} + +const CSS_END_OF_PROPERTY_VALUE_TOKEN_SET: TokenSet = token_set!(T!['}'], T![;]); + +/// Returns true if the parser has reached the end of what should be considered +/// the value for a property. This is used to ensure that all expected values +/// are reached (i.e., by looping until this condition is `false`), and that no +/// extranneous values come after the parsed content (i.e., by checking for this +/// condition at the end of successfully parsing a property value). +/// +/// A property value definition ends when either a `;` is reached, which ends +/// the declaration, or a `}` is reached, which ends the declaration _list_. +pub(crate) fn is_at_end_of_property_value(p: &mut CssParser) -> bool { + p.at_ts(CSS_END_OF_PROPERTY_VALUE_TOKEN_SET) +} + pub(crate) struct GenericComponentValueList; impl ParseNodeList for GenericComponentValueList { @@ -58,7 +182,7 @@ impl ParseNodeList for GenericComponentValueList { } fn is_at_list_end(&self, p: &mut Self::Parser<'_>) -> bool { - !is_at_genetic_component_value(p) + !is_at_generic_component_value(p) } fn recover( @@ -68,20 +192,23 @@ impl ParseNodeList for GenericComponentValueList { ) -> RecoveryResult { parsed_element.or_recover_with_token_set( p, - &ParseRecoveryTokenSet::new(CSS_BOGUS, token_set!(T!['}'], T![;])), + &ParseRecoveryTokenSet::new( + CSS_BOGUS_PROPERTY_VALUE, + CSS_END_OF_PROPERTY_VALUE_TOKEN_SET, + ), expected_component_value, ) } } #[inline] -pub(crate) fn is_at_genetic_component_value(p: &mut CssParser) -> bool { +pub(crate) fn is_at_generic_component_value(p: &mut CssParser) -> bool { is_at_any_value(p) || is_at_generic_delimiter(p) } #[inline] pub(crate) fn parse_generic_component_value(p: &mut CssParser) -> ParsedSyntax { - if !is_at_genetic_component_value(p) { + if !is_at_generic_component_value(p) { return Absent; } diff --git a/crates/biome_css_parser/src/syntax/property/z_index.rs b/crates/biome_css_parser/src/syntax/property/z_index.rs new file mode 100644 index 000000000000..9da46ef12e92 --- /dev/null +++ b/crates/biome_css_parser/src/syntax/property/z_index.rs @@ -0,0 +1,32 @@ +use crate::parser::CssParser; +use crate::syntax::{parse_css_auto, parse_regular_identifier, parse_regular_number}; +use biome_css_syntax::{CssSyntaxKind::*, T}; +use biome_parser::prelude::ParsedSyntax::Present; +use biome_parser::prelude::*; + +use super::parse_property_value_with_fallbacks; + +/// https://drafts.csswg.org/css2/#z-index +/// +/// ```ebnf +/// z-index = +/// auto | +/// | +/// inherit +/// ``` +/// +/// `inherit` is covered by the `CssWideKeyword` set. +#[inline] +pub(crate) fn parse_z_index_property(p: &mut CssParser) -> ParsedSyntax { + // Assumes the parent has confirmed we're at the `z-index` identifier. + let m = p.start(); + parse_regular_identifier(p).ok(); + p.expect(T![:]); + + parse_property_value_with_fallbacks(p, |p| { + parse_css_auto(p).or_else(|| parse_regular_number(p)) + }) + .ok(); + + Present(m.complete(p, CSS_Z_INDEX_PROPERTY)) +} diff --git a/crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css b/crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css new file mode 100644 index 000000000000..4b53048601ee --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css @@ -0,0 +1,5 @@ +div { + unknown: calc(; + width: calc(; + --custom: calc(; +} \ No newline at end of file diff --git a/crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css.snap new file mode 100644 index 000000000000..f3a83237529e --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css.snap @@ -0,0 +1,185 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- + +## Input + +```css +div { + unknown: calc(; + width: calc(; + --custom: calc(; +} +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selector_token: missing (optional), + simple_selector: CssTypeSelector { + namespace: missing (optional), + ident: CssIdentifier { + value_token: IDENT@0..4 "div" [] [Whitespace(" ")], + }, + }, + sub_selectors: CssSubSelectorList [], + }, + ], + block: CssDeclarationListBlock { + l_curly_token: L_CURLY@4..5 "{" [] [], + declarations: CssDeclarationList [ + CssDeclaration { + property: CssBogusProperty { + items: [ + CssIdentifier { + value_token: IDENT@5..17 "unknown" [Newline("\n"), Whitespace(" ")] [], + }, + COLON@17..19 ":" [] [Whitespace(" ")], + CssBogus { + items: [ + CssBogus { + items: [ + CssIdentifier { + value_token: IDENT@19..23 "calc" [] [], + }, + L_PAREN@23..24 "(" [] [], + CssBogus { + items: [ + CssBogusParameter { + items: [ + SEMICOLON@24..25 ";" [] [], + IDENT@25..35 "width" [Newline("\n"), Whitespace(" ")] [], + COLON@35..37 ":" [] [Whitespace(" ")], + IDENT@37..41 "calc" [] [], + L_PAREN@41..42 "(" [] [], + SEMICOLON@42..43 ";" [] [], + IDENT@43..56 "--custom" [Newline("\n"), Whitespace(" ")] [], + COLON@56..58 ":" [] [Whitespace(" ")], + IDENT@58..62 "calc" [] [], + L_PAREN@62..63 "(" [] [], + SEMICOLON@63..64 ";" [] [], + R_CURLY@64..66 "}" [Newline("\n")] [], + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + important: missing (optional), + }, + ], + r_curly_token: missing (required), + }, + }, + ], + eof_token: EOF@66..66 "" [] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..66 + 0: (empty) + 1: CSS_RULE_LIST@0..66 + 0: CSS_RULE@0..66 + 0: CSS_SELECTOR_LIST@0..4 + 0: CSS_COMPOUND_SELECTOR@0..4 + 0: (empty) + 1: CSS_TYPE_SELECTOR@0..4 + 0: (empty) + 1: CSS_IDENTIFIER@0..4 + 0: IDENT@0..4 "div" [] [Whitespace(" ")] + 2: CSS_SUB_SELECTOR_LIST@4..4 + 1: CSS_DECLARATION_LIST_BLOCK@4..66 + 0: L_CURLY@4..5 "{" [] [] + 1: CSS_DECLARATION_LIST@5..66 + 0: CSS_DECLARATION@5..66 + 0: CSS_BOGUS_PROPERTY@5..66 + 0: CSS_IDENTIFIER@5..17 + 0: IDENT@5..17 "unknown" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@17..19 ":" [] [Whitespace(" ")] + 2: CSS_BOGUS@19..66 + 0: CSS_BOGUS@19..66 + 0: CSS_IDENTIFIER@19..23 + 0: IDENT@19..23 "calc" [] [] + 1: L_PAREN@23..24 "(" [] [] + 2: CSS_BOGUS@24..66 + 0: CSS_BOGUS_PARAMETER@24..66 + 0: SEMICOLON@24..25 ";" [] [] + 1: IDENT@25..35 "width" [Newline("\n"), Whitespace(" ")] [] + 2: COLON@35..37 ":" [] [Whitespace(" ")] + 3: IDENT@37..41 "calc" [] [] + 4: L_PAREN@41..42 "(" [] [] + 5: SEMICOLON@42..43 ";" [] [] + 6: IDENT@43..56 "--custom" [Newline("\n"), Whitespace(" ")] [] + 7: COLON@56..58 ":" [] [Whitespace(" ")] + 8: IDENT@58..62 "calc" [] [] + 9: L_PAREN@62..63 "(" [] [] + 10: SEMICOLON@63..64 ";" [] [] + 11: R_CURLY@64..66 "}" [Newline("\n")] [] + 1: (empty) + 2: (empty) + 2: EOF@66..66 "" [] [] + +``` + +## Diagnostics + +``` +property_generic_error.css:2:19 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × Expected a declaration item but instead found '; + width: calc(; + --custom: calc(; + }'. + + 1 │ div { + > 2 │ unknown: calc(; + │ ^ + > 3 │ width: calc(; + > 4 │ --custom: calc(; + > 5 │ } + │ ^ + + i Expected a declaration item here. + + 1 │ div { + > 2 │ unknown: calc(; + │ ^ + > 3 │ width: calc(; + > 4 │ --custom: calc(; + > 5 │ } + │ ^ + +property_generic_error.css:5:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + × expected `)` but instead the file ends + + 3 │ width: calc(; + 4 │ --custom: calc(; + > 5 │ } + │ + + i the file ends here + + 3 │ width: calc(; + 4 │ --custom: calc(; + > 5 │ } + │ + +``` + + diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css new file mode 100644 index 000000000000..5b09d3a06aee --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css @@ -0,0 +1,17 @@ +div { + /* Global values */ + all: inherit; + all: initial; + all: unset; + all: revert; + all: revert-layer; + + + /* Incorrect values become generic */ + all: 10s; + all: one-value; + all: multiple values; + all: delimited, values; + all: delimited / slash / values; + all: mixed, delimiters / can be, used; +} \ No newline at end of file diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css.snap new file mode 100644 index 000000000000..c5a30e53c063 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css.snap @@ -0,0 +1,433 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- + +## Input + +```css +div { + /* Global values */ + all: inherit; + all: initial; + all: unset; + all: revert; + all: revert-layer; + + + /* Incorrect values become generic */ + all: 10s; + all: one-value; + all: multiple values; + all: delimited, values; + all: delimited / slash / values; + all: mixed, delimiters / can be, used; +} +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selector_token: missing (optional), + simple_selector: CssTypeSelector { + namespace: missing (optional), + ident: CssIdentifier { + value_token: IDENT@0..4 "div" [] [Whitespace(" ")], + }, + }, + sub_selectors: CssSubSelectorList [], + }, + ], + block: CssDeclarationListBlock { + l_curly_token: L_CURLY@4..5 "{" [] [], + declarations: CssDeclarationList [ + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@5..37 "all" [Newline("\n"), Whitespace(" "), Comments("/* Global values */"), Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@37..39 ":" [] [Whitespace(" ")], + value: CssWideKeyword { + value: INHERIT_KW@39..46 "inherit" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@46..47 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@47..55 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@55..57 ":" [] [Whitespace(" ")], + value: CssWideKeyword { + value: INITIAL_KW@57..64 "initial" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@64..65 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@65..73 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@73..75 ":" [] [Whitespace(" ")], + value: CssWideKeyword { + value: UNSET_KW@75..80 "unset" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@80..81 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@81..89 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@89..91 ":" [] [Whitespace(" ")], + value: CssWideKeyword { + value: REVERT_KW@91..97 "revert" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@97..98 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@98..106 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@106..108 ":" [] [Whitespace(" ")], + value: CssWideKeyword { + value: REVERT_LAYER_KW@108..120 "revert-layer" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@120..121 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@121..173 "all" [Newline("\n"), Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* Incorrect values b ..."), Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@173..175 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@175..177 "10" [] [], + unit_token: IDENT@177..178 "s" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@178..179 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@179..187 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@187..189 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@189..198 "one-value" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@198..199 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@199..207 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@207..209 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@209..218 "multiple" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@218..224 "values" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@224..225 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@225..233 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@233..235 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@235..244 "delimited" [] [], + }, + CssGenericDelimiter { + value: COMMA@244..246 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@246..252 "values" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@252..253 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@253..261 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@261..263 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@263..273 "delimited" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@273..275 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@275..281 "slash" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@281..283 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@283..289 "values" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@289..290 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@290..298 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@298..300 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@300..305 "mixed" [] [], + }, + CssGenericDelimiter { + value: COMMA@305..307 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@307..318 "delimiters" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@318..320 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@320..324 "can" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@324..326 "be" [] [], + }, + CssGenericDelimiter { + value: COMMA@326..328 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@328..332 "used" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@332..333 ";" [] [], + ], + r_curly_token: R_CURLY@333..335 "}" [Newline("\n")] [], + }, + }, + ], + eof_token: EOF@335..335 "" [] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..335 + 0: (empty) + 1: CSS_RULE_LIST@0..335 + 0: CSS_RULE@0..335 + 0: CSS_SELECTOR_LIST@0..4 + 0: CSS_COMPOUND_SELECTOR@0..4 + 0: (empty) + 1: CSS_TYPE_SELECTOR@0..4 + 0: (empty) + 1: CSS_IDENTIFIER@0..4 + 0: IDENT@0..4 "div" [] [Whitespace(" ")] + 2: CSS_SUB_SELECTOR_LIST@4..4 + 1: CSS_DECLARATION_LIST_BLOCK@4..335 + 0: L_CURLY@4..5 "{" [] [] + 1: CSS_DECLARATION_LIST@5..333 + 0: CSS_DECLARATION@5..46 + 0: CSS_ALL_PROPERTY@5..46 + 0: CSS_IDENTIFIER@5..37 + 0: IDENT@5..37 "all" [Newline("\n"), Whitespace(" "), Comments("/* Global values */"), Newline("\n"), Whitespace(" ")] [] + 1: COLON@37..39 ":" [] [Whitespace(" ")] + 2: CSS_WIDE_KEYWORD@39..46 + 0: INHERIT_KW@39..46 "inherit" [] [] + 1: (empty) + 1: SEMICOLON@46..47 ";" [] [] + 2: CSS_DECLARATION@47..64 + 0: CSS_ALL_PROPERTY@47..64 + 0: CSS_IDENTIFIER@47..55 + 0: IDENT@47..55 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@55..57 ":" [] [Whitespace(" ")] + 2: CSS_WIDE_KEYWORD@57..64 + 0: INITIAL_KW@57..64 "initial" [] [] + 1: (empty) + 3: SEMICOLON@64..65 ";" [] [] + 4: CSS_DECLARATION@65..80 + 0: CSS_ALL_PROPERTY@65..80 + 0: CSS_IDENTIFIER@65..73 + 0: IDENT@65..73 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@73..75 ":" [] [Whitespace(" ")] + 2: CSS_WIDE_KEYWORD@75..80 + 0: UNSET_KW@75..80 "unset" [] [] + 1: (empty) + 5: SEMICOLON@80..81 ";" [] [] + 6: CSS_DECLARATION@81..97 + 0: CSS_ALL_PROPERTY@81..97 + 0: CSS_IDENTIFIER@81..89 + 0: IDENT@81..89 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@89..91 ":" [] [Whitespace(" ")] + 2: CSS_WIDE_KEYWORD@91..97 + 0: REVERT_KW@91..97 "revert" [] [] + 1: (empty) + 7: SEMICOLON@97..98 ";" [] [] + 8: CSS_DECLARATION@98..120 + 0: CSS_ALL_PROPERTY@98..120 + 0: CSS_IDENTIFIER@98..106 + 0: IDENT@98..106 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@106..108 ":" [] [Whitespace(" ")] + 2: CSS_WIDE_KEYWORD@108..120 + 0: REVERT_LAYER_KW@108..120 "revert-layer" [] [] + 1: (empty) + 9: SEMICOLON@120..121 ";" [] [] + 10: CSS_DECLARATION@121..178 + 0: CSS_ALL_PROPERTY@121..178 + 0: CSS_IDENTIFIER@121..173 + 0: IDENT@121..173 "all" [Newline("\n"), Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* Incorrect values b ..."), Newline("\n"), Whitespace(" ")] [] + 1: COLON@173..175 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@175..178 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@175..178 + 0: CSS_REGULAR_DIMENSION@175..178 + 0: CSS_NUMBER_LITERAL@175..177 "10" [] [] + 1: IDENT@177..178 "s" [] [] + 1: (empty) + 11: SEMICOLON@178..179 ";" [] [] + 12: CSS_DECLARATION@179..198 + 0: CSS_ALL_PROPERTY@179..198 + 0: CSS_IDENTIFIER@179..187 + 0: IDENT@179..187 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@187..189 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@189..198 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@189..198 + 0: CSS_IDENTIFIER@189..198 + 0: IDENT@189..198 "one-value" [] [] + 1: (empty) + 13: SEMICOLON@198..199 ";" [] [] + 14: CSS_DECLARATION@199..224 + 0: CSS_ALL_PROPERTY@199..224 + 0: CSS_IDENTIFIER@199..207 + 0: IDENT@199..207 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@207..209 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@209..224 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@209..224 + 0: CSS_IDENTIFIER@209..218 + 0: IDENT@209..218 "multiple" [] [Whitespace(" ")] + 1: CSS_IDENTIFIER@218..224 + 0: IDENT@218..224 "values" [] [] + 1: (empty) + 15: SEMICOLON@224..225 ";" [] [] + 16: CSS_DECLARATION@225..252 + 0: CSS_ALL_PROPERTY@225..252 + 0: CSS_IDENTIFIER@225..233 + 0: IDENT@225..233 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@233..235 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@235..252 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@235..252 + 0: CSS_IDENTIFIER@235..244 + 0: IDENT@235..244 "delimited" [] [] + 1: CSS_GENERIC_DELIMITER@244..246 + 0: COMMA@244..246 "," [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@246..252 + 0: IDENT@246..252 "values" [] [] + 1: (empty) + 17: SEMICOLON@252..253 ";" [] [] + 18: CSS_DECLARATION@253..289 + 0: CSS_ALL_PROPERTY@253..289 + 0: CSS_IDENTIFIER@253..261 + 0: IDENT@253..261 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@261..263 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@263..289 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@263..289 + 0: CSS_IDENTIFIER@263..273 + 0: IDENT@263..273 "delimited" [] [Whitespace(" ")] + 1: CSS_GENERIC_DELIMITER@273..275 + 0: SLASH@273..275 "/" [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@275..281 + 0: IDENT@275..281 "slash" [] [Whitespace(" ")] + 3: CSS_GENERIC_DELIMITER@281..283 + 0: SLASH@281..283 "/" [] [Whitespace(" ")] + 4: CSS_IDENTIFIER@283..289 + 0: IDENT@283..289 "values" [] [] + 1: (empty) + 19: SEMICOLON@289..290 ";" [] [] + 20: CSS_DECLARATION@290..332 + 0: CSS_ALL_PROPERTY@290..332 + 0: CSS_IDENTIFIER@290..298 + 0: IDENT@290..298 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@298..300 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@300..332 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@300..332 + 0: CSS_IDENTIFIER@300..305 + 0: IDENT@300..305 "mixed" [] [] + 1: CSS_GENERIC_DELIMITER@305..307 + 0: COMMA@305..307 "," [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@307..318 + 0: IDENT@307..318 "delimiters" [] [Whitespace(" ")] + 3: CSS_GENERIC_DELIMITER@318..320 + 0: SLASH@318..320 "/" [] [Whitespace(" ")] + 4: CSS_IDENTIFIER@320..324 + 0: IDENT@320..324 "can" [] [Whitespace(" ")] + 5: CSS_IDENTIFIER@324..326 + 0: IDENT@324..326 "be" [] [] + 6: CSS_GENERIC_DELIMITER@326..328 + 0: COMMA@326..328 "," [] [Whitespace(" ")] + 7: CSS_IDENTIFIER@328..332 + 0: IDENT@328..332 "used" [] [] + 1: (empty) + 21: SEMICOLON@332..333 ";" [] [] + 2: R_CURLY@333..335 "}" [Newline("\n")] [] + 2: EOF@335..335 "" [] [] + +``` + + diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css new file mode 100644 index 000000000000..f5954928e49e --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css @@ -0,0 +1,26 @@ +div { + /* Unknown property, always generic */ + unknown-property: a value; + unknown-property: one-value; + unknown-property: multiple values; + unknown-property: delimited, values; + unknown-property: delimited / slash / values; + unknown-property: mixed, delimiters / can be, used; + + /* Custom property, always generic */ + --custom-property: a value; + --custom-property: one-value; + --custom-property: multiple values; + --custom-property: delimited, values; + --custom-property: delimited / slash / values; + --custom-property: mixed, delimiters / can be, used; + + + /* Known property, incorrect values become generic */ + all: 10s; + all: one-value; + all: multiple values; + all: delimited, values; + all: delimited / slash / values; + all: mixed, delimiters / can be, used; +} \ No newline at end of file diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css.snap new file mode 100644 index 000000000000..c66f68d2b1b4 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css.snap @@ -0,0 +1,782 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- + +## Input + +```css +div { + /* Unknown property, always generic */ + unknown-property: a value; + unknown-property: one-value; + unknown-property: multiple values; + unknown-property: delimited, values; + unknown-property: delimited / slash / values; + unknown-property: mixed, delimiters / can be, used; + + /* Custom property, always generic */ + --custom-property: a value; + --custom-property: one-value; + --custom-property: multiple values; + --custom-property: delimited, values; + --custom-property: delimited / slash / values; + --custom-property: mixed, delimiters / can be, used; + + + /* Known property, incorrect values become generic */ + all: 10s; + all: one-value; + all: multiple values; + all: delimited, values; + all: delimited / slash / values; + all: mixed, delimiters / can be, used; +} +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selector_token: missing (optional), + simple_selector: CssTypeSelector { + namespace: missing (optional), + ident: CssIdentifier { + value_token: IDENT@0..4 "div" [] [Whitespace(" ")], + }, + }, + sub_selectors: CssSubSelectorList [], + }, + ], + block: CssDeclarationListBlock { + l_curly_token: L_CURLY@4..5 "{" [] [], + declarations: CssDeclarationList [ + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@5..69 "unknown-property" [Newline("\n"), Whitespace(" "), Comments("/* Unknown property, ..."), Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@69..71 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@71..73 "a" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@73..78 "value" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@78..79 ";" [] [], + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@79..100 "unknown-property" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@100..102 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@102..111 "one-value" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@111..112 ";" [] [], + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@112..133 "unknown-property" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@133..135 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@135..144 "multiple" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@144..150 "values" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@150..151 ";" [] [], + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@151..172 "unknown-property" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@172..174 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@174..183 "delimited" [] [], + }, + CssGenericDelimiter { + value: COMMA@183..185 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@185..191 "values" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@191..192 ";" [] [], + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@192..213 "unknown-property" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@213..215 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@215..225 "delimited" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@225..227 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@227..233 "slash" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@233..235 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@235..241 "values" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@241..242 ";" [] [], + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@242..263 "unknown-property" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@263..265 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@265..270 "mixed" [] [], + }, + CssGenericDelimiter { + value: COMMA@270..272 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@272..283 "delimiters" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@283..285 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@285..289 "can" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@289..291 "be" [] [], + }, + CssGenericDelimiter { + value: COMMA@291..293 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@293..297 "used" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@297..298 ";" [] [], + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@298..363 "--custom-property" [Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* Custom property, a ..."), Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@363..365 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@365..367 "a" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@367..372 "value" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@372..373 ";" [] [], + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@373..395 "--custom-property" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@395..397 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@397..406 "one-value" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@406..407 ";" [] [], + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@407..429 "--custom-property" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@429..431 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@431..440 "multiple" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@440..446 "values" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@446..447 ";" [] [], + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@447..469 "--custom-property" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@469..471 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@471..480 "delimited" [] [], + }, + CssGenericDelimiter { + value: COMMA@480..482 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@482..488 "values" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@488..489 ";" [] [], + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@489..511 "--custom-property" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@511..513 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@513..523 "delimited" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@523..525 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@525..531 "slash" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@531..533 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@533..539 "values" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@539..540 ";" [] [], + CssDeclaration { + property: CssGenericProperty { + name: CssIdentifier { + value_token: IDENT@540..562 "--custom-property" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@562..564 ":" [] [Whitespace(" ")], + value: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@564..569 "mixed" [] [], + }, + CssGenericDelimiter { + value: COMMA@569..571 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@571..582 "delimiters" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@582..584 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@584..588 "can" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@588..590 "be" [] [], + }, + CssGenericDelimiter { + value: COMMA@590..592 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@592..596 "used" [] [], + }, + ], + }, + important: missing (optional), + }, + SEMICOLON@596..597 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@597..665 "all" [Newline("\n"), Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* Known property, in ..."), Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@665..667 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@667..669 "10" [] [], + unit_token: IDENT@669..670 "s" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@670..671 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@671..679 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@679..681 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@681..690 "one-value" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@690..691 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@691..699 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@699..701 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@701..710 "multiple" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@710..716 "values" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@716..717 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@717..725 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@725..727 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@727..736 "delimited" [] [], + }, + CssGenericDelimiter { + value: COMMA@736..738 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@738..744 "values" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@744..745 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@745..753 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@753..755 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@755..765 "delimited" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@765..767 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@767..773 "slash" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@773..775 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@775..781 "values" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@781..782 ";" [] [], + CssDeclaration { + property: CssAllProperty { + name: CssIdentifier { + value_token: IDENT@782..790 "all" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@790..792 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@792..797 "mixed" [] [], + }, + CssGenericDelimiter { + value: COMMA@797..799 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@799..810 "delimiters" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@810..812 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@812..816 "can" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@816..818 "be" [] [], + }, + CssGenericDelimiter { + value: COMMA@818..820 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@820..824 "used" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@824..825 ";" [] [], + ], + r_curly_token: R_CURLY@825..827 "}" [Newline("\n")] [], + }, + }, + ], + eof_token: EOF@827..827 "" [] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..827 + 0: (empty) + 1: CSS_RULE_LIST@0..827 + 0: CSS_RULE@0..827 + 0: CSS_SELECTOR_LIST@0..4 + 0: CSS_COMPOUND_SELECTOR@0..4 + 0: (empty) + 1: CSS_TYPE_SELECTOR@0..4 + 0: (empty) + 1: CSS_IDENTIFIER@0..4 + 0: IDENT@0..4 "div" [] [Whitespace(" ")] + 2: CSS_SUB_SELECTOR_LIST@4..4 + 1: CSS_DECLARATION_LIST_BLOCK@4..827 + 0: L_CURLY@4..5 "{" [] [] + 1: CSS_DECLARATION_LIST@5..825 + 0: CSS_DECLARATION@5..78 + 0: CSS_GENERIC_PROPERTY@5..78 + 0: CSS_IDENTIFIER@5..69 + 0: IDENT@5..69 "unknown-property" [Newline("\n"), Whitespace(" "), Comments("/* Unknown property, ..."), Newline("\n"), Whitespace(" ")] [] + 1: COLON@69..71 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@71..78 + 0: CSS_IDENTIFIER@71..73 + 0: IDENT@71..73 "a" [] [Whitespace(" ")] + 1: CSS_IDENTIFIER@73..78 + 0: IDENT@73..78 "value" [] [] + 1: (empty) + 1: SEMICOLON@78..79 ";" [] [] + 2: CSS_DECLARATION@79..111 + 0: CSS_GENERIC_PROPERTY@79..111 + 0: CSS_IDENTIFIER@79..100 + 0: IDENT@79..100 "unknown-property" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@100..102 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@102..111 + 0: CSS_IDENTIFIER@102..111 + 0: IDENT@102..111 "one-value" [] [] + 1: (empty) + 3: SEMICOLON@111..112 ";" [] [] + 4: CSS_DECLARATION@112..150 + 0: CSS_GENERIC_PROPERTY@112..150 + 0: CSS_IDENTIFIER@112..133 + 0: IDENT@112..133 "unknown-property" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@133..135 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@135..150 + 0: CSS_IDENTIFIER@135..144 + 0: IDENT@135..144 "multiple" [] [Whitespace(" ")] + 1: CSS_IDENTIFIER@144..150 + 0: IDENT@144..150 "values" [] [] + 1: (empty) + 5: SEMICOLON@150..151 ";" [] [] + 6: CSS_DECLARATION@151..191 + 0: CSS_GENERIC_PROPERTY@151..191 + 0: CSS_IDENTIFIER@151..172 + 0: IDENT@151..172 "unknown-property" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@172..174 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@174..191 + 0: CSS_IDENTIFIER@174..183 + 0: IDENT@174..183 "delimited" [] [] + 1: CSS_GENERIC_DELIMITER@183..185 + 0: COMMA@183..185 "," [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@185..191 + 0: IDENT@185..191 "values" [] [] + 1: (empty) + 7: SEMICOLON@191..192 ";" [] [] + 8: CSS_DECLARATION@192..241 + 0: CSS_GENERIC_PROPERTY@192..241 + 0: CSS_IDENTIFIER@192..213 + 0: IDENT@192..213 "unknown-property" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@213..215 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@215..241 + 0: CSS_IDENTIFIER@215..225 + 0: IDENT@215..225 "delimited" [] [Whitespace(" ")] + 1: CSS_GENERIC_DELIMITER@225..227 + 0: SLASH@225..227 "/" [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@227..233 + 0: IDENT@227..233 "slash" [] [Whitespace(" ")] + 3: CSS_GENERIC_DELIMITER@233..235 + 0: SLASH@233..235 "/" [] [Whitespace(" ")] + 4: CSS_IDENTIFIER@235..241 + 0: IDENT@235..241 "values" [] [] + 1: (empty) + 9: SEMICOLON@241..242 ";" [] [] + 10: CSS_DECLARATION@242..297 + 0: CSS_GENERIC_PROPERTY@242..297 + 0: CSS_IDENTIFIER@242..263 + 0: IDENT@242..263 "unknown-property" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@263..265 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@265..297 + 0: CSS_IDENTIFIER@265..270 + 0: IDENT@265..270 "mixed" [] [] + 1: CSS_GENERIC_DELIMITER@270..272 + 0: COMMA@270..272 "," [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@272..283 + 0: IDENT@272..283 "delimiters" [] [Whitespace(" ")] + 3: CSS_GENERIC_DELIMITER@283..285 + 0: SLASH@283..285 "/" [] [Whitespace(" ")] + 4: CSS_IDENTIFIER@285..289 + 0: IDENT@285..289 "can" [] [Whitespace(" ")] + 5: CSS_IDENTIFIER@289..291 + 0: IDENT@289..291 "be" [] [] + 6: CSS_GENERIC_DELIMITER@291..293 + 0: COMMA@291..293 "," [] [Whitespace(" ")] + 7: CSS_IDENTIFIER@293..297 + 0: IDENT@293..297 "used" [] [] + 1: (empty) + 11: SEMICOLON@297..298 ";" [] [] + 12: CSS_DECLARATION@298..372 + 0: CSS_GENERIC_PROPERTY@298..372 + 0: CSS_IDENTIFIER@298..363 + 0: IDENT@298..363 "--custom-property" [Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* Custom property, a ..."), Newline("\n"), Whitespace(" ")] [] + 1: COLON@363..365 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@365..372 + 0: CSS_IDENTIFIER@365..367 + 0: IDENT@365..367 "a" [] [Whitespace(" ")] + 1: CSS_IDENTIFIER@367..372 + 0: IDENT@367..372 "value" [] [] + 1: (empty) + 13: SEMICOLON@372..373 ";" [] [] + 14: CSS_DECLARATION@373..406 + 0: CSS_GENERIC_PROPERTY@373..406 + 0: CSS_IDENTIFIER@373..395 + 0: IDENT@373..395 "--custom-property" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@395..397 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@397..406 + 0: CSS_IDENTIFIER@397..406 + 0: IDENT@397..406 "one-value" [] [] + 1: (empty) + 15: SEMICOLON@406..407 ";" [] [] + 16: CSS_DECLARATION@407..446 + 0: CSS_GENERIC_PROPERTY@407..446 + 0: CSS_IDENTIFIER@407..429 + 0: IDENT@407..429 "--custom-property" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@429..431 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@431..446 + 0: CSS_IDENTIFIER@431..440 + 0: IDENT@431..440 "multiple" [] [Whitespace(" ")] + 1: CSS_IDENTIFIER@440..446 + 0: IDENT@440..446 "values" [] [] + 1: (empty) + 17: SEMICOLON@446..447 ";" [] [] + 18: CSS_DECLARATION@447..488 + 0: CSS_GENERIC_PROPERTY@447..488 + 0: CSS_IDENTIFIER@447..469 + 0: IDENT@447..469 "--custom-property" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@469..471 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@471..488 + 0: CSS_IDENTIFIER@471..480 + 0: IDENT@471..480 "delimited" [] [] + 1: CSS_GENERIC_DELIMITER@480..482 + 0: COMMA@480..482 "," [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@482..488 + 0: IDENT@482..488 "values" [] [] + 1: (empty) + 19: SEMICOLON@488..489 ";" [] [] + 20: CSS_DECLARATION@489..539 + 0: CSS_GENERIC_PROPERTY@489..539 + 0: CSS_IDENTIFIER@489..511 + 0: IDENT@489..511 "--custom-property" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@511..513 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@513..539 + 0: CSS_IDENTIFIER@513..523 + 0: IDENT@513..523 "delimited" [] [Whitespace(" ")] + 1: CSS_GENERIC_DELIMITER@523..525 + 0: SLASH@523..525 "/" [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@525..531 + 0: IDENT@525..531 "slash" [] [Whitespace(" ")] + 3: CSS_GENERIC_DELIMITER@531..533 + 0: SLASH@531..533 "/" [] [Whitespace(" ")] + 4: CSS_IDENTIFIER@533..539 + 0: IDENT@533..539 "values" [] [] + 1: (empty) + 21: SEMICOLON@539..540 ";" [] [] + 22: CSS_DECLARATION@540..596 + 0: CSS_GENERIC_PROPERTY@540..596 + 0: CSS_IDENTIFIER@540..562 + 0: IDENT@540..562 "--custom-property" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@562..564 ":" [] [Whitespace(" ")] + 2: CSS_GENERIC_COMPONENT_VALUE_LIST@564..596 + 0: CSS_IDENTIFIER@564..569 + 0: IDENT@564..569 "mixed" [] [] + 1: CSS_GENERIC_DELIMITER@569..571 + 0: COMMA@569..571 "," [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@571..582 + 0: IDENT@571..582 "delimiters" [] [Whitespace(" ")] + 3: CSS_GENERIC_DELIMITER@582..584 + 0: SLASH@582..584 "/" [] [Whitespace(" ")] + 4: CSS_IDENTIFIER@584..588 + 0: IDENT@584..588 "can" [] [Whitespace(" ")] + 5: CSS_IDENTIFIER@588..590 + 0: IDENT@588..590 "be" [] [] + 6: CSS_GENERIC_DELIMITER@590..592 + 0: COMMA@590..592 "," [] [Whitespace(" ")] + 7: CSS_IDENTIFIER@592..596 + 0: IDENT@592..596 "used" [] [] + 1: (empty) + 23: SEMICOLON@596..597 ";" [] [] + 24: CSS_DECLARATION@597..670 + 0: CSS_ALL_PROPERTY@597..670 + 0: CSS_IDENTIFIER@597..665 + 0: IDENT@597..665 "all" [Newline("\n"), Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* Known property, in ..."), Newline("\n"), Whitespace(" ")] [] + 1: COLON@665..667 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@667..670 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@667..670 + 0: CSS_REGULAR_DIMENSION@667..670 + 0: CSS_NUMBER_LITERAL@667..669 "10" [] [] + 1: IDENT@669..670 "s" [] [] + 1: (empty) + 25: SEMICOLON@670..671 ";" [] [] + 26: CSS_DECLARATION@671..690 + 0: CSS_ALL_PROPERTY@671..690 + 0: CSS_IDENTIFIER@671..679 + 0: IDENT@671..679 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@679..681 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@681..690 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@681..690 + 0: CSS_IDENTIFIER@681..690 + 0: IDENT@681..690 "one-value" [] [] + 1: (empty) + 27: SEMICOLON@690..691 ";" [] [] + 28: CSS_DECLARATION@691..716 + 0: CSS_ALL_PROPERTY@691..716 + 0: CSS_IDENTIFIER@691..699 + 0: IDENT@691..699 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@699..701 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@701..716 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@701..716 + 0: CSS_IDENTIFIER@701..710 + 0: IDENT@701..710 "multiple" [] [Whitespace(" ")] + 1: CSS_IDENTIFIER@710..716 + 0: IDENT@710..716 "values" [] [] + 1: (empty) + 29: SEMICOLON@716..717 ";" [] [] + 30: CSS_DECLARATION@717..744 + 0: CSS_ALL_PROPERTY@717..744 + 0: CSS_IDENTIFIER@717..725 + 0: IDENT@717..725 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@725..727 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@727..744 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@727..744 + 0: CSS_IDENTIFIER@727..736 + 0: IDENT@727..736 "delimited" [] [] + 1: CSS_GENERIC_DELIMITER@736..738 + 0: COMMA@736..738 "," [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@738..744 + 0: IDENT@738..744 "values" [] [] + 1: (empty) + 31: SEMICOLON@744..745 ";" [] [] + 32: CSS_DECLARATION@745..781 + 0: CSS_ALL_PROPERTY@745..781 + 0: CSS_IDENTIFIER@745..753 + 0: IDENT@745..753 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@753..755 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@755..781 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@755..781 + 0: CSS_IDENTIFIER@755..765 + 0: IDENT@755..765 "delimited" [] [Whitespace(" ")] + 1: CSS_GENERIC_DELIMITER@765..767 + 0: SLASH@765..767 "/" [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@767..773 + 0: IDENT@767..773 "slash" [] [Whitespace(" ")] + 3: CSS_GENERIC_DELIMITER@773..775 + 0: SLASH@773..775 "/" [] [Whitespace(" ")] + 4: CSS_IDENTIFIER@775..781 + 0: IDENT@775..781 "values" [] [] + 1: (empty) + 33: SEMICOLON@781..782 ";" [] [] + 34: CSS_DECLARATION@782..824 + 0: CSS_ALL_PROPERTY@782..824 + 0: CSS_IDENTIFIER@782..790 + 0: IDENT@782..790 "all" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@790..792 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@792..824 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@792..824 + 0: CSS_IDENTIFIER@792..797 + 0: IDENT@792..797 "mixed" [] [] + 1: CSS_GENERIC_DELIMITER@797..799 + 0: COMMA@797..799 "," [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@799..810 + 0: IDENT@799..810 "delimiters" [] [Whitespace(" ")] + 3: CSS_GENERIC_DELIMITER@810..812 + 0: SLASH@810..812 "/" [] [Whitespace(" ")] + 4: CSS_IDENTIFIER@812..816 + 0: IDENT@812..816 "can" [] [Whitespace(" ")] + 5: CSS_IDENTIFIER@816..818 + 0: IDENT@816..818 "be" [] [] + 6: CSS_GENERIC_DELIMITER@818..820 + 0: COMMA@818..820 "," [] [Whitespace(" ")] + 7: CSS_IDENTIFIER@820..824 + 0: IDENT@820..824 "used" [] [] + 1: (empty) + 35: SEMICOLON@824..825 ";" [] [] + 2: R_CURLY@825..827 "}" [Newline("\n")] [] + 2: EOF@827..827 "" [] [] + +``` + + diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css new file mode 100644 index 000000000000..dc5b14d2c55f --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css @@ -0,0 +1,27 @@ +div { + /* Global values */ + z-index: inherit; + z-index: initial; + z-index: unset; + z-index: revert; + z-index: revert-layer; + + /* auto */ + z-index: auto; + + /* */ + z-index: 1; + z-index: 0; + z-index: -1; + z-index: -123456; + z-index: 444567; + + + /* Incorrect values become generic */ + z-index: 10s; + z-index: one-value; + z-index: multiple values; + z-index: delimited, values; + z-index: delimited / slash / values; + z-index: mixed, delimiters / can be, used; +} diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css.snap new file mode 100644 index 000000000000..36f5e072ec34 --- /dev/null +++ b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css.snap @@ -0,0 +1,576 @@ +--- +source: crates/biome_css_parser/tests/spec_test.rs +expression: snapshot +--- + +## Input + +```css +div { + /* Global values */ + z-index: inherit; + z-index: initial; + z-index: unset; + z-index: revert; + z-index: revert-layer; + + /* auto */ + z-index: auto; + + /* */ + z-index: 1; + z-index: 0; + z-index: -1; + z-index: -123456; + z-index: 444567; + + + /* Incorrect values become generic */ + z-index: 10s; + z-index: one-value; + z-index: multiple values; + z-index: delimited, values; + z-index: delimited / slash / values; + z-index: mixed, delimiters / can be, used; +} + +``` + + +## AST + +``` +CssRoot { + bom_token: missing (optional), + rules: CssRuleList [ + CssRule { + prelude: CssSelectorList [ + CssCompoundSelector { + nesting_selector_token: missing (optional), + simple_selector: CssTypeSelector { + namespace: missing (optional), + ident: CssIdentifier { + value_token: IDENT@0..4 "div" [] [Whitespace(" ")], + }, + }, + sub_selectors: CssSubSelectorList [], + }, + ], + block: CssDeclarationListBlock { + l_curly_token: L_CURLY@4..5 "{" [] [], + declarations: CssDeclarationList [ + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@5..41 "z-index" [Newline("\n"), Whitespace(" "), Comments("/* Global values */"), Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@41..43 ":" [] [Whitespace(" ")], + value: CssWideKeyword { + value: INHERIT_KW@43..50 "inherit" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@50..51 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@51..63 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@63..65 ":" [] [Whitespace(" ")], + value: CssWideKeyword { + value: INITIAL_KW@65..72 "initial" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@72..73 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@73..85 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@85..87 ":" [] [Whitespace(" ")], + value: CssWideKeyword { + value: UNSET_KW@87..92 "unset" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@92..93 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@93..105 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@105..107 ":" [] [Whitespace(" ")], + value: CssWideKeyword { + value: REVERT_KW@107..113 "revert" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@113..114 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@114..126 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@126..128 ":" [] [Whitespace(" ")], + value: CssWideKeyword { + value: REVERT_LAYER_KW@128..140 "revert-layer" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@140..141 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@141..169 "z-index" [Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* auto */"), Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@169..171 ":" [] [Whitespace(" ")], + value: CssAuto { + value_token: AUTO_KW@171..175 "auto" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@175..176 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@176..209 "z-index" [Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* */"), Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@209..211 ":" [] [Whitespace(" ")], + value: CssNumber { + value_token: CSS_NUMBER_LITERAL@211..212 "1" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@212..213 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@213..225 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@225..227 ":" [] [Whitespace(" ")], + value: CssNumber { + value_token: CSS_NUMBER_LITERAL@227..228 "0" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@228..229 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@229..241 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@241..243 ":" [] [Whitespace(" ")], + value: CssNumber { + value_token: CSS_NUMBER_LITERAL@243..245 "-1" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@245..246 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@246..258 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@258..260 ":" [] [Whitespace(" ")], + value: CssNumber { + value_token: CSS_NUMBER_LITERAL@260..267 "-123456" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@267..268 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@268..280 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@280..282 ":" [] [Whitespace(" ")], + value: CssNumber { + value_token: CSS_NUMBER_LITERAL@282..288 "444567" [] [], + }, + }, + important: missing (optional), + }, + SEMICOLON@288..289 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@289..345 "z-index" [Newline("\n"), Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* Incorrect values b ..."), Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@345..347 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssRegularDimension { + value_token: CSS_NUMBER_LITERAL@347..349 "10" [] [], + unit_token: IDENT@349..350 "s" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@350..351 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@351..363 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@363..365 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@365..374 "one-value" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@374..375 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@375..387 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@387..389 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@389..398 "multiple" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@398..404 "values" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@404..405 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@405..417 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@417..419 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@419..428 "delimited" [] [], + }, + CssGenericDelimiter { + value: COMMA@428..430 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@430..436 "values" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@436..437 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@437..449 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@449..451 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@451..461 "delimited" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@461..463 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@463..469 "slash" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@469..471 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@471..477 "values" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@477..478 ";" [] [], + CssDeclaration { + property: CssZIndexProperty { + name: CssIdentifier { + value_token: IDENT@478..490 "z-index" [Newline("\n"), Whitespace(" ")] [], + }, + colon_token: COLON@490..492 ":" [] [Whitespace(" ")], + value: CssUnknownPropertyValue { + css_generic_component_value_list: CssGenericComponentValueList [ + CssIdentifier { + value_token: IDENT@492..497 "mixed" [] [], + }, + CssGenericDelimiter { + value: COMMA@497..499 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@499..510 "delimiters" [] [Whitespace(" ")], + }, + CssGenericDelimiter { + value: SLASH@510..512 "/" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@512..516 "can" [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@516..518 "be" [] [], + }, + CssGenericDelimiter { + value: COMMA@518..520 "," [] [Whitespace(" ")], + }, + CssIdentifier { + value_token: IDENT@520..524 "used" [] [], + }, + ], + }, + }, + important: missing (optional), + }, + SEMICOLON@524..525 ";" [] [], + ], + r_curly_token: R_CURLY@525..527 "}" [Newline("\n")] [], + }, + }, + ], + eof_token: EOF@527..528 "" [Newline("\n")] [], +} +``` + +## CST + +``` +0: CSS_ROOT@0..528 + 0: (empty) + 1: CSS_RULE_LIST@0..527 + 0: CSS_RULE@0..527 + 0: CSS_SELECTOR_LIST@0..4 + 0: CSS_COMPOUND_SELECTOR@0..4 + 0: (empty) + 1: CSS_TYPE_SELECTOR@0..4 + 0: (empty) + 1: CSS_IDENTIFIER@0..4 + 0: IDENT@0..4 "div" [] [Whitespace(" ")] + 2: CSS_SUB_SELECTOR_LIST@4..4 + 1: CSS_DECLARATION_LIST_BLOCK@4..527 + 0: L_CURLY@4..5 "{" [] [] + 1: CSS_DECLARATION_LIST@5..525 + 0: CSS_DECLARATION@5..50 + 0: CSS_Z_INDEX_PROPERTY@5..50 + 0: CSS_IDENTIFIER@5..41 + 0: IDENT@5..41 "z-index" [Newline("\n"), Whitespace(" "), Comments("/* Global values */"), Newline("\n"), Whitespace(" ")] [] + 1: COLON@41..43 ":" [] [Whitespace(" ")] + 2: CSS_WIDE_KEYWORD@43..50 + 0: INHERIT_KW@43..50 "inherit" [] [] + 1: (empty) + 1: SEMICOLON@50..51 ";" [] [] + 2: CSS_DECLARATION@51..72 + 0: CSS_Z_INDEX_PROPERTY@51..72 + 0: CSS_IDENTIFIER@51..63 + 0: IDENT@51..63 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@63..65 ":" [] [Whitespace(" ")] + 2: CSS_WIDE_KEYWORD@65..72 + 0: INITIAL_KW@65..72 "initial" [] [] + 1: (empty) + 3: SEMICOLON@72..73 ";" [] [] + 4: CSS_DECLARATION@73..92 + 0: CSS_Z_INDEX_PROPERTY@73..92 + 0: CSS_IDENTIFIER@73..85 + 0: IDENT@73..85 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@85..87 ":" [] [Whitespace(" ")] + 2: CSS_WIDE_KEYWORD@87..92 + 0: UNSET_KW@87..92 "unset" [] [] + 1: (empty) + 5: SEMICOLON@92..93 ";" [] [] + 6: CSS_DECLARATION@93..113 + 0: CSS_Z_INDEX_PROPERTY@93..113 + 0: CSS_IDENTIFIER@93..105 + 0: IDENT@93..105 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@105..107 ":" [] [Whitespace(" ")] + 2: CSS_WIDE_KEYWORD@107..113 + 0: REVERT_KW@107..113 "revert" [] [] + 1: (empty) + 7: SEMICOLON@113..114 ";" [] [] + 8: CSS_DECLARATION@114..140 + 0: CSS_Z_INDEX_PROPERTY@114..140 + 0: CSS_IDENTIFIER@114..126 + 0: IDENT@114..126 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@126..128 ":" [] [Whitespace(" ")] + 2: CSS_WIDE_KEYWORD@128..140 + 0: REVERT_LAYER_KW@128..140 "revert-layer" [] [] + 1: (empty) + 9: SEMICOLON@140..141 ";" [] [] + 10: CSS_DECLARATION@141..175 + 0: CSS_Z_INDEX_PROPERTY@141..175 + 0: CSS_IDENTIFIER@141..169 + 0: IDENT@141..169 "z-index" [Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* auto */"), Newline("\n"), Whitespace(" ")] [] + 1: COLON@169..171 ":" [] [Whitespace(" ")] + 2: CSS_AUTO@171..175 + 0: AUTO_KW@171..175 "auto" [] [] + 1: (empty) + 11: SEMICOLON@175..176 ";" [] [] + 12: CSS_DECLARATION@176..212 + 0: CSS_Z_INDEX_PROPERTY@176..212 + 0: CSS_IDENTIFIER@176..209 + 0: IDENT@176..209 "z-index" [Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* */"), Newline("\n"), Whitespace(" ")] [] + 1: COLON@209..211 ":" [] [Whitespace(" ")] + 2: CSS_NUMBER@211..212 + 0: CSS_NUMBER_LITERAL@211..212 "1" [] [] + 1: (empty) + 13: SEMICOLON@212..213 ";" [] [] + 14: CSS_DECLARATION@213..228 + 0: CSS_Z_INDEX_PROPERTY@213..228 + 0: CSS_IDENTIFIER@213..225 + 0: IDENT@213..225 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@225..227 ":" [] [Whitespace(" ")] + 2: CSS_NUMBER@227..228 + 0: CSS_NUMBER_LITERAL@227..228 "0" [] [] + 1: (empty) + 15: SEMICOLON@228..229 ";" [] [] + 16: CSS_DECLARATION@229..245 + 0: CSS_Z_INDEX_PROPERTY@229..245 + 0: CSS_IDENTIFIER@229..241 + 0: IDENT@229..241 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@241..243 ":" [] [Whitespace(" ")] + 2: CSS_NUMBER@243..245 + 0: CSS_NUMBER_LITERAL@243..245 "-1" [] [] + 1: (empty) + 17: SEMICOLON@245..246 ";" [] [] + 18: CSS_DECLARATION@246..267 + 0: CSS_Z_INDEX_PROPERTY@246..267 + 0: CSS_IDENTIFIER@246..258 + 0: IDENT@246..258 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@258..260 ":" [] [Whitespace(" ")] + 2: CSS_NUMBER@260..267 + 0: CSS_NUMBER_LITERAL@260..267 "-123456" [] [] + 1: (empty) + 19: SEMICOLON@267..268 ";" [] [] + 20: CSS_DECLARATION@268..288 + 0: CSS_Z_INDEX_PROPERTY@268..288 + 0: CSS_IDENTIFIER@268..280 + 0: IDENT@268..280 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@280..282 ":" [] [Whitespace(" ")] + 2: CSS_NUMBER@282..288 + 0: CSS_NUMBER_LITERAL@282..288 "444567" [] [] + 1: (empty) + 21: SEMICOLON@288..289 ";" [] [] + 22: CSS_DECLARATION@289..350 + 0: CSS_Z_INDEX_PROPERTY@289..350 + 0: CSS_IDENTIFIER@289..345 + 0: IDENT@289..345 "z-index" [Newline("\n"), Newline("\n"), Newline("\n"), Whitespace(" "), Comments("/* Incorrect values b ..."), Newline("\n"), Whitespace(" ")] [] + 1: COLON@345..347 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@347..350 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@347..350 + 0: CSS_REGULAR_DIMENSION@347..350 + 0: CSS_NUMBER_LITERAL@347..349 "10" [] [] + 1: IDENT@349..350 "s" [] [] + 1: (empty) + 23: SEMICOLON@350..351 ";" [] [] + 24: CSS_DECLARATION@351..374 + 0: CSS_Z_INDEX_PROPERTY@351..374 + 0: CSS_IDENTIFIER@351..363 + 0: IDENT@351..363 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@363..365 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@365..374 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@365..374 + 0: CSS_IDENTIFIER@365..374 + 0: IDENT@365..374 "one-value" [] [] + 1: (empty) + 25: SEMICOLON@374..375 ";" [] [] + 26: CSS_DECLARATION@375..404 + 0: CSS_Z_INDEX_PROPERTY@375..404 + 0: CSS_IDENTIFIER@375..387 + 0: IDENT@375..387 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@387..389 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@389..404 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@389..404 + 0: CSS_IDENTIFIER@389..398 + 0: IDENT@389..398 "multiple" [] [Whitespace(" ")] + 1: CSS_IDENTIFIER@398..404 + 0: IDENT@398..404 "values" [] [] + 1: (empty) + 27: SEMICOLON@404..405 ";" [] [] + 28: CSS_DECLARATION@405..436 + 0: CSS_Z_INDEX_PROPERTY@405..436 + 0: CSS_IDENTIFIER@405..417 + 0: IDENT@405..417 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@417..419 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@419..436 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@419..436 + 0: CSS_IDENTIFIER@419..428 + 0: IDENT@419..428 "delimited" [] [] + 1: CSS_GENERIC_DELIMITER@428..430 + 0: COMMA@428..430 "," [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@430..436 + 0: IDENT@430..436 "values" [] [] + 1: (empty) + 29: SEMICOLON@436..437 ";" [] [] + 30: CSS_DECLARATION@437..477 + 0: CSS_Z_INDEX_PROPERTY@437..477 + 0: CSS_IDENTIFIER@437..449 + 0: IDENT@437..449 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@449..451 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@451..477 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@451..477 + 0: CSS_IDENTIFIER@451..461 + 0: IDENT@451..461 "delimited" [] [Whitespace(" ")] + 1: CSS_GENERIC_DELIMITER@461..463 + 0: SLASH@461..463 "/" [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@463..469 + 0: IDENT@463..469 "slash" [] [Whitespace(" ")] + 3: CSS_GENERIC_DELIMITER@469..471 + 0: SLASH@469..471 "/" [] [Whitespace(" ")] + 4: CSS_IDENTIFIER@471..477 + 0: IDENT@471..477 "values" [] [] + 1: (empty) + 31: SEMICOLON@477..478 ";" [] [] + 32: CSS_DECLARATION@478..524 + 0: CSS_Z_INDEX_PROPERTY@478..524 + 0: CSS_IDENTIFIER@478..490 + 0: IDENT@478..490 "z-index" [Newline("\n"), Whitespace(" ")] [] + 1: COLON@490..492 ":" [] [Whitespace(" ")] + 2: CSS_UNKNOWN_PROPERTY_VALUE@492..524 + 0: CSS_GENERIC_COMPONENT_VALUE_LIST@492..524 + 0: CSS_IDENTIFIER@492..497 + 0: IDENT@492..497 "mixed" [] [] + 1: CSS_GENERIC_DELIMITER@497..499 + 0: COMMA@497..499 "," [] [Whitespace(" ")] + 2: CSS_IDENTIFIER@499..510 + 0: IDENT@499..510 "delimiters" [] [Whitespace(" ")] + 3: CSS_GENERIC_DELIMITER@510..512 + 0: SLASH@510..512 "/" [] [Whitespace(" ")] + 4: CSS_IDENTIFIER@512..516 + 0: IDENT@512..516 "can" [] [Whitespace(" ")] + 5: CSS_IDENTIFIER@516..518 + 0: IDENT@516..518 "be" [] [] + 6: CSS_GENERIC_DELIMITER@518..520 + 0: COMMA@518..520 "," [] [Whitespace(" ")] + 7: CSS_IDENTIFIER@520..524 + 0: IDENT@520..524 "used" [] [] + 1: (empty) + 33: SEMICOLON@524..525 ";" [] [] + 2: R_CURLY@525..527 "}" [Newline("\n")] [] + 2: EOF@527..528 "" [Newline("\n")] [] + +``` + + diff --git a/crates/biome_css_syntax/src/generated/kind.rs b/crates/biome_css_syntax/src/generated/kind.rs index cd080a2b600b..b4f646e7c153 100644 --- a/crates/biome_css_syntax/src/generated/kind.rs +++ b/crates/biome_css_syntax/src/generated/kind.rs @@ -100,6 +100,7 @@ pub enum CssSyntaxKind { VAR_KW, URL_KW, FONT_PALETTE_VALUES_KW, + AUTO_KW, INITIAL_KW, INHERIT_KW, UNSET_KW, @@ -238,9 +239,11 @@ pub enum CssSyntaxKind { CSS_GENERIC_COMPONENT_VALUE_LIST, CSS_GENERIC_DELIMITER, CSS_GENERIC_PROPERTY, + CSS_UNKNOWN_PROPERTY_VALUE, + CSS_ALL_PROPERTY, + CSS_Z_INDEX_PROPERTY, CSS_PARAMETER_LIST, CSS_DECLARATION_IMPORTANT, - CSS_UNIT, CSS_REGULAR_DIMENSION, CSS_UNKNOWN_DIMENSION, CSS_NAMESPACE, @@ -290,6 +293,8 @@ pub enum CssSyntaxKind { CSS_URL_VALUE_RAW, CSS_URL_FUNCTION, CSS_COLOR, + CSS_AUTO, + CSS_WIDE_KEYWORD, CSS_AT_RULE, CSS_CHARSET_AT_RULE, CSS_COLOR_PROFILE_AT_RULE, @@ -377,6 +382,7 @@ pub enum CssSyntaxKind { CSS_BOGUS_COMPONENT_VALUE, CSS_BOGUS_PARAMETER, CSS_BOGUS_PROPERTY, + CSS_BOGUS_PROPERTY_VALUE, CSS_BOGUS_MEDIA_QUERY, CSS_BOGUS_SCOPE_RANGE, #[doc(hidden)] @@ -486,6 +492,7 @@ impl CssSyntaxKind { "var" => VAR_KW, "url" => URL_KW, "font-palette-values" => FONT_PALETTE_VALUES_KW, + "auto" => AUTO_KW, "initial" => INITIAL_KW, "inherit" => INHERIT_KW, "unset" => UNSET_KW, @@ -676,6 +683,7 @@ impl CssSyntaxKind { VAR_KW => "var", URL_KW => "url", FONT_PALETTE_VALUES_KW => "font-palette-values", + AUTO_KW => "auto", INITIAL_KW => "initial", INHERIT_KW => "inherit", UNSET_KW => "unset", @@ -781,4 +789,4 @@ impl CssSyntaxKind { } #[doc = r" Utility macro for creating a SyntaxKind through simple macro syntax"] #[macro_export] -macro_rules ! T { [;] => { $ crate :: CssSyntaxKind :: SEMICOLON } ; [,] => { $ crate :: CssSyntaxKind :: COMMA } ; ['('] => { $ crate :: CssSyntaxKind :: L_PAREN } ; [')'] => { $ crate :: CssSyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: CssSyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: CssSyntaxKind :: R_CURLY } ; ['['] => { $ crate :: CssSyntaxKind :: L_BRACK } ; [']'] => { $ crate :: CssSyntaxKind :: R_BRACK } ; [<] => { $ crate :: CssSyntaxKind :: L_ANGLE } ; [>] => { $ crate :: CssSyntaxKind :: R_ANGLE } ; [~] => { $ crate :: CssSyntaxKind :: TILDE } ; [#] => { $ crate :: CssSyntaxKind :: HASH } ; [&] => { $ crate :: CssSyntaxKind :: AMP } ; [|] => { $ crate :: CssSyntaxKind :: PIPE } ; [||] => { $ crate :: CssSyntaxKind :: PIPE2 } ; [+] => { $ crate :: CssSyntaxKind :: PLUS } ; [*] => { $ crate :: CssSyntaxKind :: STAR } ; [/] => { $ crate :: CssSyntaxKind :: SLASH } ; [^] => { $ crate :: CssSyntaxKind :: CARET } ; [%] => { $ crate :: CssSyntaxKind :: PERCENT } ; [.] => { $ crate :: CssSyntaxKind :: DOT } ; [:] => { $ crate :: CssSyntaxKind :: COLON } ; [::] => { $ crate :: CssSyntaxKind :: COLON2 } ; [=] => { $ crate :: CssSyntaxKind :: EQ } ; [!] => { $ crate :: CssSyntaxKind :: BANG } ; [!=] => { $ crate :: CssSyntaxKind :: NEQ } ; [-] => { $ crate :: CssSyntaxKind :: MINUS } ; [<=] => { $ crate :: CssSyntaxKind :: LTEQ } ; [>=] => { $ crate :: CssSyntaxKind :: GTEQ } ; [+=] => { $ crate :: CssSyntaxKind :: PLUSEQ } ; [|=] => { $ crate :: CssSyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: CssSyntaxKind :: AMPEQ } ; [^=] => { $ crate :: CssSyntaxKind :: CARETEQ } ; [/=] => { $ crate :: CssSyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: CssSyntaxKind :: STAREQ } ; [%=] => { $ crate :: CssSyntaxKind :: PERCENTEQ } ; [@] => { $ crate :: CssSyntaxKind :: AT } ; ["$="] => { $ crate :: CssSyntaxKind :: DOLLAR_EQ } ; [~=] => { $ crate :: CssSyntaxKind :: TILDE_EQ } ; [-->] => { $ crate :: CssSyntaxKind :: CDC } ; [] => { $ crate :: CssSyntaxKind :: CDC } ; [