css_parse/traits/declaration_value.rs
1use crate::{
2 Cursor, Declaration, Diagnostic, KindSet, NodeMetadata, NodeWithMetadata, Parser, Peek, Result, SemanticEq, T,
3 ToCursors,
4};
5use css_lexer::ToSpan;
6
7/// A trait that can be used for AST nodes representing a Declaration's Value. It offers some
8/// convenience functions for handling such values.
9pub trait DeclarationValue<'a, M: NodeMetadata>: Sized + NodeWithMetadata<M> + ToSpan + ToCursors + SemanticEq {
10 /// Returns metadata for this value when used in a declaration context.
11 /// This allows the value to inspect the declaration (e.g., checking for !important)
12 /// and include that information in the metadata.
13 ///
14 /// The default implementation just returns the value's metadata, ignoring the declaration context.
15 fn declaration_metadata(declaration: &Declaration<'a, Self, M>) -> M {
16 declaration.value.metadata()
17 }
18
19 /// Determines if the given [Cursor] represents a valid [Ident][crate::token_macros::Ident] matching a known property
20 /// name.
21 ///
22 /// If implementing a set of declarations where ony limited property-ids are valid (such as the declarations allowed
23 /// by an at-rule) then it might be worthwhile changing this to sometimes return `false`, which consumers of this
24 /// trait can use to error early without having to do too much backtracking.
25 fn valid_declaration_name<Iter>(_p: &Parser<'a, Iter>, _c: Cursor) -> bool
26 where
27 Iter: Iterator<Item = crate::Cursor> + Clone,
28 {
29 true
30 }
31
32 /// Determines if the parsed Self was parsed as an unknown value.
33 ///
34 /// If implementing a set of declarations where any name is accepted, or where the value might result in re-parsing
35 /// as unknown, this method can be used to signal that to upstream consumers of this trait. By default this returns
36 /// `false` because `valid_declaration_name` returns `true`, the assumption being that any successful construction of
37 /// Self is indeed a valid and known declaration.
38 fn is_unknown(&self) -> bool {
39 false
40 }
41
42 /// Determines if the parsed Self was parsed as a Custom value.
43 ///
44 /// If implementing a set of declarations where custom names are accepted, or where the value might result in
45 /// re-parsing as unknown, this method can be used to signal that to upstream consumers of this trait. By default
46 /// this returns `false` because `valid_declaration_name` returns `true`, the assumption being that any successful
47 /// construction of Self is indeed a valid and known declaration.
48 fn is_custom(&self) -> bool {
49 false
50 }
51
52 /// Determines if the parsed Self was parsed as the "initial" keyword.
53 ///
54 /// If implementing a set of declarations where the "initial" keyword is accepted this method can be used to signal
55 /// that to upstream consumers of this trait.
56 fn is_initial(&self) -> bool;
57
58 /// Determines if the parsed Self was parsed as the "inherit" keyword.
59 ///
60 /// If implementing a set of declarations where the "inherit" keyword is accepted this method can be used to signal
61 /// that to upstream consumers of this trait.
62 fn is_inherit(&self) -> bool;
63
64 /// Determines if the parsed Self was parsed as the "unset" keyword.
65 ///
66 /// If implementing a set of declarations where the "unset" keyword is accepted this method can be used to signal
67 /// that to upstream consumers of this trait.
68 fn is_unset(&self) -> bool;
69
70 /// Determines if the parsed Self was parsed as the "revert" keyword.
71 ///
72 /// If implementing a set of declarations where the "revert" keyword is accepted this method can be used to signal
73 /// that to upstream consumers of this trait.
74 fn is_revert(&self) -> bool;
75
76 /// Determines if the parsed Self was parsed as the "revert" keyword.
77 ///
78 /// If implementing a set of declarations where the "revert" keyword is accepted this method can be used to signal
79 /// that to upstream consumers of this trait.
80 fn is_revert_layer(&self) -> bool;
81
82 /// Determines if the parsed Self is not a valid literal production of the grammar, and instead some of its
83 /// constituent parts will need additional computation to reify into a known value.
84 ///
85 /// CSS properties are allowed to include substitutions, such as `calc()` or `var()`. These are not defined in the
86 /// declaration's grammar but are instead stored so that when a style object is reified the declarations that had
87 /// those tokens can be recomputed against the context of their node.
88 fn needs_computing(&self) -> bool;
89
90 /// Like `parse()` but with the additional context of the `name` [Cursor]. This cursor is known to be dashed ident,
91 /// therefore this should return a `Self` reflecting a Custom property. Alternatively, if this DeclarationValue
92 /// disallows custom declarations then this is the right place to return a parse Error.
93 ///
94 /// The default implementation of this method is to return an Unexpected Err.
95 fn parse_custom_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _name: Cursor) -> Result<Self>
96 where
97 Iter: Iterator<Item = crate::Cursor> + Clone,
98 {
99 let c = p.peek_n(1);
100 Err(Diagnostic::new(c, Diagnostic::unexpected))?
101 }
102
103 /// Determines if the given [Cursor] begins a computed value (an arbitrary substitution function such as
104 /// `var()`/`env()`, or a typed math function such as `calc()`/`min()`).
105 ///
106 /// This is used by [`parse_declaration_value`][DeclarationValue::parse_declaration_value] as the fallback check after
107 /// property-specific parsing fails or stops early: if this returns `true` the whole declaration is re-parsed via
108 /// [`parse_computed_declaration_value`][DeclarationValue::parse_computed_declaration_value].
109 ///
110 /// The default implementation returns `false`, i.e. this DeclarationValue has no computed fallback.
111 fn is_computed_declaration_value<Iter>(_p: &Parser<'a, Iter>, _c: Cursor) -> bool
112 where
113 Iter: Iterator<Item = crate::Cursor> + Clone,
114 {
115 false
116 }
117
118 /// Like `parse()` but with the additional context of the `name` [Cursor]. This is only called before verifying that
119 /// the next token was peeked to be a ComputedValue, therefore this should return a `Self` reflecting a Computed
120 /// property. Alternatively, if this DeclarationValue disallows computed declarations then this is the right place to
121 /// return a parse Error.
122 ///
123 /// The default implementation of this method is to return an Unexpected Err.
124 fn parse_computed_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _name: Cursor) -> Result<Self>
125 where
126 Iter: Iterator<Item = crate::Cursor> + Clone,
127 {
128 let c = p.peek_n(1);
129 Err(Diagnostic::new(c, Diagnostic::unexpected))?
130 }
131
132 /// Like `parse()` but with the additional context of the `name` [Cursor]. This is only called on values that are
133 /// assumed to be _specified_, that is, they're not custom and not computed. Therefore this should return a `Self`
134 /// reflecting a specified value. If this results in a Parse error then ComputedValue will be checked to see if the
135 /// parser stopped because it saw a computed value function. If this results in a success, the next token is still
136 /// checked as it may be a ComputedValue, which - if so - the parsed value will be discarded, and the parser rewound
137 /// to re-parse this as a ComputedValue.
138 ///
139 /// The default implementation of this method is to return an Unexpected Err.
140 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _name: Cursor) -> Result<Self>
141 where
142 Iter: Iterator<Item = crate::Cursor> + Clone,
143 {
144 let c = p.peek_n(1);
145 Err(Diagnostic::new(c, Diagnostic::unexpected))?
146 }
147
148 /// Like `parse()` but with the additional context of the `name` [Cursor]. This is only called on values that are
149 /// didn't parse as either a Custom, Computed or Specified value therefore this should return a `Self` reflecting an
150 /// unknown property, or alternatively the right place to return a parse error.
151 ///
152 /// The default implementation of this method is to return an Unexpected Err.
153 fn parse_unknown_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _name: Cursor) -> Result<Self>
154 where
155 Iter: Iterator<Item = crate::Cursor> + Clone,
156 {
157 let c = p.peek_n(1);
158 Err(Diagnostic::new(c, Diagnostic::unexpected))?
159 }
160
161 // Like `parse()` but with the additional context of the `name` [Cursor] - the same [Cursor]
162 // passed to [DeclarationValue::valid_declaration_name()].
163 //
164 // Parsing order:
165 // 1. Custom properties (--dashed-ident)
166 // 2. Unknown property names
167 // 3. Property-specific parsing (via parse_specified_declaration_value)
168 // 4. Fallback to Computed for var/calc if property parsing failed/stopped early
169 // 5. Unknown as final fallback
170 fn parse_declaration_value<Iter>(p: &mut Parser<'a, Iter>, name: Cursor) -> Result<Self>
171 where
172 Iter: Iterator<Item = crate::Cursor> + Clone,
173 {
174 if name.token().is_dashed_ident() {
175 return Self::parse_custom_declaration_value(p, name);
176 }
177 if !Self::valid_declaration_name(p, name) {
178 return Self::parse_unknown_declaration_value(p, name);
179 }
180
181 let checkpoint = p.checkpoint();
182 if let Ok(val) = Self::parse_specified_declaration_value(p, name) {
183 let c = p.peek_n(1);
184 if p.at_end() || c == KindSet::RIGHT_CURLY_SEMICOLON_OR_RIGHT_PAREN || <T![!]>::peek(p, c) {
185 return Ok(val);
186 }
187 }
188 p.rewind(checkpoint.clone());
189 if Self::is_computed_declaration_value(p, p.peek_n(1))
190 && let Ok(val) = Self::parse_computed_declaration_value(p, name)
191 {
192 return Ok(val);
193 }
194 p.rewind(checkpoint);
195 Self::parse_unknown_declaration_value(p, name)
196 }
197}