1include!(concat!(env!("OUT_DIR"), "/css_node_kind.rs"));
2include!(concat!(env!("OUT_DIR"), "/css_apply_visit_methods.rs"));
3
4use css_parse::Vec;
5use css_parse::{
6 AttributeOperator, Block, Box, CommaSeparated, Comparison, ComponentValue, ComponentValues, Cursor, Declaration,
7 DeclarationGroup, DeclarationList, DeclarationOrBad, DeclarationValue, Either, NoBlockAllowed, NodeMetadata,
8 NodeWithMetadata, Optionals2, Optionals3, Optionals4, Optionals5, Parse, Peek, QualifiedRule, RuleList, Span,
9 ToCursors, ToSpan, syntax::BadDeclaration, token_macros,
10};
11use visit_flow::{VisitFlow, try_visit};
12
13pub use csskit_derives::visitor;
16pub use visit_flow::{VisitAction, VisitBreak, VisitFlowExt};
17
18mod root;
19mod visit_node;
20pub use root::{ErasedNode, ParsedRoot, parse_root};
21pub(crate) use visit_node::QueryNodeData;
22pub use visit_node::{NodeKey, VisitNode};
23
24use crate::*;
25
26macro_rules! visit_mut_trait {
27 ( $(
28 $name: ident$(<$($gen:tt),+>)?($obj: ty),
29 )+ ) => {
30 pub trait VisitMut: Sized {
31 fn visit_declaration<'a, T: DeclarationValue<'a, CssMetadata>>(&mut self, _rule: &mut Declaration<'a, T, CssMetadata>) {}
32 fn exit_declaration<'a, T: DeclarationValue<'a, CssMetadata>>(&mut self, _rule: &mut Declaration<'a, T, CssMetadata>) {}
33 fn visit_bad_declaration<'a>(&mut self, _rule: &mut BadDeclaration<'a>) {}
34 fn exit_bad_declaration<'a>(&mut self, _rule: &mut BadDeclaration<'a>) {}
35 fn visit_string(&mut self, _str: &mut token_macros::String) {}
36 fn exit_string(&mut self, _str: &mut token_macros::String) {}
37 fn visit_comparison(&mut self, _comparison: &mut Comparison) {}
38 fn exit_comparison(&mut self, _comparison: &mut Comparison) {}
39 $(
40 fn $name$(<$($gen),+>)?(&mut self, _rule: &mut $obj) {}
41 )+
42 }
43 }
44}
45apply_visit_methods!(visit_mut_trait);
46
47pub trait NodeVisitor {
54 fn consider_node(&self, node: VisitNode) -> VisitFlow;
59
60 fn enter_node(&mut self, node: VisitNode) -> VisitFlow;
65
66 fn exit_node(&mut self, node: VisitNode) -> VisitFlow;
68}
69
70impl NodeVisitor for &mut (dyn NodeVisitor + '_) {
71 fn consider_node(&self, node: VisitNode) -> VisitFlow {
72 (**self).consider_node(node)
73 }
74
75 fn enter_node(&mut self, node: VisitNode) -> VisitFlow {
76 (**self).enter_node(node)
77 }
78
79 fn exit_node(&mut self, node: VisitNode) -> VisitFlow {
80 (**self).exit_node(node)
81 }
82}
83
84impl Visit for &mut (dyn NodeVisitor + '_) {}
85
86macro_rules! visit_trait {
87 ( $(
88 $name: ident$(<$($gen:tt),+>)?($obj: ty),
89 )+ ) => {
90 pub trait Visit: NodeVisitor + Sized {
91
92 fn enter_declaration<'a, T: DeclarationValue<'a, CssMetadata>>(&mut self, _rule: &Declaration<'a, T, CssMetadata>, _node: VisitNode) -> VisitFlow {
93 VisitFlow::DESCEND
94 }
95 fn exit_declaration<'a, T: DeclarationValue<'a, CssMetadata>>(&mut self, _rule: &Declaration<'a, T, CssMetadata>, _node: VisitNode) -> VisitFlow {
96 VisitFlow::DESCEND
97 }
98 fn visit_bad_declaration<'a>(&mut self, _rule: &BadDeclaration<'a>) -> VisitFlow {
99 VisitFlow::DESCEND
100 }
101 fn exit_bad_declaration<'a>(&mut self, _rule: &BadDeclaration<'a>) -> VisitFlow {
102 VisitFlow::DESCEND
103 }
104 fn visit_string(&mut self, _str: &token_macros::String) -> VisitFlow {
105 VisitFlow::DESCEND
106 }
107 fn exit_string(&mut self, _str: &token_macros::String) -> VisitFlow {
108 VisitFlow::DESCEND
109 }
110 fn visit_comparison(&mut self, _comparison: &Comparison) -> VisitFlow {
111 VisitFlow::DESCEND
112 }
113 fn exit_comparison(&mut self, _comparison: &Comparison) -> VisitFlow {
114 VisitFlow::DESCEND
115 }
116
117 fn visit_feature<T: FeatureMetadata>(&mut self, _node: &T) {}
118 fn exit_feature<T: FeatureMetadata>(&mut self, _node: &T) {}
119
120 $(
121 fn $name$(<$($gen),+>)?(&mut self, _rule: &$obj) -> VisitFlow {
122 VisitFlow::DESCEND
123 }
124 )+
125 }
126 }
127}
128apply_visit_methods!(visit_trait);
129
130pub trait VisitableMut {
131 fn accept_mut<V: VisitMut>(&mut self, v: &mut V);
132}
133
134pub trait Visitable {
135 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow;
136}
137
138pub(crate) trait QueryableNode: ToSpan + NodeWithMetadata<CssMetadata> {
144 const NODE_ID: NodeId;
146
147 fn get_property(&self, _kind: PropertyKind) -> Option<Cursor> {
153 None
154 }
155
156 fn visit_node(&self) -> VisitNode<'_>
161 where
162 Self: Sized,
163 {
164 VisitNode::new(Self::NODE_ID, self)
165 }
166}
167
168impl<T: QueryableNode> QueryNodeData for T {
170 #[inline]
171 fn span(&self) -> Span {
172 ToSpan::to_span(self)
173 }
174
175 #[inline]
176 fn self_metadata(&self) -> CssMetadata {
177 NodeWithMetadata::self_metadata(self)
178 }
179
180 #[inline]
181 fn subtree_metadata(&self) -> CssMetadata {
182 NodeWithMetadata::metadata(self)
183 }
184
185 #[inline]
186 fn get_property(&self, kind: PropertyKind) -> Option<Cursor> {
187 QueryableNode::get_property(self, kind)
188 }
189}
190
191impl<T> VisitableMut for Option<T>
192where
193 T: VisitableMut,
194{
195 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
196 if let Some(node) = self {
197 node.accept_mut(v)
198 }
199 }
200}
201
202macro_rules! impl_optionals {
203 ($N:ident, $($T:ident),+) => {
204 impl<$($T),*> Visitable for $N<$($T),+>
205 where
206 $($T: Visitable,)+
207 {
208 #[allow(non_snake_case)]
209 #[allow(unused)]
210 fn accept<VI: Visit>(&self, v: &mut VI) -> VisitFlow {
211 let $N($($T),+) = self;
212 $(try_visit!($T.accept(v));)+;
213 VisitFlow::DESCEND
214 }
215 }
216
217 impl<$($T),*> VisitableMut for $N<$($T),+>
218 where
219 $($T: VisitableMut,)+
220 {
221 #[allow(non_snake_case)]
222 #[allow(unused)]
223 fn accept_mut<VI: VisitMut>(&mut self, v: &mut VI) {
224 let $N($($T),+) = self;
225 $($T.accept_mut(v);)+;
226 }
227 }
228 };
229}
230
231impl_optionals!(Optionals2, T, U);
232impl_optionals!(Optionals3, T, U, V);
233impl_optionals!(Optionals4, T, U, V, W);
234impl_optionals!(Optionals5, T, U, V, W, X);
235
236impl Visitable for token_macros::Ident {
237 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
238 VisitFlow::DESCEND
239 }
240}
241
242impl VisitableMut for token_macros::Ident {
243 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
244}
245
246impl Visitable for token_macros::Function {
247 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
248 VisitFlow::DESCEND
249 }
250}
251
252impl VisitableMut for token_macros::Function {
253 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
254}
255
256impl Visitable for token_macros::Comma {
257 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
258 VisitFlow::DESCEND
259 }
260}
261
262impl VisitableMut for token_macros::Comma {
263 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
264}
265
266impl Visitable for token_macros::LeftParen {
267 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
268 VisitFlow::DESCEND
269 }
270}
271
272impl VisitableMut for token_macros::LeftParen {
273 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
274}
275
276impl Visitable for token_macros::RightParen {
277 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
278 VisitFlow::DESCEND
279 }
280}
281
282impl VisitableMut for token_macros::RightParen {
283 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
284}
285
286impl Visitable for token_macros::Colon {
287 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
288 VisitFlow::DESCEND
289 }
290}
291
292impl VisitableMut for token_macros::Colon {
293 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
294}
295
296impl Visitable for token_macros::Semicolon {
297 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
298 VisitFlow::DESCEND
299 }
300}
301
302impl VisitableMut for token_macros::Semicolon {
303 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
304}
305
306impl Visitable for Comparison {
307 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
308 try_visit!(v.visit_comparison(self));
309 try_visit!(v.exit_comparison(self));
310 VisitFlow::DESCEND
311 }
312}
313
314impl VisitableMut for Comparison {
315 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
316 v.visit_comparison(self);
317 v.exit_comparison(self);
318 }
319}
320
321impl Visitable for token_macros::delim::Dash {
322 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
323 VisitFlow::DESCEND
324 }
325}
326
327impl VisitableMut for token_macros::delim::Dash {
328 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
329}
330
331impl Visitable for token_macros::delim::Slash {
332 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
333 VisitFlow::DESCEND
334 }
335}
336
337impl VisitableMut for token_macros::delim::Slash {
338 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
339}
340
341impl Visitable for token_macros::Number {
342 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
343 VisitFlow::DESCEND
344 }
345}
346
347impl VisitableMut for token_macros::Number {
348 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
349}
350
351impl Visitable for token_macros::Any {
352 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
353 VisitFlow::DESCEND
354 }
355}
356
357impl VisitableMut for token_macros::Any {
358 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
359}
360
361impl Visitable for token_macros::String {
362 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
363 try_visit!(v.visit_string(self));
364 try_visit!(v.exit_string(self));
365 VisitFlow::DESCEND
366 }
367}
368
369impl VisitableMut for token_macros::String {
370 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
371 v.visit_string(self);
372 v.exit_string(self);
373 }
374}
375
376impl<T> Visitable for Option<T>
377where
378 T: Visitable,
379{
380 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
381 if let Some(node) = self {
382 try_visit!(node.accept(v));
383 }
384 VisitFlow::DESCEND
385 }
386}
387
388impl<'a, T: VisitableMut> VisitableMut for Box<'a, T> {
389 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
390 (**self).accept_mut(v)
391 }
392}
393
394impl<'a, T: Visitable> Visitable for Box<'a, T> {
395 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
396 (**self).accept(v)
397 }
398}
399
400impl<'a, T, const MIN: usize> VisitableMut for CommaSeparated<'a, T, MIN>
401where
402 T: VisitableMut,
403{
404 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
405 for (node, _) in self {
406 node.accept_mut(v)
407 }
408 }
409}
410
411impl<'a, T, const MIN: usize> Visitable for CommaSeparated<'a, T, MIN>
412where
413 T: Visitable,
414{
415 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
416 for (node, _) in self {
417 try_visit!(node.accept(v));
418 }
419 VisitFlow::DESCEND
420 }
421}
422
423impl<Left, Right> VisitableMut for Either<Left, Right>
424where
425 Left: VisitableMut,
426 Right: VisitableMut,
427{
428 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
429 match self {
430 Self::Left(t) => t.accept_mut(v),
431 Self::Right(t) => t.accept_mut(v),
432 }
433 }
434}
435
436impl<Left, Right> Visitable for Either<Left, Right>
437where
438 Left: Visitable,
439 Right: Visitable,
440{
441 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
442 match self {
443 Self::Left(t) => t.accept(v),
444 Self::Right(t) => t.accept(v),
445 }
446 }
447}
448
449impl<'a, T> VisitableMut for Declaration<'a, T, CssMetadata>
450where
451 T: VisitableMut + DeclarationValue<'a, CssMetadata>,
452{
453 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
454 v.visit_declaration(self);
455 self.value.accept_mut(v);
456 v.exit_declaration(self);
457 }
458}
459
460impl<'a, T> QueryableNode for Declaration<'a, T, CssMetadata>
461where
462 T: DeclarationValue<'a, CssMetadata> + QueryableNode,
463{
464 const NODE_ID: NodeId = NodeId::StyleValue;
465
466 fn get_property(&self, kind: PropertyKind) -> Option<Cursor> {
467 match kind {
468 PropertyKind::Name => Some(self.name.into()),
469 _ => None,
470 }
471 }
472
473 fn visit_node(&self) -> VisitNode<'_> {
474 VisitNode::new(T::NODE_ID, self)
476 }
477}
478
479impl<'a, T> Visitable for Declaration<'a, T, CssMetadata>
480where
481 T: Visitable + DeclarationValue<'a, CssMetadata> + QueryableNode,
482{
483 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
484 let node = self.visit_node();
485 if let visit_flow::VisitAction::SkipChildren = try_visit!(v.consider_node(node)) {
486 return VisitFlow::DESCEND;
487 }
488 if let visit_flow::VisitAction::Descend = visit_flow::try_visit!(v.enter_node(node)) {
489 if let visit_flow::VisitAction::Descend = visit_flow::try_visit!(v.enter_declaration::<T>(self, node)) {
490 try_visit!(self.value.accept(v));
491 }
492 try_visit!(v.exit_declaration::<T>(self, node));
493 }
494 try_visit!(v.exit_node(node));
495 VisitFlow::DESCEND
496 }
497}
498
499impl<'a, T> VisitableMut for DeclarationList<'a, T, CssMetadata>
500where
501 T: VisitableMut + DeclarationValue<'a, CssMetadata>,
502{
503 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
504 for declaration in &mut self.declarations {
505 declaration.accept_mut(v);
506 }
507 }
508}
509
510impl<'a, T> Visitable for DeclarationList<'a, T, CssMetadata>
511where
512 T: Visitable + DeclarationValue<'a, CssMetadata> + QueryableNode,
513{
514 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
515 for declaration in &self.declarations {
516 try_visit!(declaration.accept(v));
517 }
518 VisitFlow::DESCEND
519 }
520}
521
522impl<'a, T, M> VisitableMut for RuleList<'a, T, M>
523where
524 T: VisitableMut + Parse<'a> + ToCursors + ToSpan + NodeWithMetadata<M>,
525 M: NodeMetadata,
526{
527 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
528 self.rules.accept_mut(v);
529 }
530}
531
532impl<'a, T, M> Visitable for RuleList<'a, T, M>
533where
534 T: Visitable + Parse<'a> + ToCursors + ToSpan + NodeWithMetadata<M>,
535 M: NodeMetadata,
536{
537 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
538 self.rules.accept(v)
539 }
540}
541
542impl<'a, P, D, R> VisitableMut for QualifiedRule<'a, P, D, R, CssMetadata>
543where
544 P: VisitableMut + Peek<'a> + Parse<'a> + ToCursors + ToSpan,
545 D: VisitableMut + DeclarationValue<'a, CssMetadata>,
546 R: VisitableMut + Parse<'a> + ToCursors + ToSpan,
547 Block<'a, D, R, CssMetadata>: Parse<'a> + ToCursors + ToSpan,
548{
549 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
550 self.prelude.accept_mut(v);
551 self.block.accept_mut(v);
552 }
553}
554
555impl<'a, P, D, R> Visitable for QualifiedRule<'a, P, D, R, CssMetadata>
556where
557 P: Visitable + Peek<'a> + Parse<'a> + ToCursors + ToSpan,
558 D: Visitable + DeclarationValue<'a, CssMetadata> + QueryableNode,
559 R: Visitable + Parse<'a> + ToCursors + ToSpan,
560 Block<'a, D, R, CssMetadata>: Parse<'a> + ToCursors + ToSpan,
561{
562 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
563 try_visit!(self.prelude.accept(v));
564 self.block.accept(v)
565 }
566}
567
568impl<'a, D, R> VisitableMut for Block<'a, D, R, CssMetadata>
569where
570 D: VisitableMut + DeclarationValue<'a, CssMetadata>,
571 R: VisitableMut + Parse<'a> + ToCursors + ToSpan,
572{
573 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
574 for declaration in &mut self.declarations {
575 declaration.accept_mut(v);
576 }
577 for rule in &mut self.rules {
578 rule.accept_mut(v);
579 }
580 }
581}
582
583impl<'a, D, R> Visitable for Block<'a, D, R, CssMetadata>
584where
585 D: Visitable + DeclarationValue<'a, CssMetadata> + QueryableNode,
586 R: Visitable + Parse<'a> + ToCursors + ToSpan,
587{
588 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
589 for declaration in &self.declarations {
590 try_visit!(declaration.accept(v));
591 }
592 for rule in &self.rules {
593 try_visit!(rule.accept(v));
594 }
595 VisitFlow::DESCEND
596 }
597}
598
599impl<'a, T> VisitableMut for Vec<'a, T>
600where
601 T: VisitableMut,
602{
603 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
604 for node in self {
605 node.accept_mut(v);
606 }
607 }
608}
609
610impl<'a, T> Visitable for Vec<'a, T>
611where
612 T: Visitable,
613{
614 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
615 for node in self {
616 try_visit!(node.accept(v));
617 }
618 VisitFlow::DESCEND
619 }
620}
621
622impl<'a> VisitableMut for BadDeclaration<'a> {
623 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
624 v.visit_bad_declaration(self);
625 v.exit_bad_declaration(self);
626 }
627}
628
629impl<'a> Visitable for BadDeclaration<'a> {
630 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
631 try_visit!(v.visit_bad_declaration(self));
632 try_visit!(v.exit_bad_declaration(self));
633 VisitFlow::DESCEND
634 }
635}
636
637impl<'a> VisitableMut for ComponentValues<'a> {
638 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
639 v.visit_component_values(self);
640 for value in &mut self.values {
641 value.accept_mut(v);
642 }
643 v.exit_component_values(self);
644 }
645}
646
647impl<'a> QueryableNode for ComponentValues<'a> {
648 const NODE_ID: NodeId = NodeId::ComponentValues;
649}
650
651impl<'a> Visitable for ComponentValues<'a> {
652 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
653 let node = QueryableNode::visit_node(self);
654 if let VisitAction::SkipChildren = try_visit!(v.consider_node(node)) {
655 return VisitFlow::DESCEND;
656 }
657 if let VisitAction::Descend = try_visit!(v.enter_node(node)) {
658 if let VisitAction::Descend = try_visit!(v.visit_component_values(self)) {
659 for value in &self.values {
660 try_visit!(value.accept(v));
661 }
662 }
663 try_visit!(v.exit_component_values(self));
664 }
665 try_visit!(v.exit_node(node));
666 VisitFlow::DESCEND
667 }
668}
669
670impl<'a> VisitableMut for ComponentValue<'a> {
671 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
672 v.visit_component_value(self);
673 match self {
674 ComponentValue::SimpleBlock(block) => block.values.accept_mut(v),
675 ComponentValue::Function(function) => function.params.accept_mut(v),
676 _ => {}
677 }
678 v.exit_component_value(self);
679 }
680}
681
682impl<'a> QueryableNode for ComponentValue<'a> {
683 const NODE_ID: NodeId = NodeId::ComponentValue;
684}
685
686impl<'a> Visitable for ComponentValue<'a> {
687 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
688 let node = QueryableNode::visit_node(self);
689 if let VisitAction::SkipChildren = try_visit!(v.consider_node(node)) {
690 return VisitFlow::DESCEND;
691 }
692 if let VisitAction::Descend = try_visit!(v.enter_node(node)) {
693 if let VisitAction::Descend = try_visit!(v.visit_component_value(self)) {
694 match self {
695 ComponentValue::SimpleBlock(block) => {
696 try_visit!(block.values.accept(v));
697 }
698 ComponentValue::Function(function) => {
699 try_visit!(function.params.accept(v));
700 }
701 _ => {}
702 }
703 }
704 try_visit!(v.exit_component_value(self));
705 }
706 try_visit!(v.exit_node(node));
707 VisitFlow::DESCEND
708 }
709}
710
711impl VisitableMut for AttributeOperator {
712 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
713 v.visit_attribute_operator(self);
714 v.exit_attribute_operator(self);
715 }
716}
717
718impl QueryableNode for AttributeOperator {
719 const NODE_ID: NodeId = NodeId::AttributeOperator;
720}
721
722impl Visitable for AttributeOperator {
723 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
724 let node = QueryableNode::visit_node(self);
725 if let VisitAction::SkipChildren = try_visit!(v.consider_node(node)) {
726 return VisitFlow::DESCEND;
727 }
728 if let VisitAction::Descend = try_visit!(v.enter_node(node)) {
729 try_visit!(v.visit_attribute_operator(self));
730 try_visit!(v.exit_attribute_operator(self));
731 }
732 try_visit!(v.exit_node(node));
733 VisitFlow::DESCEND
734 }
735}
736
737impl<'a> VisitableMut for Unresolved<'a> {
738 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
739}
740
741impl<'a> Visitable for Unresolved<'a> {
742 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
743 VisitFlow::DESCEND
744 }
745}
746
747impl<D, M> VisitableMut for NoBlockAllowed<D, M> {
748 fn accept_mut<V: VisitMut>(&mut self, _: &mut V) {}
749}
750
751impl<D, M> Visitable for NoBlockAllowed<D, M> {
752 fn accept<V: Visit>(&self, _: &mut V) -> VisitFlow {
753 VisitFlow::DESCEND
754 }
755}
756
757impl<'a, D> VisitableMut for DeclarationGroup<'a, D, CssMetadata>
758where
759 D: VisitableMut + DeclarationValue<'a, CssMetadata>,
760{
761 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
762 for declaration in &mut self.declarations {
763 declaration.accept_mut(v)
764 }
765 }
766}
767
768impl<'a, D> Visitable for DeclarationGroup<'a, D, CssMetadata>
769where
770 D: Visitable + DeclarationValue<'a, CssMetadata> + QueryableNode,
771{
772 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
773 for declaration in &self.declarations {
774 try_visit!(declaration.accept(v));
775 }
776 VisitFlow::DESCEND
777 }
778}
779
780impl<'a, D> VisitableMut for DeclarationOrBad<'a, D, CssMetadata>
781where
782 D: VisitableMut + DeclarationValue<'a, CssMetadata>,
783{
784 fn accept_mut<V: VisitMut>(&mut self, v: &mut V) {
785 match self {
786 Self::Declaration(d) => d.accept_mut(v),
787 Self::Bad(b) => b.accept_mut(v),
788 }
789 }
790}
791
792impl<'a, D> Visitable for DeclarationOrBad<'a, D, CssMetadata>
793where
794 D: Visitable + DeclarationValue<'a, CssMetadata> + QueryableNode,
795{
796 fn accept<V: Visit>(&self, v: &mut V) -> VisitFlow {
797 match self {
798 Self::Declaration(d) => d.accept(v),
799 Self::Bad(b) => b.accept(v),
800 }
801 }
802}
803
804macro_rules! impl_tuple_mut {
805 ($($T:ident),*) => {
806 impl<$($T),*> VisitableMut for ($($T),*)
807 where
808 $($T: VisitableMut,)*
809 {
810 #[allow(non_snake_case)]
811 #[allow(unused)]
812 fn accept_mut<VI: VisitMut>(&mut self, v: &mut VI) {
813 let ($($T),*) = self;
814 $($T.accept_mut(v);)*
815 }
816 }
817 };
818}
819
820impl_tuple_mut!(T, U);
821impl_tuple_mut!(T, U, V);
822impl_tuple_mut!(T, U, V, W);
823impl_tuple_mut!(T, U, V, W, X);
824impl_tuple_mut!(T, U, V, W, X, Y);
825impl_tuple_mut!(T, U, V, W, X, Y, Z);
826impl_tuple_mut!(T, U, V, W, X, Y, Z, A);
827impl_tuple_mut!(T, U, V, W, X, Y, Z, A, B);
828impl_tuple_mut!(T, U, V, W, X, Y, Z, A, B, C);
829impl_tuple_mut!(T, U, V, W, X, Y, Z, A, B, C, D);
830impl_tuple_mut!(T, U, V, W, X, Y, Z, A, B, C, D, E);
831
832macro_rules! impl_tuple {
833 ($($T:ident),*) => {
834 impl<$($T),*> Visitable for ($($T),*)
835 where
836 $($T: Visitable,)*
837 {
838 #[allow(non_snake_case)]
839 #[allow(unused)]
840 fn accept<VI: Visit>(&self, v: &mut VI) -> VisitFlow {
841 let ($($T),*) = self;
842 $(try_visit!($T.accept(v));)*
843 VisitFlow::DESCEND
844 }
845 }
846 };
847}
848impl_tuple!(T, U);
849impl_tuple!(T, U, V);
850impl_tuple!(T, U, V, W);
851impl_tuple!(T, U, V, W, X);
852impl_tuple!(T, U, V, W, X, Y);
853impl_tuple!(T, U, V, W, X, Y, Z);
854impl_tuple!(T, U, V, W, X, Y, Z, A);
855impl_tuple!(T, U, V, W, X, Y, Z, A, B);
856impl_tuple!(T, U, V, W, X, Y, Z, A, B, C);
857impl_tuple!(T, U, V, W, X, Y, Z, A, B, C, D);
858impl_tuple!(T, U, V, W, X, Y, Z, A, B, C, D, E);