1use crate::{
62 declaration::DeclarationBlock,
63 media_query::{MediaFeature, MediaFeatureValue, MediaList, MediaQuery},
64 parser::DefaultAtRule,
65 properties::{
66 custom::{EnvironmentVariable, Function, TokenList, TokenOrValue, Variable},
67 Property,
68 },
69 rules::{supports::SupportsCondition, CssRule, CssRuleList},
70 selector::{Selector, SelectorList},
71 stylesheet::StyleSheet,
72 values::{
73 angle::Angle,
74 color::CssColor,
75 ident::{CustomIdent, DashedIdent},
76 image::Image,
77 length::LengthValue,
78 ratio::Ratio,
79 resolution::Resolution,
80 time::Time,
81 url::Url,
82 },
83};
84use bitflags::bitflags;
85use indexmap::IndexMap;
86use smallvec::SmallVec;
87
88pub(crate) use lightningcss_derive::Visit;
89
90bitflags! {
91 #[derive(PartialEq, Eq, Clone, Copy)]
96 pub struct VisitTypes: u32 {
97 const RULES = 1 << 0;
99 const PROPERTIES = 1 << 1;
101 const URLS = 1 << 2;
103 const COLORS = 1 << 3;
105 const IMAGES = 1 << 4;
107 const LENGTHS = 1 << 5;
109 const ANGLES = 1 << 6;
111 const RATIOS = 1 << 7;
113 const RESOLUTIONS = 1 << 8;
115 const TIMES = 1 << 9;
117 const CUSTOM_IDENTS = 1 << 10;
119 const DASHED_IDENTS = 1 << 11;
121 const VARIABLES = 1 << 12;
123 const ENVIRONMENT_VARIABLES = 1 << 13;
125 const MEDIA_QUERIES = 1 << 14;
127 const SUPPORTS_CONDITIONS = 1 << 15;
129 const SELECTORS = 1 << 16;
131 const FUNCTIONS = 1 << 17;
133 const TOKENS = 1 << 18;
135 }
136}
137
138#[macro_export]
140macro_rules! visit_types {
141 ($( $flag: ident )|+) => {
142 $crate::visitor::VisitTypes::from_bits_truncate(0 $(| $crate::visitor::VisitTypes::$flag.bits())+)
143 }
144}
145
146pub trait Visitor<'i, T: Visit<'i, T, Self> = DefaultAtRule> {
148 type Error;
150
151 fn visit_types(&self) -> VisitTypes;
154
155 #[inline]
157 fn visit_stylesheet<'o>(&mut self, stylesheet: &mut StyleSheet<'i, 'o, T>) -> Result<(), Self::Error> {
158 stylesheet.visit_children(self)
159 }
160
161 #[inline]
163 fn visit_rule_list(&mut self, rules: &mut CssRuleList<'i, T>) -> Result<(), Self::Error> {
164 rules.visit_children(self)
165 }
166
167 #[inline]
169 fn visit_rule(&mut self, rule: &mut CssRule<'i, T>) -> Result<(), Self::Error> {
170 rule.visit_children(self)
171 }
172
173 #[inline]
175 fn visit_declaration_block(&mut self, decls: &mut DeclarationBlock<'i>) -> Result<(), Self::Error> {
176 decls.visit_children(self)
177 }
178
179 #[inline]
181 fn visit_property(&mut self, property: &mut Property<'i>) -> Result<(), Self::Error> {
182 property.visit_children(self)
183 }
184
185 fn visit_url(&mut self, _url: &mut Url<'i>) -> Result<(), Self::Error> {
187 Ok(())
188 }
189
190 #[allow(unused_variables)]
192 fn visit_color(&mut self, color: &mut CssColor) -> Result<(), Self::Error> {
193 Ok(())
194 }
195
196 #[inline]
198 fn visit_image(&mut self, image: &mut Image<'i>) -> Result<(), Self::Error> {
199 image.visit_children(self)
200 }
201
202 #[allow(unused_variables)]
204 fn visit_length(&mut self, length: &mut LengthValue) -> Result<(), Self::Error> {
205 Ok(())
206 }
207
208 #[allow(unused_variables)]
210 fn visit_angle(&mut self, angle: &mut Angle) -> Result<(), Self::Error> {
211 Ok(())
212 }
213
214 #[allow(unused_variables)]
216 fn visit_ratio(&mut self, ratio: &mut Ratio) -> Result<(), Self::Error> {
217 Ok(())
218 }
219
220 #[allow(unused_variables)]
222 fn visit_resolution(&mut self, resolution: &mut Resolution) -> Result<(), Self::Error> {
223 Ok(())
224 }
225
226 #[allow(unused_variables)]
228 fn visit_time(&mut self, time: &mut Time) -> Result<(), Self::Error> {
229 Ok(())
230 }
231
232 #[allow(unused_variables)]
234 fn visit_custom_ident(&mut self, ident: &mut CustomIdent) -> Result<(), Self::Error> {
235 Ok(())
236 }
237
238 #[allow(unused_variables)]
240 fn visit_dashed_ident(&mut self, ident: &mut DashedIdent) -> Result<(), Self::Error> {
241 Ok(())
242 }
243
244 #[inline]
246 fn visit_variable(&mut self, var: &mut Variable<'i>) -> Result<(), Self::Error> {
247 var.visit_children(self)
248 }
249
250 #[inline]
252 fn visit_environment_variable(&mut self, env: &mut EnvironmentVariable<'i>) -> Result<(), Self::Error> {
253 env.visit_children(self)
254 }
255
256 #[inline]
258 fn visit_media_list(&mut self, media: &mut MediaList<'i>) -> Result<(), Self::Error> {
259 media.visit_children(self)
260 }
261
262 #[inline]
264 fn visit_media_query(&mut self, query: &mut MediaQuery<'i>) -> Result<(), Self::Error> {
265 query.visit_children(self)
266 }
267
268 #[inline]
270 fn visit_media_feature(&mut self, feature: &mut MediaFeature<'i>) -> Result<(), Self::Error> {
271 feature.visit_children(self)
272 }
273
274 #[inline]
276 fn visit_media_feature_value(&mut self, value: &mut MediaFeatureValue<'i>) -> Result<(), Self::Error> {
277 value.visit_children(self)
278 }
279
280 #[inline]
282 fn visit_supports_condition(&mut self, condition: &mut SupportsCondition<'i>) -> Result<(), Self::Error> {
283 condition.visit_children(self)
284 }
285
286 #[inline]
288 fn visit_selector_list(&mut self, selectors: &mut SelectorList<'i>) -> Result<(), Self::Error> {
289 selectors.visit_children(self)
290 }
291
292 #[allow(unused_variables)]
294 fn visit_selector(&mut self, selector: &mut Selector<'i>) -> Result<(), Self::Error> {
295 Ok(())
296 }
297
298 #[inline]
300 fn visit_function(&mut self, function: &mut Function<'i>) -> Result<(), Self::Error> {
301 function.visit_children(self)
302 }
303
304 #[inline]
306 fn visit_token_list(&mut self, tokens: &mut TokenList<'i>) -> Result<(), Self::Error> {
307 tokens.visit_children(self)
308 }
309
310 #[inline]
312 fn visit_token(&mut self, token: &mut TokenOrValue<'i>) -> Result<(), Self::Error> {
313 token.visit_children(self)
314 }
315}
316
317pub trait Visit<'i, T: Visit<'i, T, V>, V: ?Sized + Visitor<'i, T>> {
319 const CHILD_TYPES: VisitTypes;
323
324 #[inline]
327 fn visit(&mut self, visitor: &mut V) -> Result<(), V::Error> {
328 self.visit_children(visitor)
329 }
330
331 fn visit_children(&mut self, visitor: &mut V) -> Result<(), V::Error>;
333}
334
335impl<'i, T: Visit<'i, T, V>, V: ?Sized + Visitor<'i, T>, U: Visit<'i, T, V>> Visit<'i, T, V> for Option<U> {
336 const CHILD_TYPES: VisitTypes = U::CHILD_TYPES;
337
338 fn visit(&mut self, visitor: &mut V) -> Result<(), V::Error> {
339 if let Some(v) = self {
340 v.visit(visitor)
341 } else {
342 Ok(())
343 }
344 }
345
346 fn visit_children(&mut self, visitor: &mut V) -> Result<(), V::Error> {
347 if let Some(v) = self {
348 v.visit_children(visitor)
349 } else {
350 Ok(())
351 }
352 }
353}
354
355impl<'i, T: Visit<'i, T, V>, V: ?Sized + Visitor<'i, T>, U: Visit<'i, T, V>> Visit<'i, T, V> for Box<U> {
356 const CHILD_TYPES: VisitTypes = U::CHILD_TYPES;
357
358 fn visit(&mut self, visitor: &mut V) -> Result<(), V::Error> {
359 self.as_mut().visit(visitor)
360 }
361
362 fn visit_children(&mut self, visitor: &mut V) -> Result<(), V::Error> {
363 self.as_mut().visit_children(visitor)
364 }
365}
366
367impl<'i, T: Visit<'i, T, V>, V: ?Sized + Visitor<'i, T>, U: Visit<'i, T, V>> Visit<'i, T, V> for Vec<U> {
368 const CHILD_TYPES: VisitTypes = U::CHILD_TYPES;
369
370 fn visit(&mut self, visitor: &mut V) -> Result<(), V::Error> {
371 self.iter_mut().try_for_each(|v| v.visit(visitor))
372 }
373
374 fn visit_children(&mut self, visitor: &mut V) -> Result<(), V::Error> {
375 self.iter_mut().try_for_each(|v| v.visit_children(visitor))
376 }
377}
378
379impl<'i, A: smallvec::Array<Item = U>, U: Visit<'i, T, V>, T: Visit<'i, T, V>, V: ?Sized + Visitor<'i, T>>
380 Visit<'i, T, V> for SmallVec<A>
381{
382 const CHILD_TYPES: VisitTypes = U::CHILD_TYPES;
383
384 fn visit(&mut self, visitor: &mut V) -> Result<(), V::Error> {
385 self.iter_mut().try_for_each(|v| v.visit(visitor))
386 }
387
388 fn visit_children(&mut self, visitor: &mut V) -> Result<(), V::Error> {
389 self.iter_mut().try_for_each(|v| v.visit_children(visitor))
390 }
391}
392
393impl<'i, T, V, U, W> Visit<'i, T, V> for IndexMap<U, W>
394where
395 T: Visit<'i, T, V>,
396 V: ?Sized + Visitor<'i, T>,
397 W: Visit<'i, T, V>,
398{
399 const CHILD_TYPES: VisitTypes = W::CHILD_TYPES;
400
401 fn visit(&mut self, visitor: &mut V) -> Result<(), V::Error> {
402 self.iter_mut().try_for_each(|(_k, v)| v.visit(visitor))
403 }
404
405 fn visit_children(&mut self, visitor: &mut V) -> Result<(), V::Error> {
406 self.iter_mut().try_for_each(|(_k, v)| v.visit_children(visitor))
407 }
408}
409
410macro_rules! impl_visit {
411 ($t: ty) => {
412 impl<'i, V: ?Sized + Visitor<'i, T>, T: Visit<'i, T, V>> Visit<'i, T, V> for $t {
413 const CHILD_TYPES: VisitTypes = VisitTypes::empty();
414
415 fn visit_children(&mut self, _: &mut V) -> Result<(), V::Error> {
416 Ok(())
417 }
418 }
419 };
420}
421
422impl_visit!(u8);
423impl_visit!(u16);
424impl_visit!(u32);
425impl_visit!(i32);
426impl_visit!(f32);
427impl_visit!(bool);
428impl_visit!(char);
429impl_visit!(str);
430impl_visit!(String);
431impl_visit!((f32, f32));