1#![allow(missing_docs)]
62
63use crate::expr::{
64 Array, BinaryOp, BinaryOperator, Conditional, Expression, ForCond, ForExpr, ForIntro, FuncArgs,
65 FuncCall, FuncName, Null, Object, ObjectKey, ObjectValue, Parenthesis, Splat, Traversal,
66 TraversalOperator, UnaryOp, UnaryOperator,
67};
68use crate::structure::{Attribute, Block, BlockLabel, Body, Structure};
69use crate::template::{
70 Directive, Element, ElseTemplateExpr, EndforTemplateExpr, EndifTemplateExpr, ForDirective,
71 ForTemplateExpr, HeredocTemplate, IfDirective, IfTemplateExpr, Interpolation, StringTemplate,
72 Template,
73};
74use crate::{Decorated, Formatted, Ident, Number, Spanned};
75
76macro_rules! empty_visit_methods {
77 ($($name: ident => $t: ty),+ $(,)?) => {
78 $(
79 fn $name(&mut self, node: &$t) {
80 let _ = node;
81 }
82 )*
83 };
84}
85
86macro_rules! visit_methods {
87 ($($name: ident => $t: ty),+ $(,)?) => {
88 $(
89 fn $name(&mut self, node: &$t) {
90 $name(self, node);
91 }
92 )*
93 };
94}
95
96pub trait Visit {
100 empty_visit_methods! {
101 visit_ident => Decorated<Ident>,
102 visit_null => Decorated<Null>,
103 visit_bool => Decorated<bool>,
104 visit_u64 => Decorated<u64>,
105 visit_number => Formatted<Number>,
106 visit_string => Decorated<String>,
107 visit_splat => Decorated<Splat>,
108 visit_literal => Spanned<String>,
109 visit_unary_operator => Spanned<UnaryOperator>,
110 visit_binary_operator => Spanned<BinaryOperator>,
111 visit_endif_template_expr => EndifTemplateExpr,
112 visit_endfor_template_expr => EndforTemplateExpr,
113 }
114
115 visit_methods! {
116 visit_body => Body,
117 visit_structure => Structure,
118 visit_attr => Attribute,
119 visit_block => Block,
120 visit_block_label => BlockLabel,
121 visit_expr => Expression,
122 visit_array => Array,
123 visit_object => Object,
124 visit_object_key => ObjectKey,
125 visit_object_value => ObjectValue,
126 visit_parenthesis => Parenthesis,
127 visit_conditional => Conditional,
128 visit_unary_op => UnaryOp,
129 visit_binary_op => BinaryOp,
130 visit_traversal => Traversal,
131 visit_traversal_operator => TraversalOperator,
132 visit_func_call => FuncCall,
133 visit_func_name => FuncName,
134 visit_func_args => FuncArgs,
135 visit_for_expr => ForExpr,
136 visit_for_intro => ForIntro,
137 visit_for_cond => ForCond,
138 visit_string_template => StringTemplate,
139 visit_heredoc_template => HeredocTemplate,
140 visit_template => Template,
141 visit_element => Element,
142 visit_interpolation => Interpolation,
143 visit_directive => Directive,
144 visit_if_directive => IfDirective,
145 visit_for_directive => ForDirective,
146 visit_if_template_expr => IfTemplateExpr,
147 visit_else_template_expr => ElseTemplateExpr,
148 visit_for_template_expr => ForTemplateExpr,
149 }
150
151 fn visit_object_item(&mut self, key: &ObjectKey, value: &ObjectValue) {
152 visit_object_item(self, key, value);
153 }
154}
155
156pub fn visit_body<V>(v: &mut V, node: &Body)
157where
158 V: Visit + ?Sized,
159{
160 for structure in node {
161 v.visit_structure(structure);
162 }
163}
164
165pub fn visit_structure<V>(v: &mut V, node: &Structure)
166where
167 V: Visit + ?Sized,
168{
169 match node {
170 Structure::Attribute(attr) => v.visit_attr(attr),
171 Structure::Block(block) => v.visit_block(block),
172 }
173}
174
175pub fn visit_attr<V>(v: &mut V, node: &Attribute)
176where
177 V: Visit + ?Sized,
178{
179 v.visit_ident(&node.key);
180 v.visit_expr(&node.value);
181}
182
183pub fn visit_block<V>(v: &mut V, node: &Block)
184where
185 V: Visit + ?Sized,
186{
187 v.visit_ident(&node.ident);
188 for label in &node.labels {
189 v.visit_block_label(label);
190 }
191 v.visit_body(&node.body);
192}
193
194pub fn visit_block_label<V>(v: &mut V, node: &BlockLabel)
195where
196 V: Visit + ?Sized,
197{
198 match node {
199 BlockLabel::String(string) => v.visit_string(string),
200 BlockLabel::Ident(ident) => v.visit_ident(ident),
201 }
202}
203
204pub fn visit_expr<V>(v: &mut V, node: &Expression)
205where
206 V: Visit + ?Sized,
207{
208 match node {
209 Expression::Null(null) => v.visit_null(null),
210 Expression::Bool(b) => v.visit_bool(b),
211 Expression::Number(number) => v.visit_number(number),
212 Expression::String(string) => v.visit_string(string),
213 Expression::Array(array) => v.visit_array(array),
214 Expression::Object(object) => v.visit_object(object),
215 Expression::StringTemplate(template) => v.visit_string_template(template),
216 Expression::HeredocTemplate(template) => v.visit_heredoc_template(template),
217 Expression::Parenthesis(parens) => v.visit_parenthesis(parens),
218 Expression::Variable(var) => v.visit_ident(var),
219 Expression::ForExpr(for_expr) => v.visit_for_expr(for_expr),
220 Expression::Conditional(conditional) => v.visit_conditional(conditional),
221 Expression::FuncCall(func_call) => v.visit_func_call(func_call),
222 Expression::UnaryOp(unary_op) => v.visit_unary_op(unary_op),
223 Expression::BinaryOp(binary_op) => v.visit_binary_op(binary_op),
224 Expression::Traversal(traversal) => v.visit_traversal(traversal),
225 }
226}
227
228pub fn visit_array<V>(v: &mut V, node: &Array)
229where
230 V: Visit + ?Sized,
231{
232 for expr in node {
233 v.visit_expr(expr);
234 }
235}
236
237pub fn visit_object<V>(v: &mut V, node: &Object)
238where
239 V: Visit + ?Sized,
240{
241 for (key, value) in node {
242 v.visit_object_item(key, value);
243 }
244}
245
246pub fn visit_object_item<V>(v: &mut V, key: &ObjectKey, value: &ObjectValue)
247where
248 V: Visit + ?Sized,
249{
250 v.visit_object_key(key);
251 v.visit_object_value(value);
252}
253
254pub fn visit_object_key<V>(v: &mut V, node: &ObjectKey)
255where
256 V: Visit + ?Sized,
257{
258 match node {
259 ObjectKey::Ident(ident) => v.visit_ident(ident),
260 ObjectKey::Expression(expr) => v.visit_expr(expr),
261 }
262}
263
264pub fn visit_object_value<V>(v: &mut V, node: &ObjectValue)
265where
266 V: Visit + ?Sized,
267{
268 v.visit_expr(node.expr());
269}
270
271pub fn visit_parenthesis<V>(v: &mut V, node: &Parenthesis)
272where
273 V: Visit + ?Sized,
274{
275 v.visit_expr(node.inner());
276}
277
278pub fn visit_conditional<V>(v: &mut V, node: &Conditional)
279where
280 V: Visit + ?Sized,
281{
282 v.visit_expr(&node.cond_expr);
283 v.visit_expr(&node.true_expr);
284 v.visit_expr(&node.false_expr);
285}
286
287pub fn visit_unary_op<V>(v: &mut V, node: &UnaryOp)
288where
289 V: Visit + ?Sized,
290{
291 v.visit_unary_operator(&node.operator);
292 v.visit_expr(&node.expr);
293}
294
295pub fn visit_binary_op<V>(v: &mut V, node: &BinaryOp)
296where
297 V: Visit + ?Sized,
298{
299 v.visit_expr(&node.lhs_expr);
300 v.visit_binary_operator(&node.operator);
301 v.visit_expr(&node.rhs_expr);
302}
303
304pub fn visit_traversal<V>(v: &mut V, node: &Traversal)
305where
306 V: Visit + ?Sized,
307{
308 v.visit_expr(&node.expr);
309 for operator in &node.operators {
310 v.visit_traversal_operator(operator);
311 }
312}
313
314pub fn visit_traversal_operator<V>(v: &mut V, node: &TraversalOperator)
315where
316 V: Visit + ?Sized,
317{
318 match node {
319 TraversalOperator::AttrSplat(splat) | TraversalOperator::FullSplat(splat) => {
320 v.visit_splat(splat);
321 }
322 TraversalOperator::GetAttr(ident) => v.visit_ident(ident),
323 TraversalOperator::Index(expr) => v.visit_expr(expr),
324 TraversalOperator::LegacyIndex(u) => v.visit_u64(u),
325 }
326}
327
328pub fn visit_func_call<V>(v: &mut V, node: &FuncCall)
329where
330 V: Visit + ?Sized,
331{
332 v.visit_func_name(&node.name);
333 v.visit_func_args(&node.args);
334}
335
336pub fn visit_func_name<V>(v: &mut V, node: &FuncName)
337where
338 V: Visit + ?Sized,
339{
340 for component in &node.namespace {
341 v.visit_ident(component);
342 }
343 v.visit_ident(&node.name);
344}
345
346pub fn visit_func_args<V>(v: &mut V, node: &FuncArgs)
347where
348 V: Visit + ?Sized,
349{
350 for arg in node {
351 v.visit_expr(arg);
352 }
353}
354
355pub fn visit_for_expr<V>(v: &mut V, node: &ForExpr)
356where
357 V: Visit + ?Sized,
358{
359 v.visit_for_intro(&node.intro);
360 if let Some(key_expr) = &node.key_expr {
361 v.visit_expr(key_expr);
362 }
363 v.visit_expr(&node.value_expr);
364 if let Some(cond) = &node.cond {
365 v.visit_for_cond(cond);
366 }
367}
368
369pub fn visit_for_intro<V>(v: &mut V, node: &ForIntro)
370where
371 V: Visit + ?Sized,
372{
373 if let Some(key_var) = &node.key_var {
374 v.visit_ident(key_var);
375 }
376 v.visit_ident(&node.value_var);
377 v.visit_expr(&node.collection_expr);
378}
379
380pub fn visit_for_cond<V>(v: &mut V, node: &ForCond)
381where
382 V: Visit + ?Sized,
383{
384 v.visit_expr(&node.expr);
385}
386
387pub fn visit_string_template<V>(v: &mut V, node: &StringTemplate)
388where
389 V: Visit + ?Sized,
390{
391 for element in node {
392 v.visit_element(element);
393 }
394}
395
396pub fn visit_heredoc_template<V>(v: &mut V, node: &HeredocTemplate)
397where
398 V: Visit + ?Sized,
399{
400 v.visit_template(&node.template);
401}
402
403pub fn visit_template<V>(v: &mut V, node: &Template)
404where
405 V: Visit + ?Sized,
406{
407 for element in node {
408 v.visit_element(element);
409 }
410}
411
412pub fn visit_element<V>(v: &mut V, node: &Element)
413where
414 V: Visit + ?Sized,
415{
416 match node {
417 Element::Literal(literal) => v.visit_literal(literal),
418 Element::Interpolation(interpolation) => v.visit_interpolation(interpolation),
419 Element::Directive(directive) => v.visit_directive(directive),
420 }
421}
422
423pub fn visit_interpolation<V>(v: &mut V, node: &Interpolation)
424where
425 V: Visit + ?Sized,
426{
427 v.visit_expr(&node.expr);
428}
429
430pub fn visit_directive<V>(v: &mut V, node: &Directive)
431where
432 V: Visit + ?Sized,
433{
434 match node {
435 Directive::If(if_directive) => v.visit_if_directive(if_directive),
436 Directive::For(for_directive) => v.visit_for_directive(for_directive),
437 }
438}
439
440pub fn visit_if_directive<V>(v: &mut V, node: &IfDirective)
441where
442 V: Visit + ?Sized,
443{
444 v.visit_if_template_expr(&node.if_expr);
445 if let Some(else_template_expr) = &node.else_expr {
446 v.visit_else_template_expr(else_template_expr);
447 }
448 v.visit_endif_template_expr(&node.endif_expr);
449}
450
451pub fn visit_for_directive<V>(v: &mut V, node: &ForDirective)
452where
453 V: Visit + ?Sized,
454{
455 v.visit_for_template_expr(&node.for_expr);
456 v.visit_endfor_template_expr(&node.endfor_expr);
457}
458
459pub fn visit_if_template_expr<V>(v: &mut V, node: &IfTemplateExpr)
460where
461 V: Visit + ?Sized,
462{
463 v.visit_expr(&node.cond_expr);
464 v.visit_template(&node.template);
465}
466
467pub fn visit_else_template_expr<V>(v: &mut V, node: &ElseTemplateExpr)
468where
469 V: Visit + ?Sized,
470{
471 v.visit_template(&node.template);
472}
473
474pub fn visit_for_template_expr<V>(v: &mut V, node: &ForTemplateExpr)
475where
476 V: Visit + ?Sized,
477{
478 if let Some(key_var) = &node.key_var {
479 v.visit_ident(key_var);
480 }
481 v.visit_ident(&node.value_var);
482 v.visit_template(&node.template);
483}