1use crate::{
2 BadDeclaration, Block, CursorSink, DeclarationValue, Diagnostic, Kind, KindSet, NodeMetadata, NodeWithMetadata,
3 Parse, Parser, Peek, Result, SemanticEq, Span, State, T, ToCursors, ToSpan,
4};
5use csskit_proc_macro::node;
6
7#[node]
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize))]
10#[cfg_attr(
11 feature = "serde",
12 serde(bound(serialize = "P: serde::Serialize, D: serde::Serialize, R: serde::Serialize"))
13)]
14pub struct QualifiedRule<'a, P, D, R, M>
15where
16 D: DeclarationValue<'a, M>,
18 M: NodeMetadata,
19{
20 pub prelude: P,
21 pub block: Block<'a, D, R, M>,
22 #[cfg_attr(feature = "serde", serde(skip))]
23 meta: M,
24}
25
26impl<'a, P, D, R, M> NodeWithMetadata<M> for QualifiedRule<'a, P, D, R, M>
27where
28 D: DeclarationValue<'a, M>,
29 M: NodeMetadata,
30{
31 fn metadata(&self) -> M {
32 self.meta
33 }
34}
35
36impl<'a, P, D, R, M> Peek<'a> for QualifiedRule<'a, P, D, R, M>
37where
38 P: Peek<'a>,
39 D: DeclarationValue<'a, M>,
40 M: NodeMetadata,
41{
42 const PEEK_KINDSET: KindSet = P::PEEK_KINDSET;
43}
44
45impl<'a, P, D, R, M> Parse<'a> for QualifiedRule<'a, P, D, R, M>
49where
50 D: DeclarationValue<'a, M>,
51 P: Parse<'a>,
52 R: Parse<'a> + NodeWithMetadata<M> + crate::RuleVariants<'a, DeclarationValue = D, Metadata = M>,
53 M: NodeMetadata,
54{
55 fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
56 where
57 Iter: Iterator<Item = crate::Cursor> + Clone,
58 {
59 let c = p.peek_n(1);
60 if p.at_end() {
68 Err(Diagnostic::new(p.peek_n(1), Diagnostic::unexpected_end))?
69 }
70
71 if p.is(State::Nested) && <T!['}']>::peek(p, c) {
74 Err(Diagnostic::new(c, Diagnostic::unexpected_close_curly))?;
75 }
76
77 let checkpoint = p.checkpoint();
80 if <T![DashedIdent]>::peek(p, c) {
81 p.parse::<T![DashedIdent]>().ok();
82 if <T![:]>::peek(p, p.peek_n(1)) {
83 if p.is(State::Nested) {
85 p.rewind(checkpoint.clone());
86 let start = p.peek_n(1);
87 p.parse::<BadDeclaration>()?;
88 let end = p.peek_n(1);
89 Err(Diagnostic::new(start, Diagnostic::bad_declaration).with_end_cursor(end))?
90 } else {
92 p.parse::<Block<'a, D, R, M>>()?;
98 let start = p.peek_n(1);
99 p.parse::<BadDeclaration>()?;
100 let end = p.peek_n(1);
101 Err(Diagnostic::new(start, Diagnostic::bad_declaration).with_end_cursor(end))?
102 }
103 }
104 p.rewind(checkpoint);
105 }
106
107 let old_stop = p.set_stop(KindSet::new(&[Kind::LeftCurly]));
109 let prelude = p.parse::<P>();
110 p.set_stop(old_stop);
111 let prelude = prelude?;
112
113 let block = p.parse::<Block<'a, D, R, M>>()?;
120 let meta = block.metadata();
121 Ok(Self { prelude, block, meta })
122 }
123}
124
125impl<'a, P, D, R, M> ToCursors for QualifiedRule<'a, P, D, R, M>
126where
127 D: DeclarationValue<'a, M> + ToCursors,
128 P: ToCursors,
129 R: ToCursors,
130 M: NodeMetadata,
131{
132 fn to_cursors(&self, s: &mut impl CursorSink) {
133 ToCursors::to_cursors(&self.prelude, s);
134 ToCursors::to_cursors(&self.block, s);
135 }
136}
137
138impl<'a, P, D, R, M> ToSpan for QualifiedRule<'a, P, D, R, M>
139where
140 D: DeclarationValue<'a, M> + ToSpan,
141 P: ToSpan,
142 R: ToSpan,
143 M: NodeMetadata,
144{
145 fn to_span(&self) -> Span {
146 self.prelude.to_span() + self.block.to_span()
147 }
148}
149
150impl<'a, P, D, R, M> SemanticEq for QualifiedRule<'a, P, D, R, M>
151where
152 D: DeclarationValue<'a, M> + SemanticEq,
153 P: SemanticEq,
154 R: SemanticEq,
155 M: NodeMetadata,
156{
157 fn semantic_eq(&self, other: &Self) -> bool {
158 self.prelude.semantic_eq(&other.prelude) && self.block.semantic_eq(&other.block)
159 }
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165 use crate::{Cursor, EmptyAtomSet, test_helpers::*};
166
167 #[derive(Debug)]
168 struct Decl(T![Ident]);
169
170 impl NodeWithMetadata<()> for Decl {
171 fn metadata(&self) {}
172 }
173
174 impl<'a> DeclarationValue<'a, ()> for Decl {
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 test_writes() {
260 assert_parse!(EmptyAtomSet::ATOMS, QualifiedRule<T![Ident], Decl, Rule, ()>, "body{color:black}");
261 }
262}