1use super::prelude::*;
2use crate::{BangImportant, token_macros};
3use std::marker::PhantomData;
4
5#[node]
28#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
30pub struct Declaration<'a, V, M>
31where
32 V: DeclarationValue<'a, M>,
33 M: NodeMetadata,
34{
35 pub name: token_macros::Ident,
36 pub colon: token_macros::Colon,
37 pub value: V,
38 pub important: Option<BangImportant>,
39 pub semicolon: Option<token_macros::Semicolon>,
40 #[cfg_attr(feature = "serde", serde(skip))]
41 meta: M,
42 #[cfg_attr(feature = "serde", serde(skip))]
43 _phantom: PhantomData<&'a ()>,
44}
45
46impl<'a, V, M> Declaration<'a, V, M>
47where
48 V: DeclarationValue<'a, M>,
49 M: NodeMetadata,
50{
51 pub fn is_unknown(&self) -> bool {
52 self.value.is_unknown()
53 }
54}
55
56impl<'a, V, M> NodeWithMetadata<M> for Declaration<'a, V, M>
57where
58 V: DeclarationValue<'a, M>,
59 M: NodeMetadata,
60{
61 fn self_metadata(&self) -> M {
62 self.meta
65 }
66
67 fn metadata(&self) -> M {
68 self.meta
69 }
70}
71
72impl<'a, V, M> Peek<'a> for Declaration<'a, V, M>
73where
74 V: DeclarationValue<'a, M>,
75 M: NodeMetadata,
76{
77 const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::Ident]);
78
79 #[inline(always)]
80 fn peek<Iter>(p: &Parser<'a, Iter>, c: Cursor) -> bool
81 where
82 Iter: Iterator<Item = crate::Cursor> + Clone,
83 {
84 if c != Kind::Ident || p.peek_n(2) != Kind::Colon {
91 return false;
92 }
93
94 if c.token().is_dashed_ident() {
99 return true;
100 }
101
102 if p.peek_n(3) == Kind::Colon {
106 return false;
107 }
108
109 if p.peek_n(4) == Kind::LeftCurly || p.peek_n(5) == Kind::LeftCurly {
115 return false;
116 }
117
118 true
120 }
121}
122
123impl<'a, V, M> Parse<'a> for Declaration<'a, V, M>
124where
125 V: DeclarationValue<'a, M>,
126 M: NodeMetadata,
127{
128 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
129 where
130 Iter: Iterator<Item = crate::Cursor> + Clone,
131 {
132 let name = p.parse::<T![Ident]>()?;
133 let colon = p.parse::<T![:]>()?;
134 let c: Cursor = name.into();
135 let value = <V>::parse_declaration_value(p, c)?;
136 let important = p.parse_if_peek::<BangImportant>()?;
137 let semicolon = p.parse_if_peek::<T![;]>()?;
138 let mut declaration =
139 Self { name, colon, value, important, semicolon, meta: M::default(), _phantom: PhantomData };
140 declaration.meta = DeclarationValue::declaration_metadata(&declaration);
141 Ok(declaration)
142 }
143}
144
145impl<'a, V, M> ToCursors for Declaration<'a, V, M>
146where
147 V: DeclarationValue<'a, M> + ToCursors,
148 M: NodeMetadata,
149{
150 fn to_cursors(&self, s: &mut impl CursorSink) {
151 ToCursors::to_cursors(&self.name, s);
152 ToCursors::to_cursors(&self.colon, s);
153 ToCursors::to_cursors(&self.value, s);
154 ToCursors::to_cursors(&self.important, s);
155 ToCursors::to_cursors(&self.semicolon, s);
156 }
157}
158
159impl<'a, V, M> ToSpan for Declaration<'a, V, M>
160where
161 V: DeclarationValue<'a, M> + ToSpan,
162 M: NodeMetadata,
163{
164 fn to_span(&self) -> Span {
165 self.name.to_span() + self.value.to_span() + self.important.to_span() + self.semicolon.to_span()
166 }
167}
168
169impl<'a, V, M> SemanticEq for Declaration<'a, V, M>
170where
171 V: DeclarationValue<'a, M>,
172 M: NodeMetadata,
173{
174 fn semantic_eq(&self, other: &Self) -> bool {
175 self.name.semantic_eq(&other.name)
177 && self.value.semantic_eq(&other.value)
178 && self.important.semantic_eq(&other.important)
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185 use crate::EmptyAtomSet;
186 use crate::SemanticEq;
187 use crate::test_helpers::*;
188
189 #[derive(Debug)]
190 struct Decl(T![Ident]);
191
192 impl<M: NodeMetadata> NodeWithMetadata<M> for Decl {
193 fn metadata(&self) -> M {
194 M::default()
195 }
196 }
197
198 impl<'a, M: NodeMetadata> DeclarationValue<'a, M> for Decl {
199 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _name: Cursor) -> Result<Self>
200 where
201 Iter: Iterator<Item = crate::Cursor> + Clone,
202 {
203 p.parse::<T![Ident]>().map(Self)
204 }
205 }
206
207 impl ToCursors for Decl {
208 fn to_cursors(&self, s: &mut impl CursorSink) {
209 s.append(self.0.into())
210 }
211 }
212
213 impl ToSpan for Decl {
214 fn to_span(&self) -> Span {
215 self.0.to_span()
216 }
217 }
218
219 impl SemanticEq for Decl {
220 fn semantic_eq(&self, other: &Self) -> bool {
221 self.0.semantic_eq(&other.0)
222 }
223 }
224
225 #[test]
226 fn test_writes() {
227 assert_parse!(EmptyAtomSet::ATOMS, Declaration<Decl, ()>, "color:black;");
228 }
229}