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