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}