1use crate::{
2 BadDeclaration, Block, CursorSink, DeclarationValue, Diagnostic, Kind, KindSet, NodeMetadata, NodeWithMetadata,
3 Parse, Parser, Peek, Result, SemanticEq, Span, State, T, ToCursors, ToSpan,
4};
5
6#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize))]
8#[cfg_attr(
9 feature = "serde",
10 serde(bound(serialize = "P: serde::Serialize, D: serde::Serialize, R: serde::Serialize"))
11)]
12pub struct QualifiedRule<'a, P, D, R, M>
13where
14 D: DeclarationValue<'a, M>,
16 M: NodeMetadata,
17{
18 pub prelude: P,
19 pub block: Block<'a, D, R, M>,
20 #[cfg_attr(feature = "serde", serde(skip))]
21 meta: M,
22}
23
24impl<'a, P, D, R, M> NodeWithMetadata<M> for QualifiedRule<'a, P, D, R, M>
25where
26 D: DeclarationValue<'a, M>,
27 M: NodeMetadata,
28{
29 fn metadata(&self) -> M {
30 self.meta
31 }
32}
33
34impl<'a, P, D, R, M> Peek<'a> for QualifiedRule<'a, P, D, R, M>
35where
36 P: Peek<'a>,
37 D: DeclarationValue<'a, M>,
38 M: NodeMetadata,
39{
40 const PEEK_KINDSET: KindSet = P::PEEK_KINDSET;
41}
42
43impl<'a, P, D, R, M> Parse<'a> for QualifiedRule<'a, P, D, R, M>
47where
48 D: DeclarationValue<'a, M>,
49 P: Parse<'a>,
50 R: Parse<'a> + NodeWithMetadata<M> + crate::RuleVariants<'a, DeclarationValue = D, Metadata = M>,
51 M: NodeMetadata,
52{
53 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
54 where
55 Iter: Iterator<Item = crate::Cursor> + Clone,
56 {
57 let c = p.peek_n(1);
58 if p.at_end() {
66 Err(Diagnostic::new(p.peek_n(1), Diagnostic::unexpected_end))?
67 }
68
69 if p.is(State::Nested) && <T!['}']>::peek(p, c) {
72 Err(Diagnostic::new(c, Diagnostic::unexpected_close_curly))?;
73 }
74
75 let checkpoint = p.checkpoint();
78 if <T![DashedIdent]>::peek(p, c) {
79 p.parse::<T![DashedIdent]>().ok();
80 if <T![:]>::peek(p, p.peek_n(1)) {
81 if p.is(State::Nested) {
83 p.rewind(checkpoint.clone());
84 let start = p.peek_n(1);
85 p.parse::<BadDeclaration>()?;
86 let end = p.peek_n(0);
87 Err(Diagnostic::new(start, Diagnostic::bad_declaration).with_end_cursor(end))?
88 } else {
90 p.parse::<Block<'a, D, R, M>>()?;
96 let start = p.peek_n(1);
97 p.parse::<BadDeclaration>()?;
98 let end = p.peek_n(0);
99 Err(Diagnostic::new(start, Diagnostic::bad_declaration).with_end_cursor(end))?
100 }
101 }
102 p.rewind(checkpoint);
103 }
104
105 let old_stop = p.set_stop(KindSet::new(&[Kind::LeftCurly]));
107 let prelude = p.parse::<P>();
108 p.set_stop(old_stop);
109 let prelude = prelude?;
110
111 let block = p.parse::<Block<'a, D, R, M>>()?;
118 let meta = block.metadata();
119 Ok(Self { prelude, block, meta })
120 }
121}
122
123impl<'a, P, D, R, M> ToCursors for QualifiedRule<'a, P, D, R, M>
124where
125 D: DeclarationValue<'a, M> + ToCursors,
126 P: ToCursors,
127 R: ToCursors,
128 M: NodeMetadata,
129{
130 fn to_cursors(&self, s: &mut impl CursorSink) {
131 ToCursors::to_cursors(&self.prelude, s);
132 ToCursors::to_cursors(&self.block, s);
133 }
134}
135
136impl<'a, P, D, R, M> ToSpan for QualifiedRule<'a, P, D, R, M>
137where
138 D: DeclarationValue<'a, M> + ToSpan,
139 P: ToSpan,
140 R: ToSpan,
141 M: NodeMetadata,
142{
143 fn to_span(&self) -> Span {
144 self.prelude.to_span() + self.block.to_span()
145 }
146}
147
148impl<'a, P, D, R, M> SemanticEq for QualifiedRule<'a, P, D, R, M>
149where
150 D: DeclarationValue<'a, M> + SemanticEq,
151 P: SemanticEq,
152 R: SemanticEq,
153 M: NodeMetadata,
154{
155 fn semantic_eq(&self, other: &Self) -> bool {
156 self.prelude.semantic_eq(&other.prelude) && self.block.semantic_eq(&other.block)
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163 use crate::{Cursor, EmptyAtomSet, test_helpers::*};
164
165 #[derive(Debug)]
166 struct Decl(T![Ident]);
167
168 impl NodeWithMetadata<()> for Decl {
169 fn metadata(&self) {}
170 }
171
172 impl<'a> DeclarationValue<'a, ()> for Decl {
173 type ComputedValue = T![Eof];
174
175 fn is_initial(&self) -> bool {
176 false
177 }
178
179 fn is_inherit(&self) -> bool {
180 false
181 }
182
183 fn is_unset(&self) -> bool {
184 false
185 }
186
187 fn is_revert(&self) -> bool {
188 false
189 }
190
191 fn is_revert_layer(&self) -> bool {
192 false
193 }
194
195 fn needs_computing(&self) -> bool {
196 false
197 }
198
199 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _: 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 ToCursors::to_cursors(&self.0, s);
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 #[derive(Debug)]
226 struct Rule(T![Ident]);
227
228 impl<'a> Parse<'a> for Rule {
229 fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
230 where
231 I: Iterator<Item = Cursor> + Clone,
232 {
233 Ok(Self(p.parse::<T![Ident]>()?))
234 }
235 }
236
237 impl ToCursors for Rule {
238 fn to_cursors(&self, s: &mut impl CursorSink) {
239 ToCursors::to_cursors(&self.0, s);
240 }
241 }
242
243 impl ToSpan for Rule {
244 fn to_span(&self) -> Span {
245 self.0.to_span()
246 }
247 }
248
249 impl NodeWithMetadata<()> for Rule {
250 fn metadata(&self) {}
251 }
252
253 impl<'a> crate::RuleVariants<'a> for Rule {
254 type DeclarationValue = Decl;
255 type Metadata = ();
256 }
257
258 #[test]
259 fn size_test() {
260 assert_eq!(std::mem::size_of::<QualifiedRule<T![Ident], Decl, Rule, ()>>(), 112);
261 }
262
263 #[test]
264 fn test_writes() {
265 assert_parse!(EmptyAtomSet::ATOMS, QualifiedRule<T![Ident], Decl, Rule, ()>, "body{color:black}");
266 }
267}