1use crate::{
2 BadDeclaration, Block, Cursor, CursorSink, DeclarationValue, Diagnostic, Kind, KindSet, NodeMetadata,
3 NodeWithMetadata, 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 fn peek<Iter>(p: &Parser<'a, Iter>, c: Cursor) -> bool
41 where
42 Iter: Iterator<Item = crate::Cursor> + Clone,
43 {
44 <P>::peek(p, c)
45 }
46}
47
48impl<'a, P, D, R, M> Parse<'a> for QualifiedRule<'a, P, D, R, M>
52where
53 D: DeclarationValue<'a, M>,
54 P: Parse<'a>,
55 R: Parse<'a> + NodeWithMetadata<M> + crate::RuleVariants<'a, DeclarationValue = D, Metadata = M>,
56 M: NodeMetadata,
57{
58 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
59 where
60 Iter: Iterator<Item = crate::Cursor> + Clone,
61 {
62 let c = p.peek_n(1);
63 if p.at_end() {
71 Err(Diagnostic::new(p.peek_n(1), Diagnostic::unexpected_end))?
72 }
73
74 if p.is(State::Nested) && <T!['}']>::peek(p, c) {
77 Err(Diagnostic::new(c, Diagnostic::unexpected_close_curly))?;
78 }
79
80 let checkpoint = p.checkpoint();
83 if <T![DashedIdent]>::peek(p, c) {
84 p.parse::<T![DashedIdent]>().ok();
85 if <T![:]>::peek(p, p.peek_n(1)) {
86 if p.is(State::Nested) {
88 p.rewind(checkpoint.clone());
89 let start = p.peek_n(1);
90 p.parse::<BadDeclaration>()?;
91 let end = p.peek_n(0);
92 Err(Diagnostic::new(start, Diagnostic::bad_declaration).with_end_cursor(end))?
93 } else {
95 p.parse::<Block<'a, D, R, M>>()?;
101 let start = p.peek_n(1);
102 p.parse::<BadDeclaration>()?;
103 let end = p.peek_n(0);
104 Err(Diagnostic::new(start, Diagnostic::bad_declaration).with_end_cursor(end))?
105 }
106 }
107 p.rewind(checkpoint);
108 }
109
110 let old_stop = p.set_stop(KindSet::new(&[Kind::LeftCurly]));
112 let prelude = p.parse::<P>();
113 p.set_stop(old_stop);
114 let prelude = prelude?;
115
116 let block = p.parse::<Block<'a, D, R, M>>()?;
123 let meta = block.metadata();
124 Ok(Self { prelude, block, meta })
125 }
126}
127
128impl<'a, P, D, R, M> ToCursors for QualifiedRule<'a, P, D, R, M>
129where
130 D: DeclarationValue<'a, M> + ToCursors,
131 P: ToCursors,
132 R: ToCursors,
133 M: NodeMetadata,
134{
135 fn to_cursors(&self, s: &mut impl CursorSink) {
136 ToCursors::to_cursors(&self.prelude, s);
137 ToCursors::to_cursors(&self.block, s);
138 }
139}
140
141impl<'a, P, D, R, M> ToSpan for QualifiedRule<'a, P, D, R, M>
142where
143 D: DeclarationValue<'a, M> + ToSpan,
144 P: ToSpan,
145 R: ToSpan,
146 M: NodeMetadata,
147{
148 fn to_span(&self) -> Span {
149 self.prelude.to_span() + self.block.to_span()
150 }
151}
152
153impl<'a, P, D, R, M> SemanticEq for QualifiedRule<'a, P, D, R, M>
154where
155 D: DeclarationValue<'a, M> + SemanticEq,
156 P: SemanticEq,
157 R: SemanticEq,
158 M: NodeMetadata,
159{
160 fn semantic_eq(&self, other: &Self) -> bool {
161 self.prelude.semantic_eq(&other.prelude) && self.block.semantic_eq(&other.block)
162 }
163}
164
165#[cfg(test)]
166mod tests {
167 use super::*;
168 use crate::{EmptyAtomSet, test_helpers::*};
169
170 #[derive(Debug)]
171 struct Decl(T![Ident]);
172
173 impl NodeWithMetadata<()> for Decl {
174 fn metadata(&self) {}
175 }
176
177 impl<'a> DeclarationValue<'a, ()> for Decl {
178 type ComputedValue = T![Eof];
179
180 fn is_initial(&self) -> bool {
181 false
182 }
183
184 fn is_inherit(&self) -> bool {
185 false
186 }
187
188 fn is_unset(&self) -> bool {
189 false
190 }
191
192 fn is_revert(&self) -> bool {
193 false
194 }
195
196 fn is_revert_layer(&self) -> bool {
197 false
198 }
199
200 fn needs_computing(&self) -> bool {
201 false
202 }
203
204 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _: Cursor) -> Result<Self>
205 where
206 Iter: Iterator<Item = crate::Cursor> + Clone,
207 {
208 p.parse::<T![Ident]>().map(Self)
209 }
210 }
211
212 impl ToCursors for Decl {
213 fn to_cursors(&self, s: &mut impl CursorSink) {
214 ToCursors::to_cursors(&self.0, s);
215 }
216 }
217
218 impl ToSpan for Decl {
219 fn to_span(&self) -> Span {
220 self.0.to_span()
221 }
222 }
223
224 impl SemanticEq for Decl {
225 fn semantic_eq(&self, other: &Self) -> bool {
226 self.0.semantic_eq(&other.0)
227 }
228 }
229
230 #[derive(Debug)]
231 struct Rule(T![Ident]);
232
233 impl<'a> Parse<'a> for Rule {
234 fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
235 where
236 I: Iterator<Item = Cursor> + Clone,
237 {
238 Ok(Self(p.parse::<T![Ident]>()?))
239 }
240 }
241
242 impl ToCursors for Rule {
243 fn to_cursors(&self, s: &mut impl CursorSink) {
244 ToCursors::to_cursors(&self.0, s);
245 }
246 }
247
248 impl ToSpan for Rule {
249 fn to_span(&self) -> Span {
250 self.0.to_span()
251 }
252 }
253
254 impl NodeWithMetadata<()> for Rule {
255 fn metadata(&self) {}
256 }
257
258 impl<'a> crate::RuleVariants<'a> for Rule {
259 type DeclarationValue = Decl;
260 type Metadata = ();
261 }
262
263 #[test]
264 fn size_test() {
265 assert_eq!(std::mem::size_of::<QualifiedRule<T![Ident], Decl, Rule, ()>>(), 112);
266 }
267
268 #[test]
269 fn test_writes() {
270 assert_parse!(EmptyAtomSet::ATOMS, QualifiedRule<T![Ident], Decl, Rule, ()>, "body{color:black}");
271 }
272}