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::Constant(expr) => expr.visit_source_order(visitor),
294 Expr::BooleanLiteral(expr) => expr.visit_source_order(visitor),
295 Expr::NoneLiteral(expr) => expr.visit_source_order(visitor),
296 Expr::EllipsisLiteral(expr) => expr.visit_source_order(visitor),
297 Expr::Attribute(expr) => expr.visit_source_order(visitor),
298 Expr::Subscript(expr) => expr.visit_source_order(visitor),
299 Expr::Starred(expr) => expr.visit_source_order(visitor),
300 Expr::Name(expr) => expr.visit_source_order(visitor),
301 Expr::List(expr) => expr.visit_source_order(visitor),
302 Expr::Tuple(expr) => expr.visit_source_order(visitor),
303 Expr::Slice(expr) => expr.visit_source_order(visitor),
304 Expr::IpyEscapeCommand(expr) => expr.visit_source_order(visitor),
305 }
306 }
307
308 visitor.leave_node(node);
309}
310
311pub fn walk_comprehension<'a, V>(visitor: &mut V, comprehension: &'a Comprehension)
312where
313 V: SourceOrderVisitor<'a> + ?Sized,
314{
315 let node = AnyNodeRef::from(comprehension);
316 if visitor.enter_node(node).is_traverse() {
317 comprehension.visit_source_order(visitor);
318 }
319
320 visitor.leave_node(node);
321}
322
323pub fn walk_elif_else_clause<'a, V>(visitor: &mut V, elif_else_clause: &'a ElifElseClause)
324where
325 V: SourceOrderVisitor<'a> + ?Sized,
326{
327 let node = AnyNodeRef::from(elif_else_clause);
328 if visitor.enter_node(node).is_traverse() {
329 elif_else_clause.visit_source_order(visitor);
330 }
331
332 visitor.leave_node(node);
333}
334
335pub fn walk_except_handler<'a, V>(visitor: &mut V, except_handler: &'a ExceptHandler)
336where
337 V: SourceOrderVisitor<'a> + ?Sized,
338{
339 let node = AnyNodeRef::from(except_handler);
340 if visitor.enter_node(node).is_traverse() {
341 match except_handler {
342 ExceptHandler::ExceptHandler(except_handler) => {
343 except_handler.visit_source_order(visitor);
344 }
345 }
346 }
347 visitor.leave_node(node);
348}
349
350pub fn walk_format_spec<'a, V: SourceOrderVisitor<'a> + ?Sized>(
351 visitor: &mut V,
352 format_spec: &'a Expr,
353) {
354 let node = AnyNodeRef::from(format_spec);
355 if visitor.enter_node(node).is_traverse() {
356 visitor.visit_expr(format_spec);
357 }
358
359 visitor.leave_node(node);
360}
361
362pub fn walk_arguments<'a, V>(visitor: &mut V, arguments: &'a Arguments)
363where
364 V: SourceOrderVisitor<'a> + ?Sized,
365{
366 let node = AnyNodeRef::from(arguments);
367 if visitor.enter_node(node).is_traverse() {
368 arguments.visit_source_order(visitor);
369 }
370
371 visitor.leave_node(node);
372}
373
374pub fn walk_parameters<'a, V>(visitor: &mut V, parameters: &'a Parameters)
375where
376 V: SourceOrderVisitor<'a> + ?Sized,
377{
378 let node = AnyNodeRef::from(parameters);
379 if visitor.enter_node(node).is_traverse() {
380 parameters.visit_source_order(visitor);
381 }
382
383 visitor.leave_node(node);
384}
385
386pub fn walk_parameter<'a, V>(visitor: &mut V, parameter: &'a Parameter)
387where
388 V: SourceOrderVisitor<'a> + ?Sized,
389{
390 let node = AnyNodeRef::from(parameter);
391
392 if visitor.enter_node(node).is_traverse() {
393 parameter.visit_source_order(visitor);
394 }
395 visitor.leave_node(node);
396}
397
398pub fn walk_parameter_with_default<'a, V>(
399 visitor: &mut V,
400 parameter_with_default: &'a ParameterWithDefault,
401) where
402 V: SourceOrderVisitor<'a> + ?Sized,
403{
404 let node = AnyNodeRef::from(parameter_with_default);
405 if visitor.enter_node(node).is_traverse() {
406 parameter_with_default.visit_source_order(visitor);
407 }
408
409 visitor.leave_node(node);
410}
411
412#[inline]
413pub fn walk_keyword<'a, V>(visitor: &mut V, keyword: &'a Keyword)
414where
415 V: SourceOrderVisitor<'a> + ?Sized,
416{
417 let node = AnyNodeRef::from(keyword);
418
419 if visitor.enter_node(node).is_traverse() {
420 keyword.visit_source_order(visitor);
421 }
422 visitor.leave_node(node);
423}
424
425pub fn walk_with_item<'a, V>(visitor: &mut V, with_item: &'a WithItem)
426where
427 V: SourceOrderVisitor<'a> + ?Sized,
428{
429 let node = AnyNodeRef::from(with_item);
430 if visitor.enter_node(node).is_traverse() {
431 with_item.visit_source_order(visitor);
432 }
433 visitor.leave_node(node);
434}
435
436pub fn walk_type_params<'a, V>(visitor: &mut V, type_params: &'a TypeParams)
437where
438 V: SourceOrderVisitor<'a> + ?Sized,
439{
440 let node = AnyNodeRef::from(type_params);
441 if visitor.enter_node(node).is_traverse() {
442 type_params.visit_source_order(visitor);
443 }
444 visitor.leave_node(node);
445}
446
447pub fn walk_type_param<'a, V>(visitor: &mut V, type_param: &'a TypeParam)
448where
449 V: SourceOrderVisitor<'a> + ?Sized,
450{
451 let node = AnyNodeRef::from(type_param);
452 if visitor.enter_node(node).is_traverse() {
453 type_param.visit_source_order(visitor);
454 }
455 visitor.leave_node(node);
456}
457
458pub fn walk_match_case<'a, V>(visitor: &mut V, match_case: &'a MatchCase)
459where
460 V: SourceOrderVisitor<'a> + ?Sized,
461{
462 let node = AnyNodeRef::from(match_case);
463 if visitor.enter_node(node).is_traverse() {
464 match_case.visit_source_order(visitor);
465 }
466 visitor.leave_node(node);
467}
468
469pub fn walk_pattern<'a, V>(visitor: &mut V, pattern: &'a Pattern)
470where
471 V: SourceOrderVisitor<'a> + ?Sized,
472{
473 let node = AnyNodeRef::from(pattern);
474 if visitor.enter_node(node).is_traverse() {
475 match pattern {
476 Pattern::MatchValue(pattern) => pattern.visit_source_order(visitor),
477 Pattern::MatchSingleton(pattern) => pattern.visit_source_order(visitor),
478 Pattern::MatchSequence(pattern) => pattern.visit_source_order(visitor),
479 Pattern::MatchMapping(pattern) => pattern.visit_source_order(visitor),
480 Pattern::MatchClass(pattern) => pattern.visit_source_order(visitor),
481 Pattern::MatchStar(pattern) => pattern.visit_source_order(visitor),
482 Pattern::MatchAs(pattern) => pattern.visit_source_order(visitor),
483 Pattern::MatchOr(pattern) => pattern.visit_source_order(visitor),
484 }
485 }
486 visitor.leave_node(node);
487}
488
489pub fn walk_pattern_arguments<'a, V>(visitor: &mut V, pattern_arguments: &'a PatternArguments)
490where
491 V: SourceOrderVisitor<'a> + ?Sized,
492{
493 let node = AnyNodeRef::from(pattern_arguments);
494 if visitor.enter_node(node).is_traverse() {
495 pattern_arguments.visit_source_order(visitor);
496 }
497 visitor.leave_node(node);
498}
499
500pub fn walk_pattern_keyword<'a, V>(visitor: &mut V, pattern_keyword: &'a PatternKeyword)
501where
502 V: SourceOrderVisitor<'a> + ?Sized,
503{
504 let node = AnyNodeRef::from(pattern_keyword);
505 if visitor.enter_node(node).is_traverse() {
506 pattern_keyword.visit_source_order(visitor);
507 }
508 visitor.leave_node(node);
509}
510
511pub fn walk_interpolated_string_element<'a, V: SourceOrderVisitor<'a> + ?Sized>(
512 visitor: &mut V,
513 f_string_element: &'a InterpolatedStringElement,
514) {
515 let node = AnyNodeRef::from(f_string_element);
516 if visitor.enter_node(node).is_traverse() {
517 match f_string_element {
518 InterpolatedStringElement::Interpolation(element) => {
519 element.visit_source_order(visitor);
520 }
521 InterpolatedStringElement::Literal(element) => element.visit_source_order(visitor),
522 }
523 }
524 visitor.leave_node(node);
525}
526
527pub fn walk_bool_op<'a, V>(_visitor: &mut V, _bool_op: &'a BoolOp)
528where
529 V: SourceOrderVisitor<'a> + ?Sized,
530{
531}
532
533#[inline]
534pub fn walk_operator<'a, V>(_visitor: &mut V, _operator: &'a Operator)
535where
536 V: SourceOrderVisitor<'a> + ?Sized,
537{
538}
539
540#[inline]
541pub fn walk_unary_op<'a, V>(_visitor: &mut V, _unary_op: &'a UnaryOp)
542where
543 V: SourceOrderVisitor<'a> + ?Sized,
544{
545}
546
547#[inline]
548pub fn walk_cmp_op<'a, V>(_visitor: &mut V, _cmp_op: &'a CmpOp)
549where
550 V: SourceOrderVisitor<'a> + ?Sized,
551{
552}
553
554#[inline]
555pub fn walk_f_string<'a, V>(visitor: &mut V, f_string: &'a FString)
556where
557 V: SourceOrderVisitor<'a> + ?Sized,
558{
559 let node = AnyNodeRef::from(f_string);
560 if visitor.enter_node(node).is_traverse() {
561 f_string.visit_source_order(visitor);
562 }
563 visitor.leave_node(node);
564}
565
566#[inline]
567pub fn walk_t_string<'a, V>(visitor: &mut V, t_string: &'a TString)
568where
569 V: SourceOrderVisitor<'a> + ?Sized,
570{
571 let node = AnyNodeRef::from(t_string);
572 if visitor.enter_node(node).is_traverse() {
573 t_string.visit_source_order(visitor);
574 }
575 visitor.leave_node(node);
576}
577
578#[inline]
579pub fn walk_string_literal<'a, V>(visitor: &mut V, string_literal: &'a StringLiteral)
580where
581 V: SourceOrderVisitor<'a> + ?Sized,
582{
583 let node = AnyNodeRef::from(string_literal);
584 if visitor.enter_node(node).is_traverse() {
585 string_literal.visit_source_order(visitor);
586 }
587 visitor.leave_node(node);
588}
589
590#[inline]
591pub fn walk_bytes_literal<'a, V>(visitor: &mut V, bytes_literal: &'a BytesLiteral)
592where
593 V: SourceOrderVisitor<'a> + ?Sized,
594{
595 let node = AnyNodeRef::from(bytes_literal);
596 if visitor.enter_node(node).is_traverse() {
597 bytes_literal.visit_source_order(visitor);
598 }
599 visitor.leave_node(node);
600}
601
602#[inline]
603pub fn walk_alias<'a, V>(visitor: &mut V, alias: &'a Alias)
604where
605 V: SourceOrderVisitor<'a> + ?Sized,
606{
607 let node = AnyNodeRef::from(alias);
608 if visitor.enter_node(node).is_traverse() {
609 alias.visit_source_order(visitor);
610 }
611 visitor.leave_node(node);
612}
613
614#[inline]
615pub fn walk_identifier<'a, V: SourceOrderVisitor<'a> + ?Sized>(
616 visitor: &mut V,
617 identifier: &'a Identifier,
618) {
619 let node = AnyNodeRef::from(identifier);
620 if visitor.enter_node(node).is_traverse() {
621 identifier.visit_source_order(visitor);
622 }
623 visitor.leave_node(node);
624}