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>,
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 }
178
179 impl<'a> DeclarationValue<'a, ()> for Decl {
180 type ComputedValue = T![Eof];
181
182 fn is_initial(&self) -> bool {
183 false
184 }
185
186 fn is_inherit(&self) -> bool {
187 false
188 }
189
190 fn is_unset(&self) -> bool {
191 false
192 }
193
194 fn is_revert(&self) -> bool {
195 false
196 }
197
198 fn is_revert_layer(&self) -> bool {
199 false
200 }
201
202 fn needs_computing(&self) -> bool {
203 false
204 }
205
206 fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _: Cursor) -> Result<Self>
207 where
208 Iter: Iterator<Item = crate::Cursor> + Clone,
209 {
210 p.parse::<T![Ident]>().map(Self)
211 }
212 }
213
214 impl ToCursors for Decl {
215 fn to_cursors(&self, s: &mut impl CursorSink) {
216 ToCursors::to_cursors(&self.0, s);
217 }
218 }
219
220 impl ToSpan for Decl {
221 fn to_span(&self) -> Span {
222 self.0.to_span()
223 }
224 }
225
226 impl SemanticEq for Decl {
227 fn semantic_eq(&self, other: &Self) -> bool {
228 self.0.semantic_eq(&other.0)
229 }
230 }
231
232 #[test]
233 fn size_test() {
234 assert_eq!(std::mem::size_of::<QualifiedRule<T![Ident], Decl, T![Ident], ()>>(), 112);
235 }
236
237 #[test]
238 fn test_writes() {
239 assert_parse!(EmptyAtomSet::ATOMS, QualifiedRule<T![Ident], Decl, T![Ident], ()>, "body{color:black}");
240 }
241}