1use crate::{
2 BangImportant, Cursor, CursorSink, DeclarationValue, Kind, NodeMetadata, NodeWithMetadata, Parse, Parser, Peek,
3 Result, SemanticEq, Span, T, ToCursors, ToSpan, token_macros,
4};
5use std::marker::PhantomData;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
31pub struct Declaration<'a, V, M>
32where
33 V: DeclarationValue<'a, M>,
34 M: NodeMetadata,
35{
36 pub name: token_macros::Ident,
37 pub colon: token_macros::Colon,
38 pub value: V,
39 pub important: Option<BangImportant>,
40 pub semicolon: Option<token_macros::Semicolon>,
41 #[cfg_attr(feature = "serde", serde(skip))]
42 _phantom: PhantomData<&'a M>,
43}
44
45impl<'a, V, M> Declaration<'a, V, M>
46where
47 V: DeclarationValue<'a, M>,
48 M: NodeMetadata,
49{
50 pub fn is_unknown(&self) -> bool {
51 self.value.is_unknown()
52 }
53}
54
55impl<'a, V, M> NodeWithMetadata<M> for Declaration<'a, V, M>
56where
57 V: DeclarationValue<'a, M>,
58 M: NodeMetadata,
59{
60 fn self_metadata(&self) -> M {
61 DeclarationValue::declaration_metadata(self)
64 }
65
66 fn metadata(&self) -> M {
67 DeclarationValue::declaration_metadata(self)
68 }
69}
70
71impl<'a, V, M> Peek<'a> for Declaration<'a, V, M>
72where
73 V: DeclarationValue<'a, M>,
74 M: NodeMetadata,
75{
76 fn peek<Iter>(p: &Parser<'a, Iter>, c: Cursor) -> bool
77 where
78 Iter: Iterator<Item = crate::Cursor> + Clone,
79 {
80 if c != Kind::Ident || p.peek_n(2) != Kind::Colon {
87 return false;
88 }
89
90 if c.token().is_dashed_ident() {
95 return true;
96 }
97
98 if p.peek_n(3) == Kind::Colon {
102 return false;
103 }
104
105 if p.peek_n(4) == Kind::LeftCurly || p.peek_n(5) == Kind::LeftCurly {
111 return false;
112 }
113
114 true
116 }
117}
118
119impl<'a, V, M> Parse<'a> for Declaration<'a, V, M>
120where
121 V: DeclarationValue<'a, M>,
122 M: NodeMetadata,
123{
124 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
125 where
126 Iter: Iterator<Item = crate::Cursor> + Clone,
127 {
128 let name = p.parse::<T![Ident]>()?;
129 let colon = p.parse::<T![:]>()?;
130 let c: Cursor = name.into();
131 let value = <V>::parse_declaration_value(p, c)?;
132 let important = p.parse_if_peek::<BangImportant>()?;
133 let semicolon = p.parse_if_peek::<T![;]>()?;
134 Ok(Self { name, colon, value, important, semicolon, _phantom: PhantomData })
135 }
136}
137
138impl<'a, V, M> ToCursors for Declaration<'a, V, M>
139where
140 V: DeclarationValue<'a, M> + ToCursors,
141 M: NodeMetadata,
142{
143 fn to_cursors(&self, s: &mut impl CursorSink) {
144 ToCursors::to_cursors(&self.name, s);
145 ToCursors::to_cursors(&self.colon, s);
146 ToCursors::to_cursors(&self.value, s);
147 ToCursors::to_cursors(&self.important, s);
148 ToCursors::to_cursors(&self.semicolon, s);
149 }
150}
151
152impl<'a, V, M> ToSpan for Declaration<'a, V, M>
153where
154 V: DeclarationValue<'a, M> + ToSpan,
155 M: NodeMetadata,
156{
157 fn to_span(&self) -> Span {
158 self.name.to_span() + self.value.to_span() + self.important.to_span() + self.semicolon.to_span()
159 }
160}
161
162impl<'a, V, M> SemanticEq for Declaration<'a, V, M>
163where
164 V: DeclarationValue<'a, M>,
165 M: NodeMetadata,
166{
167 fn semantic_eq(&self, other: &Self) -> bool {
168 self.name.semantic_eq(&other.name)
170 && self.value.semantic_eq(&other.value)
171 && self.important.semantic_eq(&other.important)
172 }
173}
174
175#[cfg(test)]
176mod tests {
177 use super::*;
178 use crate::EmptyAtomSet;
179 use crate::SemanticEq;
180 use crate::test_helpers::*;
181
182 #[derive(Debug)]
183 struct Decl(T![Ident]);
184
185 impl<M: NodeMetadata> NodeWithMetadata<M> for Decl {
186 fn metadata(&self) -> M {
187 M::default()
188 }
189 }
190
191 impl<'a, M: NodeMetadata> DeclarationValue<'a, M> for Decl {
192 type ComputedValue = T![Eof];
193
194 fn is_initial(&self) -> bool {
195 false
196 }
197
198 fn is_inherit(&self) -> bool {
199 false
200 }
201
202 fn is_unset(&self) -> bool {
203 false
204 }
205
206 fn is_revert(&self) -> bool {
207 false
208 }
209
210 fn is_revert_layer(&self) -> bool {
211 false
212 }
213
214 fn needs_computing(&self) -> bool {
215 false
216 }
217
218 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _name: Cursor) -> Result<Self>
219 where
220 Iter: Iterator<Item = crate::Cursor> + Clone,
221 {
222 p.parse::<T![Ident]>().map(Self)
223 }
224 }
225
226 impl ToCursors for Decl {
227 fn to_cursors(&self, s: &mut impl CursorSink) {
228 s.append(self.0.into())
229 }
230 }
231
232 impl ToSpan for Decl {
233 fn to_span(&self) -> Span {
234 self.0.to_span()
235 }
236 }
237
238 impl SemanticEq for Decl {
239 fn semantic_eq(&self, other: &Self) -> bool {
240 self.0.semantic_eq(&other.0)
241 }
242 }
243
244 #[test]
245 fn size_test() {
246 assert_eq!(std::mem::size_of::<Declaration<Decl, ()>>(), 80);
247 }
248
249 #[test]
250 fn test_writes() {
251 assert_parse!(EmptyAtomSet::ATOMS, Declaration<Decl, ()>, "color:black;");
252 }
253}