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