refactor(css_parser): flatten AnyCssDeclarationWithSemicolon (#6912) (#6879)
Some checks are pending
Benchmarks / Bench (push) Waiting to run
CI on main / Format Rust Files (push) Waiting to run
CI on main / Lint Rust Files (push) Waiting to run
CI on main / Check Dependencies (push) Waiting to run
CI on main / Test (push) Waiting to run
CI on main / Test262 Coverage (push) Waiting to run
Release / Release (push) Waiting to run
Release / version (push) Blocked by required conditions
Release / Package darwin-arm64 (push) Blocked by required conditions
Release / Package darwin-x64 (push) Blocked by required conditions
Release / Package linux-arm64-musl (push) Blocked by required conditions
Release / Package linux-x64-musl (push) Blocked by required conditions
Release / Package win32-arm64 (push) Blocked by required conditions
Release / Package win32-x64 (push) Blocked by required conditions
Release / Package linux-arm64 (push) Blocked by required conditions
Release / Package linux-x64 (push) Blocked by required conditions
Release / Build WASM (push) Blocked by required conditions
Release / Package JavaScript APIs (push) Blocked by required conditions
Release / Publish CLI (push) Blocked by required conditions
Release / Publish JS API (push) Blocked by required conditions
Repository dispatch on main / Build @biomejs/wasm-web (push) Waiting to run
Repository dispatch on main / Repository dispatch (push) Blocked by required conditions

This commit is contained in:
Denis Bezrukov 2025-07-14 14:36:45 +03:00 committed by GitHub
parent 5ff50f8291
commit 0059cd9b5e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 323 additions and 257 deletions

View file

@ -0,0 +1,18 @@
---
"@biomejs/biome": patch
---
Refactor: remove one level of indirection for CSS declarations with semicolon
Previously, accessing a declaration from a list required an extra step:
```rust
item
.as_any_css_declaration_with_semicolon()
.as_css_declaration_with_semicolon()
```
Now, it can be done directly with:
```rust
item.as_css_declaration_with_semicolon()
```

View file

@ -248,12 +248,8 @@ impl RecessOrderMember {
AnyCssRule::CssNestedQualifiedRule(_) => NodeKindOrder::NestedRuleOrAtRule,
AnyCssRule::CssQualifiedRule(_) => NodeKindOrder::UnknownKind,
},
AnyCssDeclarationOrRule::AnyCssDeclarationWithSemicolon(any_decl_with_semicolon) => {
let Some(decl_with_semicolon) =
any_decl_with_semicolon.as_css_declaration_with_semicolon()
else {
return NodeKindOrder::UnknownKind;
};
AnyCssDeclarationOrRule::CssEmptyDeclaration(_) => NodeKindOrder::UnknownKind,
AnyCssDeclarationOrRule::CssDeclarationWithSemicolon(decl_with_semicolon) => {
let Some(decl) = decl_with_semicolon.declaration().ok() else {
return NodeKindOrder::UnknownKind;
};
@ -284,8 +280,7 @@ impl RecessOrderMember {
pub fn property_index(&self) -> usize {
let Some(prop_text) = &self
.0
.as_any_css_declaration_with_semicolon()
.and_then(|decl| decl.as_css_declaration_with_semicolon())
.as_css_declaration_with_semicolon()
.and_then(css_declaration_to_prop_text)
else {
return usize::MAX;
@ -300,8 +295,7 @@ impl RecessOrderMember {
pub fn vendor_prefix_index(&self) -> usize {
let Some(prop_text) = &self
.0
.as_any_css_declaration_with_semicolon()
.and_then(|decl| decl.as_css_declaration_with_semicolon())
.as_css_declaration_with_semicolon()
.and_then(css_declaration_to_prop_text)
else {
return usize::MAX;
@ -408,8 +402,7 @@ fn contains_shorthand_after_longhand(nodes: &[AnyCssDeclarationOrRule]) -> bool
// Starting from the bottom, when we see a shorthand property, record the set of longhand properties that are no longer allowed to appear above it.
for node in nodes.iter().rev() {
let Some(prop_text) = &node
.as_any_css_declaration_with_semicolon()
.and_then(|decl| decl.as_css_declaration_with_semicolon())
.as_css_declaration_with_semicolon()
.and_then(css_declaration_to_prop_text)
else {
continue;
@ -442,8 +435,7 @@ fn contains_shorthand_after_longhand(nodes: &[AnyCssDeclarationOrRule]) -> bool
fn contains_unknown_property(nodes: &[AnyCssDeclarationOrRule]) -> bool {
for node in nodes.iter() {
let Some(prop_text) = &node
.as_any_css_declaration_with_semicolon()
.and_then(|decl| decl.as_css_declaration_with_semicolon())
.as_css_declaration_with_semicolon()
.and_then(css_declaration_to_prop_text)
else {
continue;

View file

@ -91,7 +91,6 @@ impl Rule for NoInvalidGridAreas {
.into_iter()
.filter_map(|item| {
let binding = item
.as_any_css_declaration_with_semicolon()?
.as_css_declaration_with_semicolon()?
.declaration()
.ok()?

View file

@ -2419,7 +2419,7 @@ where
}
pub fn css_declaration_list<I>(items: I) -> CssDeclarationList
where
I: IntoIterator<Item = AnyCssDeclarationWithSemicolon>,
I: IntoIterator<Item = AnyCssDeclaration>,
I::IntoIter: ExactSizeIterator,
{
CssDeclarationList::unwrap_cast(SyntaxNode::new_detached(

View file

@ -4824,11 +4824,9 @@ impl SyntaxFactory for CssSyntaxFactory {
CSS_CUSTOM_IDENTIFIER_LIST => {
Self::make_node_list_syntax(kind, children, AnyCssCustomIdentifier::can_cast)
}
CSS_DECLARATION_LIST => Self::make_node_list_syntax(
kind,
children,
AnyCssDeclarationWithSemicolon::can_cast,
),
CSS_DECLARATION_LIST => {
Self::make_node_list_syntax(kind, children, AnyCssDeclaration::can_cast)
}
CSS_DECLARATION_OR_AT_RULE_LIST => {
Self::make_node_list_syntax(kind, children, AnyCssDeclarationOrAtRule::can_cast)
}

View file

@ -0,0 +1,15 @@
//! 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::AnyCssDeclaration;
#[derive(Debug, Clone, Default)]
pub(crate) struct FormatAnyCssDeclaration;
impl FormatRule<AnyCssDeclaration> for FormatAnyCssDeclaration {
type Context = CssFormatContext;
fn fmt(&self, node: &AnyCssDeclaration, f: &mut CssFormatter) -> FormatResult<()> {
match node {
AnyCssDeclaration::CssDeclarationWithSemicolon(node) => node.format().fmt(f),
AnyCssDeclaration::CssEmptyDeclaration(node) => node.format().fmt(f),
}
}
}

View file

@ -8,8 +8,9 @@ impl FormatRule<AnyCssDeclarationOrAtRule> for FormatAnyCssDeclarationOrAtRule {
type Context = CssFormatContext;
fn fmt(&self, node: &AnyCssDeclarationOrAtRule, f: &mut CssFormatter) -> FormatResult<()> {
match node {
AnyCssDeclarationOrAtRule::AnyCssDeclarationWithSemicolon(node) => node.format().fmt(f),
AnyCssDeclarationOrAtRule::CssAtRule(node) => node.format().fmt(f),
AnyCssDeclarationOrAtRule::CssDeclarationWithSemicolon(node) => node.format().fmt(f),
AnyCssDeclarationOrAtRule::CssEmptyDeclaration(node) => node.format().fmt(f),
}
}
}

View file

@ -8,9 +8,10 @@ impl FormatRule<AnyCssDeclarationOrRule> for FormatAnyCssDeclarationOrRule {
type Context = CssFormatContext;
fn fmt(&self, node: &AnyCssDeclarationOrRule, f: &mut CssFormatter) -> FormatResult<()> {
match node {
AnyCssDeclarationOrRule::AnyCssDeclarationWithSemicolon(node) => node.format().fmt(f),
AnyCssDeclarationOrRule::AnyCssRule(node) => node.format().fmt(f),
AnyCssDeclarationOrRule::CssBogus(node) => node.format().fmt(f),
AnyCssDeclarationOrRule::CssDeclarationWithSemicolon(node) => node.format().fmt(f),
AnyCssDeclarationOrRule::CssEmptyDeclaration(node) => node.format().fmt(f),
AnyCssDeclarationOrRule::CssMetavariable(node) => node.format().fmt(f),
}
}

View file

@ -1,17 +0,0 @@
//! 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::AnyCssDeclarationWithSemicolon;
#[derive(Debug, Clone, Default)]
pub(crate) struct FormatAnyCssDeclarationWithSemicolon;
impl FormatRule<AnyCssDeclarationWithSemicolon> for FormatAnyCssDeclarationWithSemicolon {
type Context = CssFormatContext;
fn fmt(&self, node: &AnyCssDeclarationWithSemicolon, f: &mut CssFormatter) -> FormatResult<()> {
match node {
AnyCssDeclarationWithSemicolon::CssDeclarationWithSemicolon(node) => {
node.format().fmt(f)
}
AnyCssDeclarationWithSemicolon::CssEmptyDeclaration(node) => node.format().fmt(f),
}
}
}

View file

@ -14,13 +14,13 @@ pub(crate) mod container_style_in_parens;
pub(crate) mod container_style_or_combinable_query;
pub(crate) mod container_style_query;
pub(crate) mod custom_identifier;
pub(crate) mod declaration;
pub(crate) mod declaration_block;
pub(crate) mod declaration_name;
pub(crate) mod declaration_or_at_rule;
pub(crate) mod declaration_or_at_rule_block;
pub(crate) mod declaration_or_rule;
pub(crate) mod declaration_or_rule_block;
pub(crate) mod declaration_with_semicolon;
pub(crate) mod dimension;
pub(crate) mod document_matcher;
pub(crate) mod expression;

View file

@ -8,8 +8,9 @@ impl FormatRule<AnyCssPageAtRuleItem> for FormatAnyCssPageAtRuleItem {
type Context = CssFormatContext;
fn fmt(&self, node: &AnyCssPageAtRuleItem, f: &mut CssFormatter) -> FormatResult<()> {
match node {
AnyCssPageAtRuleItem::AnyCssDeclarationWithSemicolon(node) => node.format().fmt(f),
AnyCssPageAtRuleItem::CssAtRule(node) => node.format().fmt(f),
AnyCssPageAtRuleItem::CssDeclarationWithSemicolon(node) => node.format().fmt(f),
AnyCssPageAtRuleItem::CssEmptyDeclaration(node) => node.format().fmt(f),
AnyCssPageAtRuleItem::CssMarginAtRule(node) => node.format().fmt(f),
}
}

View file

@ -7502,6 +7502,31 @@ impl IntoFormat<CssFormatContext> for biome_css_syntax::AnyCssCustomIdentifier {
)
}
}
impl AsFormat<CssFormatContext> for biome_css_syntax::AnyCssDeclaration {
type Format<'a> = FormatRefWithRule<
'a,
biome_css_syntax::AnyCssDeclaration,
crate::css::any::declaration::FormatAnyCssDeclaration,
>;
fn format(&self) -> Self::Format<'_> {
FormatRefWithRule::new(
self,
crate::css::any::declaration::FormatAnyCssDeclaration::default(),
)
}
}
impl IntoFormat<CssFormatContext> for biome_css_syntax::AnyCssDeclaration {
type Format = FormatOwnedWithRule<
biome_css_syntax::AnyCssDeclaration,
crate::css::any::declaration::FormatAnyCssDeclaration,
>;
fn into_format(self) -> Self::Format {
FormatOwnedWithRule::new(
self,
crate::css::any::declaration::FormatAnyCssDeclaration::default(),
)
}
}
impl AsFormat<CssFormatContext> for biome_css_syntax::AnyCssDeclarationBlock {
type Format<'a> = FormatRefWithRule<
'a,
@ -7648,25 +7673,6 @@ impl IntoFormat<CssFormatContext> for biome_css_syntax::AnyCssDeclarationOrRuleB
)
}
}
impl AsFormat<CssFormatContext> for biome_css_syntax::AnyCssDeclarationWithSemicolon {
type Format<'a> = FormatRefWithRule<
'a,
biome_css_syntax::AnyCssDeclarationWithSemicolon,
crate::css::any::declaration_with_semicolon::FormatAnyCssDeclarationWithSemicolon,
>;
fn format(&self) -> Self::Format<'_> {
FormatRefWithRule :: new (self , crate :: css :: any :: declaration_with_semicolon :: FormatAnyCssDeclarationWithSemicolon :: default ())
}
}
impl IntoFormat<CssFormatContext> for biome_css_syntax::AnyCssDeclarationWithSemicolon {
type Format = FormatOwnedWithRule<
biome_css_syntax::AnyCssDeclarationWithSemicolon,
crate::css::any::declaration_with_semicolon::FormatAnyCssDeclarationWithSemicolon,
>;
fn into_format(self) -> Self::Format {
FormatOwnedWithRule :: new (self , crate :: css :: any :: declaration_with_semicolon :: FormatAnyCssDeclarationWithSemicolon :: default ())
}
}
impl AsFormat<CssFormatContext> for biome_css_syntax::AnyCssDimension {
type Format<'a> = FormatRefWithRule<
'a,

View file

@ -7256,6 +7256,25 @@ impl AnyCssCustomIdentifier {
}
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize)]
pub enum AnyCssDeclaration {
CssDeclarationWithSemicolon(CssDeclarationWithSemicolon),
CssEmptyDeclaration(CssEmptyDeclaration),
}
impl AnyCssDeclaration {
pub fn as_css_declaration_with_semicolon(&self) -> Option<&CssDeclarationWithSemicolon> {
match &self {
Self::CssDeclarationWithSemicolon(item) => Some(item),
_ => None,
}
}
pub fn as_css_empty_declaration(&self) -> Option<&CssEmptyDeclaration> {
match &self {
Self::CssEmptyDeclaration(item) => Some(item),
_ => None,
}
}
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize)]
pub enum AnyCssDeclarationBlock {
CssBogusBlock(CssBogusBlock),
CssDeclarationBlock(CssDeclarationBlock),
@ -7295,22 +7314,29 @@ impl AnyCssDeclarationName {
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize)]
pub enum AnyCssDeclarationOrAtRule {
AnyCssDeclarationWithSemicolon(AnyCssDeclarationWithSemicolon),
CssAtRule(CssAtRule),
CssDeclarationWithSemicolon(CssDeclarationWithSemicolon),
CssEmptyDeclaration(CssEmptyDeclaration),
}
impl AnyCssDeclarationOrAtRule {
pub fn as_any_css_declaration_with_semicolon(&self) -> Option<&AnyCssDeclarationWithSemicolon> {
match &self {
Self::AnyCssDeclarationWithSemicolon(item) => Some(item),
_ => None,
}
}
pub fn as_css_at_rule(&self) -> Option<&CssAtRule> {
match &self {
Self::CssAtRule(item) => Some(item),
_ => None,
}
}
pub fn as_css_declaration_with_semicolon(&self) -> Option<&CssDeclarationWithSemicolon> {
match &self {
Self::CssDeclarationWithSemicolon(item) => Some(item),
_ => None,
}
}
pub fn as_css_empty_declaration(&self) -> Option<&CssEmptyDeclaration> {
match &self {
Self::CssEmptyDeclaration(item) => Some(item),
_ => None,
}
}
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize)]
pub enum AnyCssDeclarationOrAtRuleBlock {
@ -7333,18 +7359,13 @@ impl AnyCssDeclarationOrAtRuleBlock {
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize)]
pub enum AnyCssDeclarationOrRule {
AnyCssDeclarationWithSemicolon(AnyCssDeclarationWithSemicolon),
AnyCssRule(AnyCssRule),
CssBogus(CssBogus),
CssDeclarationWithSemicolon(CssDeclarationWithSemicolon),
CssEmptyDeclaration(CssEmptyDeclaration),
CssMetavariable(CssMetavariable),
}
impl AnyCssDeclarationOrRule {
pub fn as_any_css_declaration_with_semicolon(&self) -> Option<&AnyCssDeclarationWithSemicolon> {
match &self {
Self::AnyCssDeclarationWithSemicolon(item) => Some(item),
_ => None,
}
}
pub fn as_any_css_rule(&self) -> Option<&AnyCssRule> {
match &self {
Self::AnyCssRule(item) => Some(item),
@ -7357,6 +7378,18 @@ impl AnyCssDeclarationOrRule {
_ => None,
}
}
pub fn as_css_declaration_with_semicolon(&self) -> Option<&CssDeclarationWithSemicolon> {
match &self {
Self::CssDeclarationWithSemicolon(item) => Some(item),
_ => None,
}
}
pub fn as_css_empty_declaration(&self) -> Option<&CssEmptyDeclaration> {
match &self {
Self::CssEmptyDeclaration(item) => Some(item),
_ => None,
}
}
pub fn as_css_metavariable(&self) -> Option<&CssMetavariable> {
match &self {
Self::CssMetavariable(item) => Some(item),
@ -7384,25 +7417,6 @@ impl AnyCssDeclarationOrRuleBlock {
}
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize)]
pub enum AnyCssDeclarationWithSemicolon {
CssDeclarationWithSemicolon(CssDeclarationWithSemicolon),
CssEmptyDeclaration(CssEmptyDeclaration),
}
impl AnyCssDeclarationWithSemicolon {
pub fn as_css_declaration_with_semicolon(&self) -> Option<&CssDeclarationWithSemicolon> {
match &self {
Self::CssDeclarationWithSemicolon(item) => Some(item),
_ => None,
}
}
pub fn as_css_empty_declaration(&self) -> Option<&CssEmptyDeclaration> {
match &self {
Self::CssEmptyDeclaration(item) => Some(item),
_ => None,
}
}
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize)]
pub enum AnyCssDimension {
CssPercentage(CssPercentage),
CssRegularDimension(CssRegularDimension),
@ -8022,23 +8036,30 @@ impl AnyCssPageAtRuleBlock {
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize)]
pub enum AnyCssPageAtRuleItem {
AnyCssDeclarationWithSemicolon(AnyCssDeclarationWithSemicolon),
CssAtRule(CssAtRule),
CssDeclarationWithSemicolon(CssDeclarationWithSemicolon),
CssEmptyDeclaration(CssEmptyDeclaration),
CssMarginAtRule(CssMarginAtRule),
}
impl AnyCssPageAtRuleItem {
pub fn as_any_css_declaration_with_semicolon(&self) -> Option<&AnyCssDeclarationWithSemicolon> {
match &self {
Self::AnyCssDeclarationWithSemicolon(item) => Some(item),
_ => None,
}
}
pub fn as_css_at_rule(&self) -> Option<&CssAtRule> {
match &self {
Self::CssAtRule(item) => Some(item),
_ => None,
}
}
pub fn as_css_declaration_with_semicolon(&self) -> Option<&CssDeclarationWithSemicolon> {
match &self {
Self::CssDeclarationWithSemicolon(item) => Some(item),
_ => None,
}
}
pub fn as_css_empty_declaration(&self) -> Option<&CssEmptyDeclaration> {
match &self {
Self::CssEmptyDeclaration(item) => Some(item),
_ => None,
}
}
pub fn as_css_margin_at_rule(&self) -> Option<&CssMarginAtRule> {
match &self {
Self::CssMarginAtRule(item) => Some(item),
@ -18404,6 +18425,68 @@ impl From<AnyCssCustomIdentifier> for SyntaxElement {
node.into()
}
}
impl From<CssDeclarationWithSemicolon> for AnyCssDeclaration {
fn from(node: CssDeclarationWithSemicolon) -> Self {
Self::CssDeclarationWithSemicolon(node)
}
}
impl From<CssEmptyDeclaration> for AnyCssDeclaration {
fn from(node: CssEmptyDeclaration) -> Self {
Self::CssEmptyDeclaration(node)
}
}
impl AstNode for AnyCssDeclaration {
type Language = Language;
const KIND_SET: SyntaxKindSet<Language> =
CssDeclarationWithSemicolon::KIND_SET.union(CssEmptyDeclaration::KIND_SET);
fn can_cast(kind: SyntaxKind) -> bool {
matches!(kind, CSS_DECLARATION_WITH_SEMICOLON | CSS_EMPTY_DECLARATION)
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
let res = match syntax.kind() {
CSS_DECLARATION_WITH_SEMICOLON => {
Self::CssDeclarationWithSemicolon(CssDeclarationWithSemicolon { syntax })
}
CSS_EMPTY_DECLARATION => Self::CssEmptyDeclaration(CssEmptyDeclaration { syntax }),
_ => return None,
};
Some(res)
}
fn syntax(&self) -> &SyntaxNode {
match self {
Self::CssDeclarationWithSemicolon(it) => &it.syntax,
Self::CssEmptyDeclaration(it) => &it.syntax,
}
}
fn into_syntax(self) -> SyntaxNode {
match self {
Self::CssDeclarationWithSemicolon(it) => it.syntax,
Self::CssEmptyDeclaration(it) => it.syntax,
}
}
}
impl std::fmt::Debug for AnyCssDeclaration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::CssDeclarationWithSemicolon(it) => std::fmt::Debug::fmt(it, f),
Self::CssEmptyDeclaration(it) => std::fmt::Debug::fmt(it, f),
}
}
}
impl From<AnyCssDeclaration> for SyntaxNode {
fn from(n: AnyCssDeclaration) -> Self {
match n {
AnyCssDeclaration::CssDeclarationWithSemicolon(it) => it.into(),
AnyCssDeclaration::CssEmptyDeclaration(it) => it.into(),
}
}
}
impl From<AnyCssDeclaration> for SyntaxElement {
fn from(n: AnyCssDeclaration) -> Self {
let node: SyntaxNode = n.into();
node.into()
}
}
impl From<CssBogusBlock> for AnyCssDeclarationBlock {
fn from(node: CssBogusBlock) -> Self {
Self::CssBogusBlock(node)
@ -18529,59 +18612,68 @@ impl From<CssAtRule> for AnyCssDeclarationOrAtRule {
Self::CssAtRule(node)
}
}
impl From<CssDeclarationWithSemicolon> for AnyCssDeclarationOrAtRule {
fn from(node: CssDeclarationWithSemicolon) -> Self {
Self::CssDeclarationWithSemicolon(node)
}
}
impl From<CssEmptyDeclaration> for AnyCssDeclarationOrAtRule {
fn from(node: CssEmptyDeclaration) -> Self {
Self::CssEmptyDeclaration(node)
}
}
impl AstNode for AnyCssDeclarationOrAtRule {
type Language = Language;
const KIND_SET: SyntaxKindSet<Language> =
AnyCssDeclarationWithSemicolon::KIND_SET.union(CssAtRule::KIND_SET);
const KIND_SET: SyntaxKindSet<Language> = CssAtRule::KIND_SET
.union(CssDeclarationWithSemicolon::KIND_SET)
.union(CssEmptyDeclaration::KIND_SET);
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
CSS_AT_RULE => true,
k if AnyCssDeclarationWithSemicolon::can_cast(k) => true,
_ => false,
}
matches!(
kind,
CSS_AT_RULE | CSS_DECLARATION_WITH_SEMICOLON | CSS_EMPTY_DECLARATION
)
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
let res = match syntax.kind() {
CSS_AT_RULE => Self::CssAtRule(CssAtRule { syntax }),
_ => {
if let Some(any_css_declaration_with_semicolon) =
AnyCssDeclarationWithSemicolon::cast(syntax)
{
return Some(Self::AnyCssDeclarationWithSemicolon(
any_css_declaration_with_semicolon,
));
}
return None;
CSS_DECLARATION_WITH_SEMICOLON => {
Self::CssDeclarationWithSemicolon(CssDeclarationWithSemicolon { syntax })
}
CSS_EMPTY_DECLARATION => Self::CssEmptyDeclaration(CssEmptyDeclaration { syntax }),
_ => return None,
};
Some(res)
}
fn syntax(&self) -> &SyntaxNode {
match self {
Self::CssAtRule(it) => &it.syntax,
Self::AnyCssDeclarationWithSemicolon(it) => it.syntax(),
Self::CssDeclarationWithSemicolon(it) => &it.syntax,
Self::CssEmptyDeclaration(it) => &it.syntax,
}
}
fn into_syntax(self) -> SyntaxNode {
match self {
Self::CssAtRule(it) => it.syntax,
Self::AnyCssDeclarationWithSemicolon(it) => it.into_syntax(),
Self::CssDeclarationWithSemicolon(it) => it.syntax,
Self::CssEmptyDeclaration(it) => it.syntax,
}
}
}
impl std::fmt::Debug for AnyCssDeclarationOrAtRule {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::AnyCssDeclarationWithSemicolon(it) => std::fmt::Debug::fmt(it, f),
Self::CssAtRule(it) => std::fmt::Debug::fmt(it, f),
Self::CssDeclarationWithSemicolon(it) => std::fmt::Debug::fmt(it, f),
Self::CssEmptyDeclaration(it) => std::fmt::Debug::fmt(it, f),
}
}
}
impl From<AnyCssDeclarationOrAtRule> for SyntaxNode {
fn from(n: AnyCssDeclarationOrAtRule) -> Self {
match n {
AnyCssDeclarationOrAtRule::AnyCssDeclarationWithSemicolon(it) => it.into(),
AnyCssDeclarationOrAtRule::CssAtRule(it) => it.into(),
AnyCssDeclarationOrAtRule::CssDeclarationWithSemicolon(it) => it.into(),
AnyCssDeclarationOrAtRule::CssEmptyDeclaration(it) => it.into(),
}
}
}
@ -18658,6 +18750,16 @@ impl From<CssBogus> for AnyCssDeclarationOrRule {
Self::CssBogus(node)
}
}
impl From<CssDeclarationWithSemicolon> for AnyCssDeclarationOrRule {
fn from(node: CssDeclarationWithSemicolon) -> Self {
Self::CssDeclarationWithSemicolon(node)
}
}
impl From<CssEmptyDeclaration> for AnyCssDeclarationOrRule {
fn from(node: CssEmptyDeclaration) -> Self {
Self::CssEmptyDeclaration(node)
}
}
impl From<CssMetavariable> for AnyCssDeclarationOrRule {
fn from(node: CssMetavariable) -> Self {
Self::CssMetavariable(node)
@ -18665,14 +18767,17 @@ impl From<CssMetavariable> for AnyCssDeclarationOrRule {
}
impl AstNode for AnyCssDeclarationOrRule {
type Language = Language;
const KIND_SET: SyntaxKindSet<Language> = AnyCssDeclarationWithSemicolon::KIND_SET
.union(AnyCssRule::KIND_SET)
const KIND_SET: SyntaxKindSet<Language> = AnyCssRule::KIND_SET
.union(CssBogus::KIND_SET)
.union(CssDeclarationWithSemicolon::KIND_SET)
.union(CssEmptyDeclaration::KIND_SET)
.union(CssMetavariable::KIND_SET);
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
CSS_BOGUS | CSS_METAVARIABLE => true,
k if AnyCssDeclarationWithSemicolon::can_cast(k) => true,
CSS_BOGUS
| CSS_DECLARATION_WITH_SEMICOLON
| CSS_EMPTY_DECLARATION
| CSS_METAVARIABLE => true,
k if AnyCssRule::can_cast(k) => true,
_ => false,
}
@ -18680,16 +18785,12 @@ impl AstNode for AnyCssDeclarationOrRule {
fn cast(syntax: SyntaxNode) -> Option<Self> {
let res = match syntax.kind() {
CSS_BOGUS => Self::CssBogus(CssBogus { syntax }),
CSS_DECLARATION_WITH_SEMICOLON => {
Self::CssDeclarationWithSemicolon(CssDeclarationWithSemicolon { syntax })
}
CSS_EMPTY_DECLARATION => Self::CssEmptyDeclaration(CssEmptyDeclaration { syntax }),
CSS_METAVARIABLE => Self::CssMetavariable(CssMetavariable { syntax }),
_ => {
let syntax = match AnyCssDeclarationWithSemicolon::try_cast(syntax) {
Ok(any_css_declaration_with_semicolon) => {
return Some(Self::AnyCssDeclarationWithSemicolon(
any_css_declaration_with_semicolon,
));
}
Err(syntax) => syntax,
};
if let Some(any_css_rule) = AnyCssRule::cast(syntax) {
return Some(Self::AnyCssRule(any_css_rule));
}
@ -18701,16 +18802,18 @@ impl AstNode for AnyCssDeclarationOrRule {
fn syntax(&self) -> &SyntaxNode {
match self {
Self::CssBogus(it) => &it.syntax,
Self::CssDeclarationWithSemicolon(it) => &it.syntax,
Self::CssEmptyDeclaration(it) => &it.syntax,
Self::CssMetavariable(it) => &it.syntax,
Self::AnyCssDeclarationWithSemicolon(it) => it.syntax(),
Self::AnyCssRule(it) => it.syntax(),
}
}
fn into_syntax(self) -> SyntaxNode {
match self {
Self::CssBogus(it) => it.syntax,
Self::CssDeclarationWithSemicolon(it) => it.syntax,
Self::CssEmptyDeclaration(it) => it.syntax,
Self::CssMetavariable(it) => it.syntax,
Self::AnyCssDeclarationWithSemicolon(it) => it.into_syntax(),
Self::AnyCssRule(it) => it.into_syntax(),
}
}
@ -18718,9 +18821,10 @@ impl AstNode for AnyCssDeclarationOrRule {
impl std::fmt::Debug for AnyCssDeclarationOrRule {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::AnyCssDeclarationWithSemicolon(it) => std::fmt::Debug::fmt(it, f),
Self::AnyCssRule(it) => std::fmt::Debug::fmt(it, f),
Self::CssBogus(it) => std::fmt::Debug::fmt(it, f),
Self::CssDeclarationWithSemicolon(it) => std::fmt::Debug::fmt(it, f),
Self::CssEmptyDeclaration(it) => std::fmt::Debug::fmt(it, f),
Self::CssMetavariable(it) => std::fmt::Debug::fmt(it, f),
}
}
@ -18728,9 +18832,10 @@ impl std::fmt::Debug for AnyCssDeclarationOrRule {
impl From<AnyCssDeclarationOrRule> for SyntaxNode {
fn from(n: AnyCssDeclarationOrRule) -> Self {
match n {
AnyCssDeclarationOrRule::AnyCssDeclarationWithSemicolon(it) => it.into(),
AnyCssDeclarationOrRule::AnyCssRule(it) => it.into(),
AnyCssDeclarationOrRule::CssBogus(it) => it.into(),
AnyCssDeclarationOrRule::CssDeclarationWithSemicolon(it) => it.into(),
AnyCssDeclarationOrRule::CssEmptyDeclaration(it) => it.into(),
AnyCssDeclarationOrRule::CssMetavariable(it) => it.into(),
}
}
@ -18803,68 +18908,6 @@ impl From<AnyCssDeclarationOrRuleBlock> for SyntaxElement {
node.into()
}
}
impl From<CssDeclarationWithSemicolon> for AnyCssDeclarationWithSemicolon {
fn from(node: CssDeclarationWithSemicolon) -> Self {
Self::CssDeclarationWithSemicolon(node)
}
}
impl From<CssEmptyDeclaration> for AnyCssDeclarationWithSemicolon {
fn from(node: CssEmptyDeclaration) -> Self {
Self::CssEmptyDeclaration(node)
}
}
impl AstNode for AnyCssDeclarationWithSemicolon {
type Language = Language;
const KIND_SET: SyntaxKindSet<Language> =
CssDeclarationWithSemicolon::KIND_SET.union(CssEmptyDeclaration::KIND_SET);
fn can_cast(kind: SyntaxKind) -> bool {
matches!(kind, CSS_DECLARATION_WITH_SEMICOLON | CSS_EMPTY_DECLARATION)
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
let res = match syntax.kind() {
CSS_DECLARATION_WITH_SEMICOLON => {
Self::CssDeclarationWithSemicolon(CssDeclarationWithSemicolon { syntax })
}
CSS_EMPTY_DECLARATION => Self::CssEmptyDeclaration(CssEmptyDeclaration { syntax }),
_ => return None,
};
Some(res)
}
fn syntax(&self) -> &SyntaxNode {
match self {
Self::CssDeclarationWithSemicolon(it) => &it.syntax,
Self::CssEmptyDeclaration(it) => &it.syntax,
}
}
fn into_syntax(self) -> SyntaxNode {
match self {
Self::CssDeclarationWithSemicolon(it) => it.syntax,
Self::CssEmptyDeclaration(it) => it.syntax,
}
}
}
impl std::fmt::Debug for AnyCssDeclarationWithSemicolon {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::CssDeclarationWithSemicolon(it) => std::fmt::Debug::fmt(it, f),
Self::CssEmptyDeclaration(it) => std::fmt::Debug::fmt(it, f),
}
}
}
impl From<AnyCssDeclarationWithSemicolon> for SyntaxNode {
fn from(n: AnyCssDeclarationWithSemicolon) -> Self {
match n {
AnyCssDeclarationWithSemicolon::CssDeclarationWithSemicolon(it) => it.into(),
AnyCssDeclarationWithSemicolon::CssEmptyDeclaration(it) => it.into(),
}
}
}
impl From<AnyCssDeclarationWithSemicolon> for SyntaxElement {
fn from(n: AnyCssDeclarationWithSemicolon) -> Self {
let node: SyntaxNode = n.into();
node.into()
}
}
impl From<CssPercentage> for AnyCssDimension {
fn from(node: CssPercentage) -> Self {
Self::CssPercentage(node)
@ -20782,6 +20825,16 @@ impl From<CssAtRule> for AnyCssPageAtRuleItem {
Self::CssAtRule(node)
}
}
impl From<CssDeclarationWithSemicolon> for AnyCssPageAtRuleItem {
fn from(node: CssDeclarationWithSemicolon) -> Self {
Self::CssDeclarationWithSemicolon(node)
}
}
impl From<CssEmptyDeclaration> for AnyCssPageAtRuleItem {
fn from(node: CssEmptyDeclaration) -> Self {
Self::CssEmptyDeclaration(node)
}
}
impl From<CssMarginAtRule> for AnyCssPageAtRuleItem {
fn from(node: CssMarginAtRule) -> Self {
Self::CssMarginAtRule(node)
@ -20789,53 +20842,54 @@ impl From<CssMarginAtRule> for AnyCssPageAtRuleItem {
}
impl AstNode for AnyCssPageAtRuleItem {
type Language = Language;
const KIND_SET: SyntaxKindSet<Language> = AnyCssDeclarationWithSemicolon::KIND_SET
.union(CssAtRule::KIND_SET)
const KIND_SET: SyntaxKindSet<Language> = CssAtRule::KIND_SET
.union(CssDeclarationWithSemicolon::KIND_SET)
.union(CssEmptyDeclaration::KIND_SET)
.union(CssMarginAtRule::KIND_SET);
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
CSS_AT_RULE | CSS_MARGIN_AT_RULE => true,
k if AnyCssDeclarationWithSemicolon::can_cast(k) => true,
_ => false,
}
matches!(
kind,
CSS_AT_RULE
| CSS_DECLARATION_WITH_SEMICOLON
| CSS_EMPTY_DECLARATION
| CSS_MARGIN_AT_RULE
)
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
let res = match syntax.kind() {
CSS_AT_RULE => Self::CssAtRule(CssAtRule { syntax }),
CSS_MARGIN_AT_RULE => Self::CssMarginAtRule(CssMarginAtRule { syntax }),
_ => {
if let Some(any_css_declaration_with_semicolon) =
AnyCssDeclarationWithSemicolon::cast(syntax)
{
return Some(Self::AnyCssDeclarationWithSemicolon(
any_css_declaration_with_semicolon,
));
}
return None;
CSS_DECLARATION_WITH_SEMICOLON => {
Self::CssDeclarationWithSemicolon(CssDeclarationWithSemicolon { syntax })
}
CSS_EMPTY_DECLARATION => Self::CssEmptyDeclaration(CssEmptyDeclaration { syntax }),
CSS_MARGIN_AT_RULE => Self::CssMarginAtRule(CssMarginAtRule { syntax }),
_ => return None,
};
Some(res)
}
fn syntax(&self) -> &SyntaxNode {
match self {
Self::CssAtRule(it) => &it.syntax,
Self::CssDeclarationWithSemicolon(it) => &it.syntax,
Self::CssEmptyDeclaration(it) => &it.syntax,
Self::CssMarginAtRule(it) => &it.syntax,
Self::AnyCssDeclarationWithSemicolon(it) => it.syntax(),
}
}
fn into_syntax(self) -> SyntaxNode {
match self {
Self::CssAtRule(it) => it.syntax,
Self::CssDeclarationWithSemicolon(it) => it.syntax,
Self::CssEmptyDeclaration(it) => it.syntax,
Self::CssMarginAtRule(it) => it.syntax,
Self::AnyCssDeclarationWithSemicolon(it) => it.into_syntax(),
}
}
}
impl std::fmt::Debug for AnyCssPageAtRuleItem {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::AnyCssDeclarationWithSemicolon(it) => std::fmt::Debug::fmt(it, f),
Self::CssAtRule(it) => std::fmt::Debug::fmt(it, f),
Self::CssDeclarationWithSemicolon(it) => std::fmt::Debug::fmt(it, f),
Self::CssEmptyDeclaration(it) => std::fmt::Debug::fmt(it, f),
Self::CssMarginAtRule(it) => std::fmt::Debug::fmt(it, f),
}
}
@ -20843,8 +20897,9 @@ impl std::fmt::Debug for AnyCssPageAtRuleItem {
impl From<AnyCssPageAtRuleItem> for SyntaxNode {
fn from(n: AnyCssPageAtRuleItem) -> Self {
match n {
AnyCssPageAtRuleItem::AnyCssDeclarationWithSemicolon(it) => it.into(),
AnyCssPageAtRuleItem::CssAtRule(it) => it.into(),
AnyCssPageAtRuleItem::CssDeclarationWithSemicolon(it) => it.into(),
AnyCssPageAtRuleItem::CssEmptyDeclaration(it) => it.into(),
AnyCssPageAtRuleItem::CssMarginAtRule(it) => it.into(),
}
}
@ -23380,6 +23435,11 @@ impl std::fmt::Display for AnyCssCustomIdentifier {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for AnyCssDeclaration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for AnyCssDeclarationBlock {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
@ -23410,11 +23470,6 @@ impl std::fmt::Display for AnyCssDeclarationOrRuleBlock {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for AnyCssDeclarationWithSemicolon {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for AnyCssDimension {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
@ -26477,7 +26532,7 @@ impl Serialize for CssDeclarationList {
}
impl AstNodeList for CssDeclarationList {
type Language = Language;
type Node = AnyCssDeclarationWithSemicolon;
type Node = AnyCssDeclaration;
fn syntax_list(&self) -> &SyntaxList {
&self.syntax_list
}
@ -26492,15 +26547,15 @@ impl Debug for CssDeclarationList {
}
}
impl IntoIterator for &CssDeclarationList {
type Item = AnyCssDeclarationWithSemicolon;
type IntoIter = AstNodeListIterator<Language, AnyCssDeclarationWithSemicolon>;
type Item = AnyCssDeclaration;
type IntoIter = AstNodeListIterator<Language, AnyCssDeclaration>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl IntoIterator for CssDeclarationList {
type Item = AnyCssDeclarationWithSemicolon;
type IntoIter = AstNodeListIterator<Language, AnyCssDeclarationWithSemicolon>;
type Item = AnyCssDeclaration;
type IntoIter = AstNodeListIterator<Language, AnyCssDeclaration>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}

View file

@ -1,8 +1,8 @@
use crate::CssSyntaxToken;
use crate::generated::{
CssDeclarationBlock, CssDeclarationOrAtRuleBlock, CssDeclarationOrRuleBlock,
CssFontFeatureValuesBlock, CssKeyframesBlock, CssPageAtRuleBlock, CssRuleBlock,
};
use crate::{AnyCssDeclarationOrAtRule, AnyCssDeclarationOrRule, CssSyntaxToken};
use biome_rowan::{AstNodeList, SyntaxResult, declare_node_union};
declare_node_union! {
@ -60,21 +60,15 @@ impl CssBlockLike {
Self::CssDeclarationBlock(block) => block
.declarations()
.iter()
.all(|decl| decl.as_css_declaration_with_semicolon().is_none()),
Self::CssDeclarationOrAtRuleBlock(block) => block.items().iter().all(|item| {
matches!(
item,
AnyCssDeclarationOrAtRule::AnyCssDeclarationWithSemicolon(decl)
if decl.as_css_declaration_with_semicolon().is_none()
)
}),
Self::CssDeclarationOrRuleBlock(block) => block.items().iter().all(|item| {
matches!(
item,
AnyCssDeclarationOrRule::AnyCssDeclarationWithSemicolon(decl)
if decl.as_css_declaration_with_semicolon().is_none()
)
}),
.all(|decl| decl.as_css_empty_declaration().is_some()),
Self::CssDeclarationOrAtRuleBlock(block) => block
.items()
.iter()
.all(|item| item.as_css_empty_declaration().is_some()),
Self::CssDeclarationOrRuleBlock(block) => block
.items()
.iter()
.all(|item| item.as_css_empty_declaration().is_some()),
_ => false,
}
}

Binary file not shown.

View file

@ -421,7 +421,7 @@ CssPseudoElementFunctionCustomIdentifier =
'('
ident: CssCustomIdentifier
')'
// ::part(active button) {}
// ^^^^^^^^^^^^^^^^^^^
CssPseudoElementFunction =
@ -429,7 +429,7 @@ CssPseudoElementFunction =
'('
items: CssPseudoElementFunctionParameterList
')'
CssPseudoElementFunctionParameterList = CssIdentifier*
/////////////
@ -450,7 +450,8 @@ CssDeclarationOrRuleList = AnyCssDeclarationOrRule*
AnyCssDeclarationOrRule =
AnyCssRule
| AnyCssDeclarationWithSemicolon
| CssDeclarationWithSemicolon
| CssEmptyDeclaration
| CssBogus
| CssMetavariable
@ -468,8 +469,9 @@ CssDeclarationOrAtRuleBlock =
CssDeclarationOrAtRuleList = AnyCssDeclarationOrAtRule*
AnyCssDeclarationOrAtRule =
AnyCssDeclarationWithSemicolon
| CssAtRule
CssDeclarationWithSemicolon
| CssEmptyDeclaration
| CssAtRule
// When nested in this way, the contents of a nested group rule's block are parsed as <block-contents> rather than <rule-list>:
// https://drafts.csswg.org/css-nesting-1/#conditionals
@ -478,10 +480,6 @@ AnyCssConditionalBlock =
| CssRuleBlock
| CssBogusBlock
AnyCssDeclarationWithSemicolon =
CssDeclarationWithSemicolon
| CssEmptyDeclaration
// @page :left { background: red; @media (500px <= width <= 500px) { } }
// ^^^^^^^^^^^^^^^^
// NOTE: ';' is optional for the last declaration in a block. For declarations not at the end, the parser will raise an error if ';' is missing.
@ -501,7 +499,11 @@ CssDeclarationBlock =
declarations: CssDeclarationList
'}'
CssDeclarationList = AnyCssDeclarationWithSemicolon*
CssDeclarationList = AnyCssDeclaration*
AnyCssDeclaration =
CssDeclarationWithSemicolon
| CssEmptyDeclaration
AnyCssRuleBlock =
CssRuleBlock
@ -1232,7 +1234,8 @@ CssPageAtRuleBlock =
CssPageAtRuleItemList = AnyCssPageAtRuleItem*
AnyCssPageAtRuleItem =
AnyCssDeclarationWithSemicolon
CssDeclarationWithSemicolon
| CssEmptyDeclaration
| CssAtRule
| CssMarginAtRule