1use crate::{
2 Alias, Arguments, BoolOp, BytesLiteral, CmpOp, Comprehension, Decorator, ElifElseClause,
3 ExceptHandler, Expr, FString, InterpolatedStringElement, Keyword, MatchCase, Mod, Operator,
4 Parameter, ParameterWithDefault, Parameters, Pattern, PatternArguments, PatternKeyword,
5 Singleton, Stmt, StringLiteral, TString, TypeParam, TypeParams, UnaryOp, WithItem,
6};
7use crate::{AnyNodeRef, Identifier};
8
9pub trait SourceOrderVisitor<'a> {
14 #[inline]
15 fn enter_node(&mut self, _node: AnyNodeRef<'a>) -> TraversalSignal {
16 TraversalSignal::Traverse
17 }
18
19 #[inline(always)]
20 fn leave_node(&mut self, _node: AnyNodeRef<'a>) {}
21
22 #[inline]
23 fn visit_mod(&mut self, module: &'a Mod) {
24 walk_module(self, module);
25 }
26
27 #[inline]
28 fn visit_stmt(&mut self, stmt: &'a Stmt) {
29 walk_stmt(self, stmt);
30 }
31
32 #[inline]
33 fn visit_annotation(&mut self, expr: &'a Expr) {
34 walk_annotation(self, expr);
35 }
36
37 #[inline]
38 fn visit_expr(&mut self, expr: &'a Expr) {
39 walk_expr(self, expr);
40 }
41
42 #[inline]
43 fn visit_decorator(&mut self, decorator: &'a Decorator) {
44 walk_decorator(self, decorator);
45 }
46
47 #[inline]
48 fn visit_singleton(&mut self, _singleton: &'a Singleton) {}
49
50 #[inline]
51 fn visit_bool_op(&mut self, bool_op: &'a BoolOp) {
52 walk_bool_op(self, bool_op);
53 }
54
55 #[inline]
56 fn visit_operator(&mut self, operator: &'a Operator) {
57 walk_operator(self, operator);
58 }
59
60 #[inline]
61 fn visit_unary_op(&mut self, unary_op: &'a UnaryOp) {
62 walk_unary_op(self, unary_op);
63 }
64
65 #[inline]
66 fn visit_cmp_op(&mut self, cmp_op: &'a CmpOp) {
67 walk_cmp_op(self, cmp_op);
68 }
69
70 #[inline]
71 fn visit_comprehension(&mut self, comprehension: &'a Comprehension) {
72 walk_comprehension(self, comprehension);
73 }
74
75 #[inline]
76 fn visit_except_handler(&mut self, except_handler: &'a ExceptHandler) {
77 walk_except_handler(self, except_handler);
78 }
79
80 #[inline]
81 fn visit_arguments(&mut self, arguments: &'a Arguments) {
82 walk_arguments(self, arguments);
83 }
84
85 #[inline]
86 fn visit_parameters(&mut self, parameters: &'a Parameters) {
87 walk_parameters(self, parameters);
88 }
89
90 #[inline]
91 fn visit_parameter(&mut self, arg: &'a Parameter) {
92 walk_parameter(self, arg);
93 }
94
95 fn visit_parameter_with_default(&mut self, parameter_with_default: &'a ParameterWithDefault) {
96 walk_parameter_with_default(self, parameter_with_default);
97 }
98
99 #[inline]
100 fn visit_keyword(&mut self, keyword: &'a Keyword) {
101 walk_keyword(self, keyword);
102 }
103
104 #[inline]
105 fn visit_alias(&mut self, alias: &'a Alias) {
106 walk_alias(self, alias);
107 }
108
109 #[inline]
110 fn visit_with_item(&mut self, with_item: &'a WithItem) {
111 walk_with_item(self, with_item);
112 }
113
114 #[inline]
115 fn visit_type_params(&mut self, type_params: &'a TypeParams) {
116 walk_type_params(self, type_params);
117 }
118
119 #[inline]
120 fn visit_type_param(&mut self, type_param: &'a TypeParam) {
121 walk_type_param(self, type_param);
122 }
123
124 #[inline]
125 fn visit_match_case(&mut self, match_case: &'a MatchCase) {
126 walk_match_case(self, match_case);
127 }
128
129 #[inline]
130 fn visit_pattern(&mut self, pattern: &'a Pattern) {
131 walk_pattern(self, pattern);
132 }
133
134 #[inline]
135 fn visit_pattern_arguments(&mut self, pattern_arguments: &'a PatternArguments) {
136 walk_pattern_arguments(self, pattern_arguments);
137 }
138
139 #[inline]
140 fn visit_pattern_keyword(&mut self, pattern_keyword: &'a PatternKeyword) {
141 walk_pattern_keyword(self, pattern_keyword);
142 }
143
144 #[inline]
145 fn visit_body(&mut self, body: &'a [Stmt]) {
146 walk_body(self, body);
147 }
148
149 #[inline]
150 fn visit_elif_else_clause(&mut self, elif_else_clause: &'a ElifElseClause) {
151 walk_elif_else_clause(self, elif_else_clause);
152 }
153
154 #[inline]
155 fn visit_f_string(&mut self, f_string: &'a FString) {
156 walk_f_string(self, f_string);
157 }
158
159 #[inline]
160 fn visit_interpolated_string_element(
161 &mut self,
162 interpolated_string_element: &'a InterpolatedStringElement,
163 ) {
164 walk_interpolated_string_element(self, interpolated_string_element);
165 }
166
167 #[inline]
168 fn visit_t_string(&mut self, t_string: &'a TString) {
169 walk_t_string(self, t_string);
170 }
171
172 #[inline]
173 fn visit_string_literal(&mut self, string_literal: &'a StringLiteral) {
174 walk_string_literal(self, string_literal);
175 }
176
177 #[inline]
178 fn visit_bytes_literal(&mut self, bytes_literal: &'a BytesLiteral) {
179 walk_bytes_literal(self, bytes_literal);
180 }
181
182 #[inline]
183 fn visit_identifier(&mut self, identifier: &'a Identifier) {
184 walk_identifier(self, identifier);
185 }
186}
187
188pub fn walk_module<'a, V>(visitor: &mut V, module: &'a Mod)
189where
190 V: SourceOrderVisitor<'a> + ?Sized,
191{
192 let node = AnyNodeRef::from(module);
193 if visitor.enter_node(node).is_traverse() {
194 match module {
195 Mod::Module(module) => module.visit_source_order(visitor),
196 Mod::Expression(module) => module.visit_source_order(visitor),
197 }
198 }
199
200 visitor.leave_node(node);
201}
202
203pub fn walk_body<'a, V>(visitor: &mut V, body: &'a [Stmt])
204where
205 V: SourceOrderVisitor<'a> + ?Sized,
206{
207 for stmt in body {
208 visitor.visit_stmt(stmt);
209 }
210}
211
212pub fn walk_stmt<'a, V>(visitor: &mut V, stmt: &'a Stmt)
213where
214 V: SourceOrderVisitor<'a> + ?Sized,
215{
216 let node = AnyNodeRef::from(stmt);
217
218 if visitor.enter_node(node).is_traverse() {
219 stmt.visit_source_order(visitor);
220 }
221
222 visitor.leave_node(node);
223}
224
225pub fn walk_node<'a, V>(visitor: &mut V, node: AnyNodeRef<'a>)
226where
227 V: SourceOrderVisitor<'a> + ?Sized,
228{
229 if visitor.enter_node(node).is_traverse() {
230 node.visit_source_order(visitor);
231 }
232
233 visitor.leave_node(node);
234}
235
236#[derive(Copy, Clone, Eq, PartialEq, Debug)]
237pub enum TraversalSignal {
238 Traverse,
239 Skip,
240}
241
242impl TraversalSignal {
243 pub const fn is_traverse(self) -> bool {
244 matches!(self, TraversalSignal::Traverse)
245 }
246}
247
248pub fn walk_annotation<'a, V: SourceOrderVisitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
249 visitor.visit_expr(expr);
250}
251
252pub fn walk_decorator<'a, V>(visitor: &mut V, decorator: &'a Decorator)
253where
254 V: SourceOrderVisitor<'a> + ?Sized,
255{
256 let node = AnyNodeRef::from(decorator);
257 if visitor.enter_node(node).is_traverse() {
258 decorator.visit_source_order(visitor);
259 }
260
261 visitor.leave_node(node);
262}
263
264pub fn walk_expr<'a, V>(visitor: &mut V, expr: &'a Expr)
265where
266 V: SourceOrderVisitor<'a> + ?Sized,
267{
268 let node = AnyNodeRef::from(expr);
269 if visitor.enter_node(node).is_traverse() {
270 match expr {
271 Expr::BoolOp(expr) => expr.visit_source_order(visitor),
272 Expr::Named(expr) => expr.visit_source_order(visitor),
273 Expr::BinOp(expr) => expr.visit_source_order(visitor),
274 Expr::UnaryOp(expr) => expr.visit_source_order(visitor),
275 Expr::Lambda(expr) => expr.visit_source_order(visitor),
276 Expr::If(expr) => expr.visit_source_order(visitor),
277 Expr::Dict(expr) => expr.visit_source_order(visitor),
278 Expr::Set(expr) => expr.visit_source_order(visitor),
279 Expr::ListComp(expr) => expr.visit_source_order(visitor),
280 Expr::SetComp(expr) => expr.visit_source_order(visitor),
281 Expr::DictComp(expr) => expr.visit_source_order(visitor),
282 Expr::Generator(expr) => expr.visit_source_order(visitor),
283 Expr::Await(expr) => expr.visit_source_order(visitor),
284 Expr::Yield(expr) => expr.visit_source_order(visitor),
285 Expr::YieldFrom(expr) => expr.visit_source_order(visitor),
286 Expr::Compare(expr) => expr.visit_source_order(visitor),
287 Expr::Call(expr) => expr.visit_source_order(visitor),
288 Expr::FString(expr) => expr.visit_source_order(visitor),
289 Expr::TString(expr) => expr.visit_source_order(visitor),
290 Expr::StringLiteral(expr) => expr.visit_source_order(visitor),
291 Expr::BytesLiteral(expr) => expr.visit_source_order(visitor),
292 Expr::NumberLiteral(expr) => expr.visit_source_order(visitor),
293 Expr::BooleanLiteral(expr) => expr.visit_source_order(visitor),
294 Expr::NoneLiteral(expr) => expr.visit_source_order(visitor),
295 Expr::EllipsisLiteral(expr) => expr.visit_source_order(visitor),
296 Expr::Attribute(expr) => expr.visit_source_order(visitor),
297 Expr::Subscript(expr) => expr.visit_source_order(visitor),
298 Expr::Starred(expr) => expr.visit_source_order(visitor),
299 Expr::Name(expr) => expr.visit_source_order(visitor),
300 Expr::List(expr) => expr.visit_source_order(visitor),
301 Expr::Tuple(expr) => expr.visit_source_order(visitor),
302 Expr::Slice(expr) => expr.visit_source_order(visitor),
303 Expr::IpyEscapeCommand(expr) => expr.visit_source_order(visitor),
304 }
305 }
306
307 visitor.leave_node(node);
308}
309
310pub fn walk_comprehension<'a, V>(visitor: &mut V, comprehension: &'a Comprehension)
311where
312 V: SourceOrderVisitor<'a> + ?Sized,
313{
314 let node = AnyNodeRef::from(comprehension);
315 if visitor.enter_node(node).is_traverse() {
316 comprehension.visit_source_order(visitor);
317 }
318
319 visitor.leave_node(node);
320}
321
322pub fn walk_elif_else_clause<'a, V>(visitor: &mut V, elif_else_clause: &'a ElifElseClause)
323where
324 V: SourceOrderVisitor<'a> + ?Sized,
325{
326 let node = AnyNodeRef::from(elif_else_clause);
327 if visitor.enter_node(node).is_traverse() {
328 elif_else_clause.visit_source_order(visitor);
329 }
330
331 visitor.leave_node(node);
332}
333
334pub fn walk_except_handler<'a, V>(visitor: &mut V, except_handler: &'a ExceptHandler)
335where
336 V: SourceOrderVisitor<'a> + ?Sized,
337{
338 let node = AnyNodeRef::from(except_handler);
339 if visitor.enter_node(node).is_traverse() {
340 match except_handler {
341 ExceptHandler::ExceptHandler(except_handler) => {
342 except_handler.visit_source_order(visitor);
343 }
344 }
345 }
346 visitor.leave_node(node);
347}
348
349pub fn walk_format_spec<'a, V: SourceOrderVisitor<'a> + ?Sized>(
350 visitor: &mut V,
351 format_spec: &'a Expr,
352) {
353 let node = AnyNodeRef::from(format_spec);
354 if visitor.enter_node(node).is_traverse() {
355 visitor.visit_expr(format_spec);
356 }
357
358 visitor.leave_node(node);
359}
360
361pub fn walk_arguments<'a, V>(visitor: &mut V, arguments: &'a Arguments)
362where
363 V: SourceOrderVisitor<'a> + ?Sized,
364{
365 let node = AnyNodeRef::from(arguments);
366 if visitor.enter_node(node).is_traverse() {
367 arguments.visit_source_order(visitor);
368 }
369
370 visitor.leave_node(node);
371}
372
373pub fn walk_parameters<'a, V>(visitor: &mut V, parameters: &'a Parameters)
374where
375 V: SourceOrderVisitor<'a> + ?Sized,
376{
377 let node = AnyNodeRef::from(parameters);
378 if visitor.enter_node(node).is_traverse() {
379 parameters.visit_source_order(visitor);
380 }
381
382 visitor.leave_node(node);
383}
384
385pub fn walk_parameter<'a, V>(visitor: &mut V, parameter: &'a Parameter)
386where
387 V: SourceOrderVisitor<'a> + ?Sized,
388{
389 let node = AnyNodeRef::from(parameter);
390
391 if visitor.enter_node(node).is_traverse() {
392 parameter.visit_source_order(visitor);
393 }
394 visitor.leave_node(node);
395}
396
397pub fn walk_parameter_with_default<'a, V>(
398 visitor: &mut V,
399 parameter_with_default: &'a ParameterWithDefault,
400) where
401 V: SourceOrderVisitor<'a> + ?Sized,
402{
403 let node = AnyNodeRef::from(parameter_with_default);
404 if visitor.enter_node(node).is_traverse() {
405 parameter_with_default.visit_source_order(visitor);
406 }
407
408 visitor.leave_node(node);
409}
410
411#[inline]
412pub fn walk_keyword<'a, V>(visitor: &mut V, keyword: &'a Keyword)
413where
414 V: SourceOrderVisitor<'a> + ?Sized,
415{
416 let node = AnyNodeRef::from(keyword);
417
418 if visitor.enter_node(node).is_traverse() {
419 keyword.visit_source_order(visitor);
420 }
421 visitor.leave_node(node);
422}
423
424pub fn walk_with_item<'a, V>(visitor: &mut V, with_item: &'a WithItem)
425where
426 V: SourceOrderVisitor<'a> + ?Sized,
427{
428 let node = AnyNodeRef::from(with_item);
429 if visitor.enter_node(node).is_traverse() {
430 with_item.visit_source_order(visitor);
431 }
432 visitor.leave_node(node);
433}
434
435pub fn walk_type_params<'a, V>(visitor: &mut V, type_params: &'a TypeParams)
436where
437 V: SourceOrderVisitor<'a> + ?Sized,
438{
439 let node = AnyNodeRef::from(type_params);
440 if visitor.enter_node(node).is_traverse() {
441 type_params.visit_source_order(visitor);
442 }
443 visitor.leave_node(node);
444}
445
446pub fn walk_type_param<'a, V>(visitor: &mut V, type_param: &'a TypeParam)
447where
448 V: SourceOrderVisitor<'a> + ?Sized,
449{
450 let node = AnyNodeRef::from(type_param);
451 if visitor.enter_node(node).is_traverse() {
452 type_param.visit_source_order(visitor);
453 }
454 visitor.leave_node(node);
455}
456
457pub fn walk_match_case<'a, V>(visitor: &mut V, match_case: &'a MatchCase)
458where
459 V: SourceOrderVisitor<'a> + ?Sized,
460{
461 let node = AnyNodeRef::from(match_case);
462 if visitor.enter_node(node).is_traverse() {
463 match_case.visit_source_order(visitor);
464 }
465 visitor.leave_node(node);
466}
467
468pub fn walk_pattern<'a, V>(visitor: &mut V, pattern: &'a Pattern)
469where
470 V: SourceOrderVisitor<'a> + ?Sized,
471{
472 let node = AnyNodeRef::from(pattern);
473 if visitor.enter_node(node).is_traverse() {
474 match pattern {
475 Pattern::MatchValue(pattern) => pattern.visit_source_order(visitor),
476 Pattern::MatchSingleton(pattern) => pattern.visit_source_order(visitor),
477 Pattern::MatchSequence(pattern) => pattern.visit_source_order(visitor),
478 Pattern::MatchMapping(pattern) => pattern.visit_source_order(visitor),
479 Pattern::MatchClass(pattern) => pattern.visit_source_order(visitor),
480 Pattern::MatchStar(pattern) => pattern.visit_source_order(visitor),
481 Pattern::MatchAs(pattern) => pattern.visit_source_order(visitor),
482 Pattern::MatchOr(pattern) => pattern.visit_source_order(visitor),
483 }
484 }
485 visitor.leave_node(node);
486}
487
488pub fn walk_pattern_arguments<'a, V>(visitor: &mut V, pattern_arguments: &'a PatternArguments)
489where
490 V: SourceOrderVisitor<'a> + ?Sized,
491{
492 let node = AnyNodeRef::from(pattern_arguments);
493 if visitor.enter_node(node).is_traverse() {
494 for pattern in &pattern_arguments.patterns {
495 visitor.visit_pattern(pattern);
496 }
497 for keyword in &pattern_arguments.keywords {
498 visitor.visit_pattern_keyword(keyword);
499 }
500 }
501 visitor.leave_node(node);
502}
503
504pub fn walk_pattern_keyword<'a, V>(visitor: &mut V, pattern_keyword: &'a PatternKeyword)
505where
506 V: SourceOrderVisitor<'a> + ?Sized,
507{
508 let node = AnyNodeRef::from(pattern_keyword);
509 if visitor.enter_node(node).is_traverse() {
510 pattern_keyword.visit_source_order(visitor);
511 }
512 visitor.leave_node(node);
513}
514
515pub fn walk_interpolated_string_element<'a, V: SourceOrderVisitor<'a> + ?Sized>(
516 visitor: &mut V,
517 f_string_element: &'a InterpolatedStringElement,
518) {
519 let node = AnyNodeRef::from(f_string_element);
520 if visitor.enter_node(node).is_traverse() {
521 match f_string_element {
522 InterpolatedStringElement::Interpolation(element) => {
523 element.visit_source_order(visitor);
524 }
525 InterpolatedStringElement::Literal(element) => element.visit_source_order(visitor),
526 }
527 }
528 visitor.leave_node(node);
529}
530
531pub fn walk_bool_op<'a, V>(_visitor: &mut V, _bool_op: &'a BoolOp)
532where
533 V: SourceOrderVisitor<'a> + ?Sized,
534{
535}
536
537#[inline]
538pub fn walk_operator<'a, V>(_visitor: &mut V, _operator: &'a Operator)
539where
540 V: SourceOrderVisitor<'a> + ?Sized,
541{
542}
543
544#[inline]
545pub fn walk_unary_op<'a, V>(_visitor: &mut V, _unary_op: &'a UnaryOp)
546where
547 V: SourceOrderVisitor<'a> + ?Sized,
548{
549}
550
551#[inline]
552pub fn walk_cmp_op<'a, V>(_visitor: &mut V, _cmp_op: &'a CmpOp)
553where
554 V: SourceOrderVisitor<'a> + ?Sized,
555{
556}
557
558#[inline]
559pub fn walk_f_string<'a, V>(visitor: &mut V, f_string: &'a FString)
560where
561 V: SourceOrderVisitor<'a> + ?Sized,
562{
563 let node = AnyNodeRef::from(f_string);
564 if visitor.enter_node(node).is_traverse() {
565 f_string.visit_source_order(visitor);
566 }
567 visitor.leave_node(node);
568}
569
570#[inline]
571pub fn walk_t_string<'a, V>(visitor: &mut V, t_string: &'a TString)
572where
573 V: SourceOrderVisitor<'a> + ?Sized,
574{
575 let node = AnyNodeRef::from(t_string);
576 if visitor.enter_node(node).is_traverse() {
577 t_string.visit_source_order(visitor);
578 }
579 visitor.leave_node(node);
580}
581
582#[inline]
583pub fn walk_string_literal<'a, V>(visitor: &mut V, string_literal: &'a StringLiteral)
584where
585 V: SourceOrderVisitor<'a> + ?Sized,
586{
587 let node = AnyNodeRef::from(string_literal);
588 if visitor.enter_node(node).is_traverse() {
589 string_literal.visit_source_order(visitor);
590 }
591 visitor.leave_node(node);
592}
593
594#[inline]
595pub fn walk_bytes_literal<'a, V>(visitor: &mut V, bytes_literal: &'a BytesLiteral)
596where
597 V: SourceOrderVisitor<'a> + ?Sized,
598{
599 let node = AnyNodeRef::from(bytes_literal);
600 if visitor.enter_node(node).is_traverse() {
601 bytes_literal.visit_source_order(visitor);
602 }
603 visitor.leave_node(node);
604}
605
606#[inline]
607pub fn walk_alias<'a, V>(visitor: &mut V, alias: &'a Alias)
608where
609 V: SourceOrderVisitor<'a> + ?Sized,
610{
611 let node = AnyNodeRef::from(alias);
612 if visitor.enter_node(node).is_traverse() {
613 alias.visit_source_order(visitor);
614 }
615 visitor.leave_node(node);
616}
617
618#[inline]
619pub fn walk_identifier<'a, V: SourceOrderVisitor<'a> + ?Sized>(
620 visitor: &mut V,
621 identifier: &'a Identifier,
622) {
623 let node = AnyNodeRef::from(identifier);
624 if visitor.enter_node(node).is_traverse() {
625 identifier.visit_source_order(visitor);
626 }
627 visitor.leave_node(node);
628}