Skip to main content

ruff_python_ast/
visitor.rs

1//! AST visitor trait and walk functions.
2
3pub mod source_order;
4pub mod transformer;
5
6use crate::{
7    self as ast, Alias, AnyParameterRef, Arguments, BoolOp, BytesLiteral, CmpOp, Comprehension,
8    Decorator, ElifElseClause, ExceptHandler, Expr, ExprContext, FString, FStringPart,
9    InterpolatedStringElement, Keyword, MatchCase, Operator, Parameter, Parameters, Pattern,
10    PatternArguments, PatternKeyword, Stmt, StringLiteral, TString, TypeParam, TypeParamParamSpec,
11    TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, UnaryOp, WithItem,
12};
13
14/// A trait for AST visitors. Visits all nodes in the AST recursively in evaluation-order.
15///
16/// Prefer [`crate::statement_visitor::StatementVisitor`] for visitors that only need to visit
17/// statements.
18///
19/// Use the [`PreorderVisitor`](source_order::SourceOrderVisitor) if you want to visit the nodes
20/// in source-order rather than evaluation order.
21///
22/// Use the [`Transformer`](transformer::Transformer) if you want to modify the nodes.
23pub trait Visitor<'a> {
24    fn visit_stmt(&mut self, stmt: &'a Stmt) {
25        walk_stmt(self, stmt);
26    }
27    fn visit_annotation(&mut self, expr: &'a Expr) {
28        walk_annotation(self, expr);
29    }
30    fn visit_decorator(&mut self, decorator: &'a Decorator) {
31        walk_decorator(self, decorator);
32    }
33    fn visit_expr(&mut self, expr: &'a Expr) {
34        walk_expr(self, expr);
35    }
36    fn visit_expr_context(&mut self, expr_context: &'a ExprContext) {
37        walk_expr_context(self, expr_context);
38    }
39    fn visit_bool_op(&mut self, bool_op: &'a BoolOp) {
40        walk_bool_op(self, bool_op);
41    }
42    fn visit_operator(&mut self, operator: &'a Operator) {
43        walk_operator(self, operator);
44    }
45    fn visit_unary_op(&mut self, unary_op: &'a UnaryOp) {
46        walk_unary_op(self, unary_op);
47    }
48    fn visit_cmp_op(&mut self, cmp_op: &'a CmpOp) {
49        walk_cmp_op(self, cmp_op);
50    }
51    fn visit_comprehension(&mut self, comprehension: &'a Comprehension) {
52        walk_comprehension(self, comprehension);
53    }
54    fn visit_except_handler(&mut self, except_handler: &'a ExceptHandler) {
55        walk_except_handler(self, except_handler);
56    }
57    fn visit_arguments(&mut self, arguments: &'a Arguments) {
58        walk_arguments(self, arguments);
59    }
60    fn visit_parameters(&mut self, parameters: &'a Parameters) {
61        walk_parameters(self, parameters);
62    }
63    fn visit_parameter(&mut self, parameter: &'a Parameter) {
64        walk_parameter(self, parameter);
65    }
66    fn visit_keyword(&mut self, keyword: &'a Keyword) {
67        walk_keyword(self, keyword);
68    }
69    fn visit_alias(&mut self, alias: &'a Alias) {
70        walk_alias(self, alias);
71    }
72    fn visit_with_item(&mut self, with_item: &'a WithItem) {
73        walk_with_item(self, with_item);
74    }
75    fn visit_type_params(&mut self, type_params: &'a TypeParams) {
76        walk_type_params(self, type_params);
77    }
78    fn visit_type_param(&mut self, type_param: &'a TypeParam) {
79        walk_type_param(self, type_param);
80    }
81    fn visit_match_case(&mut self, match_case: &'a MatchCase) {
82        walk_match_case(self, match_case);
83    }
84    fn visit_pattern(&mut self, pattern: &'a Pattern) {
85        walk_pattern(self, pattern);
86    }
87    fn visit_pattern_arguments(&mut self, pattern_arguments: &'a PatternArguments) {
88        walk_pattern_arguments(self, pattern_arguments);
89    }
90    fn visit_pattern_keyword(&mut self, pattern_keyword: &'a PatternKeyword) {
91        walk_pattern_keyword(self, pattern_keyword);
92    }
93    fn visit_body(&mut self, body: &'a [Stmt]) {
94        walk_body(self, body);
95    }
96    fn visit_elif_else_clause(&mut self, elif_else_clause: &'a ElifElseClause) {
97        walk_elif_else_clause(self, elif_else_clause);
98    }
99    fn visit_f_string(&mut self, f_string: &'a FString) {
100        walk_f_string(self, f_string);
101    }
102    fn visit_interpolated_string_element(
103        &mut self,
104        interpolated_string_element: &'a InterpolatedStringElement,
105    ) {
106        walk_interpolated_string_element(self, interpolated_string_element);
107    }
108    fn visit_t_string(&mut self, t_string: &'a TString) {
109        walk_t_string(self, t_string);
110    }
111    fn visit_string_literal(&mut self, string_literal: &'a StringLiteral) {
112        walk_string_literal(self, string_literal);
113    }
114    fn visit_bytes_literal(&mut self, bytes_literal: &'a BytesLiteral) {
115        walk_bytes_literal(self, bytes_literal);
116    }
117}
118
119pub fn walk_body<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, body: &'a [Stmt]) {
120    for stmt in body {
121        visitor.visit_stmt(stmt);
122    }
123}
124
125pub fn walk_elif_else_clause<'a, V: Visitor<'a> + ?Sized>(
126    visitor: &mut V,
127    elif_else_clause: &'a ElifElseClause,
128) {
129    if let Some(test) = &elif_else_clause.test {
130        visitor.visit_expr(test);
131    }
132    visitor.visit_body(&elif_else_clause.body);
133}
134
135pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
136    match stmt {
137        Stmt::FunctionDef(ast::StmtFunctionDef {
138            parameters,
139            body,
140            decorator_list,
141            returns,
142            type_params,
143            ..
144        }) => {
145            for decorator in decorator_list {
146                visitor.visit_decorator(decorator);
147            }
148            if let Some(type_params) = type_params {
149                visitor.visit_type_params(type_params);
150            }
151            visitor.visit_parameters(parameters);
152            if let Some(expr) = returns {
153                visitor.visit_annotation(expr);
154            }
155            visitor.visit_body(body);
156        }
157        Stmt::ClassDef(ast::StmtClassDef {
158            arguments,
159            body,
160            decorator_list,
161            type_params,
162            ..
163        }) => {
164            for decorator in decorator_list {
165                visitor.visit_decorator(decorator);
166            }
167            if let Some(type_params) = type_params {
168                visitor.visit_type_params(type_params);
169            }
170            if let Some(arguments) = arguments {
171                visitor.visit_arguments(arguments);
172            }
173            visitor.visit_body(body);
174        }
175        Stmt::Return(ast::StmtReturn {
176            value,
177            range: _,
178            node_index: _,
179        }) => {
180            if let Some(expr) = value {
181                visitor.visit_expr(expr);
182            }
183        }
184        Stmt::Delete(ast::StmtDelete {
185            targets,
186            range: _,
187            node_index: _,
188        }) => {
189            for expr in targets {
190                visitor.visit_expr(expr);
191            }
192        }
193        Stmt::TypeAlias(ast::StmtTypeAlias {
194            range: _,
195            node_index: _,
196            name,
197            type_params,
198            value,
199        }) => {
200            visitor.visit_expr(value);
201            if let Some(type_params) = type_params {
202                visitor.visit_type_params(type_params);
203            }
204            visitor.visit_expr(name);
205        }
206        Stmt::Assign(ast::StmtAssign { targets, value, .. }) => {
207            visitor.visit_expr(value);
208            for expr in targets {
209                visitor.visit_expr(expr);
210            }
211        }
212        Stmt::AugAssign(ast::StmtAugAssign {
213            target,
214            op,
215            value,
216            range: _,
217            node_index: _,
218        }) => {
219            visitor.visit_expr(value);
220            visitor.visit_operator(op);
221            visitor.visit_expr(target);
222        }
223        Stmt::AnnAssign(ast::StmtAnnAssign {
224            target,
225            annotation,
226            value,
227            ..
228        }) => {
229            if let Some(expr) = value {
230                visitor.visit_expr(expr);
231            }
232            visitor.visit_annotation(annotation);
233            visitor.visit_expr(target);
234        }
235        Stmt::For(ast::StmtFor {
236            target,
237            iter,
238            body,
239            orelse,
240            ..
241        }) => {
242            visitor.visit_expr(iter);
243            visitor.visit_expr(target);
244            visitor.visit_body(body);
245            visitor.visit_body(orelse);
246        }
247        Stmt::While(ast::StmtWhile {
248            test,
249            body,
250            orelse,
251            range: _,
252            node_index: _,
253        }) => {
254            visitor.visit_expr(test);
255            visitor.visit_body(body);
256            visitor.visit_body(orelse);
257        }
258        Stmt::If(ast::StmtIf {
259            test,
260            body,
261            elif_else_clauses,
262            range: _,
263            node_index: _,
264        }) => {
265            visitor.visit_expr(test);
266            visitor.visit_body(body);
267            for clause in elif_else_clauses {
268                if let Some(test) = &clause.test {
269                    visitor.visit_expr(test);
270                }
271                walk_elif_else_clause(visitor, clause);
272            }
273        }
274        Stmt::With(ast::StmtWith { items, body, .. }) => {
275            for with_item in items {
276                visitor.visit_with_item(with_item);
277            }
278            visitor.visit_body(body);
279        }
280        Stmt::Match(ast::StmtMatch {
281            subject,
282            cases,
283            range: _,
284            node_index: _,
285        }) => {
286            visitor.visit_expr(subject);
287            for match_case in cases {
288                visitor.visit_match_case(match_case);
289            }
290        }
291        Stmt::Raise(ast::StmtRaise {
292            exc,
293            cause,
294            range: _,
295            node_index: _,
296        }) => {
297            if let Some(expr) = exc {
298                visitor.visit_expr(expr);
299            }
300            if let Some(expr) = cause {
301                visitor.visit_expr(expr);
302            }
303        }
304        Stmt::Try(ast::StmtTry {
305            body,
306            handlers,
307            orelse,
308            finalbody,
309            is_star: _,
310            range: _,
311            node_index: _,
312        }) => {
313            visitor.visit_body(body);
314            for except_handler in handlers {
315                visitor.visit_except_handler(except_handler);
316            }
317            visitor.visit_body(orelse);
318            visitor.visit_body(finalbody);
319        }
320        Stmt::Assert(ast::StmtAssert {
321            test,
322            msg,
323            range: _,
324            node_index: _,
325        }) => {
326            visitor.visit_expr(test);
327            if let Some(expr) = msg {
328                visitor.visit_expr(expr);
329            }
330        }
331        Stmt::Import(ast::StmtImport {
332            names,
333            range: _,
334            node_index: _,
335        }) => {
336            for alias in names {
337                visitor.visit_alias(alias);
338            }
339        }
340        Stmt::ImportFrom(ast::StmtImportFrom { names, .. }) => {
341            for alias in names {
342                visitor.visit_alias(alias);
343            }
344        }
345        Stmt::Global(_) => {}
346        Stmt::Nonlocal(_) => {}
347        Stmt::Expr(ast::StmtExpr {
348            value,
349            range: _,
350            node_index: _,
351        }) => visitor.visit_expr(value),
352        Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) | Stmt::IpyEscapeCommand(_) => {}
353    }
354}
355
356pub fn walk_annotation<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
357    visitor.visit_expr(expr);
358}
359
360pub fn walk_decorator<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, decorator: &'a Decorator) {
361    visitor.visit_expr(&decorator.expression);
362}
363
364pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
365    match expr {
366        Expr::BoolOp(ast::ExprBoolOp {
367            op,
368            values,
369            range: _,
370            node_index: _,
371        }) => {
372            visitor.visit_bool_op(op);
373            for expr in values {
374                visitor.visit_expr(expr);
375            }
376        }
377        Expr::Named(ast::ExprNamed {
378            target,
379            value,
380            range: _,
381            node_index: _,
382        }) => {
383            visitor.visit_expr(value);
384            visitor.visit_expr(target);
385        }
386        Expr::BinOp(ast::ExprBinOp {
387            left,
388            op,
389            right,
390            range: _,
391            node_index: _,
392        }) => {
393            visitor.visit_expr(left);
394            visitor.visit_operator(op);
395            visitor.visit_expr(right);
396        }
397        Expr::UnaryOp(ast::ExprUnaryOp {
398            op,
399            operand,
400            range: _,
401            node_index: _,
402        }) => {
403            visitor.visit_unary_op(op);
404            visitor.visit_expr(operand);
405        }
406        Expr::Lambda(ast::ExprLambda {
407            parameters,
408            body,
409            range: _,
410            node_index: _,
411        }) => {
412            if let Some(parameters) = parameters {
413                visitor.visit_parameters(parameters);
414            }
415            visitor.visit_expr(body);
416        }
417        Expr::If(ast::ExprIf {
418            test,
419            body,
420            orelse,
421            range: _,
422            node_index: _,
423        }) => {
424            visitor.visit_expr(test);
425            visitor.visit_expr(body);
426            visitor.visit_expr(orelse);
427        }
428        Expr::Dict(ast::ExprDict {
429            items,
430            range: _,
431            node_index: _,
432        }) => {
433            for ast::DictItem { key, value } in items {
434                if let Some(key) = key {
435                    visitor.visit_expr(key);
436                }
437                visitor.visit_expr(value);
438            }
439        }
440        Expr::Set(ast::ExprSet {
441            elts,
442            range: _,
443            node_index: _,
444        }) => {
445            for expr in elts {
446                visitor.visit_expr(expr);
447            }
448        }
449        Expr::ListComp(ast::ExprListComp {
450            elt,
451            generators,
452            range: _,
453            node_index: _,
454        }) => {
455            for comprehension in generators {
456                visitor.visit_comprehension(comprehension);
457            }
458            visitor.visit_expr(elt);
459        }
460        Expr::SetComp(ast::ExprSetComp {
461            elt,
462            generators,
463            range: _,
464            node_index: _,
465        }) => {
466            for comprehension in generators {
467                visitor.visit_comprehension(comprehension);
468            }
469            visitor.visit_expr(elt);
470        }
471        Expr::DictComp(ast::ExprDictComp {
472            key,
473            value,
474            generators,
475            range: _,
476            node_index: _,
477        }) => {
478            for comprehension in generators {
479                visitor.visit_comprehension(comprehension);
480            }
481            visitor.visit_expr(key);
482            visitor.visit_expr(value);
483        }
484        Expr::Generator(ast::ExprGenerator {
485            elt,
486            generators,
487            range: _,
488            node_index: _,
489            parenthesized: _,
490        }) => {
491            for comprehension in generators {
492                visitor.visit_comprehension(comprehension);
493            }
494            visitor.visit_expr(elt);
495        }
496        Expr::Await(ast::ExprAwait {
497            value,
498            range: _,
499            node_index: _,
500        }) => visitor.visit_expr(value),
501        Expr::Yield(ast::ExprYield {
502            value,
503            range: _,
504            node_index: _,
505        }) => {
506            if let Some(expr) = value {
507                visitor.visit_expr(expr);
508            }
509        }
510        Expr::YieldFrom(ast::ExprYieldFrom {
511            value,
512            range: _,
513            node_index: _,
514        }) => visitor.visit_expr(value),
515        Expr::Compare(ast::ExprCompare {
516            left,
517            ops,
518            comparators,
519            range: _,
520            node_index: _,
521        }) => {
522            visitor.visit_expr(left);
523            for cmp_op in ops {
524                visitor.visit_cmp_op(cmp_op);
525            }
526            for expr in comparators {
527                visitor.visit_expr(expr);
528            }
529        }
530        Expr::Call(ast::ExprCall {
531            func,
532            arguments,
533            range: _,
534            node_index: _,
535        }) => {
536            visitor.visit_expr(func);
537            visitor.visit_arguments(arguments);
538        }
539        Expr::FString(ast::ExprFString { value, .. }) => {
540            for part in value {
541                match part {
542                    FStringPart::Literal(string_literal) => {
543                        visitor.visit_string_literal(string_literal);
544                    }
545                    FStringPart::FString(f_string) => visitor.visit_f_string(f_string),
546                }
547            }
548        }
549        Expr::TString(ast::ExprTString { value, .. }) => {
550            for t_string in value {
551                visitor.visit_t_string(t_string);
552            }
553        }
554        Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => {
555            for string_literal in value {
556                visitor.visit_string_literal(string_literal);
557            }
558        }
559        Expr::BytesLiteral(ast::ExprBytesLiteral { value, .. }) => {
560            for bytes_literal in value {
561                visitor.visit_bytes_literal(bytes_literal);
562            }
563        }
564        Expr::NumberLiteral(_)
565        | Expr::BooleanLiteral(_)
566        | Expr::NoneLiteral(_)
567        | Expr::EllipsisLiteral(_) => {}
568        Expr::Attribute(ast::ExprAttribute { value, ctx, .. }) => {
569            visitor.visit_expr(value);
570            visitor.visit_expr_context(ctx);
571        }
572        Expr::Subscript(ast::ExprSubscript {
573            value,
574            slice,
575            ctx,
576            range: _,
577            node_index: _,
578        }) => {
579            visitor.visit_expr(value);
580            visitor.visit_expr(slice);
581            visitor.visit_expr_context(ctx);
582        }
583        Expr::Starred(ast::ExprStarred {
584            value,
585            ctx,
586            range: _,
587            node_index: _,
588        }) => {
589            visitor.visit_expr(value);
590            visitor.visit_expr_context(ctx);
591        }
592        Expr::Name(ast::ExprName { ctx, .. }) => {
593            visitor.visit_expr_context(ctx);
594        }
595        Expr::List(ast::ExprList {
596            elts,
597            ctx,
598            range: _,
599            node_index: _,
600        }) => {
601            for expr in elts {
602                visitor.visit_expr(expr);
603            }
604            visitor.visit_expr_context(ctx);
605        }
606        Expr::Tuple(ast::ExprTuple {
607            elts,
608            ctx,
609            range: _,
610            node_index: _,
611            parenthesized: _,
612        }) => {
613            for expr in elts {
614                visitor.visit_expr(expr);
615            }
616            visitor.visit_expr_context(ctx);
617        }
618        Expr::Slice(ast::ExprSlice {
619            lower,
620            upper,
621            step,
622            range: _,
623            node_index: _,
624        }) => {
625            if let Some(expr) = lower {
626                visitor.visit_expr(expr);
627            }
628            if let Some(expr) = upper {
629                visitor.visit_expr(expr);
630            }
631            if let Some(expr) = step {
632                visitor.visit_expr(expr);
633            }
634        }
635        Expr::IpyEscapeCommand(_) => {}
636    }
637}
638
639pub fn walk_comprehension<'a, V: Visitor<'a> + ?Sized>(
640    visitor: &mut V,
641    comprehension: &'a Comprehension,
642) {
643    visitor.visit_expr(&comprehension.iter);
644    visitor.visit_expr(&comprehension.target);
645    for expr in &comprehension.ifs {
646        visitor.visit_expr(expr);
647    }
648}
649
650pub fn walk_except_handler<'a, V: Visitor<'a> + ?Sized>(
651    visitor: &mut V,
652    except_handler: &'a ExceptHandler,
653) {
654    match except_handler {
655        ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, body, .. }) => {
656            if let Some(expr) = type_ {
657                visitor.visit_expr(expr);
658            }
659            visitor.visit_body(body);
660        }
661    }
662}
663
664pub fn walk_arguments<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arguments: &'a Arguments) {
665    // Note that there might be keywords before the last arg, e.g. in
666    // f(*args, a=2, *args2, **kwargs)`, but we follow Python in evaluating first `args` and then
667    // `keywords`. See also [Arguments::arguments_source_order`].
668    for arg in &*arguments.args {
669        visitor.visit_expr(arg);
670    }
671    for keyword in &*arguments.keywords {
672        visitor.visit_keyword(keyword);
673    }
674}
675
676pub fn walk_parameters<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, parameters: &'a Parameters) {
677    // Defaults are evaluated before annotations.
678    for default in parameters
679        .iter_non_variadic_params()
680        .filter_map(|param| param.default.as_deref())
681    {
682        visitor.visit_expr(default);
683    }
684
685    for parameter in parameters.iter().map(AnyParameterRef::as_parameter) {
686        visitor.visit_parameter(parameter);
687    }
688}
689
690pub fn walk_parameter<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, parameter: &'a Parameter) {
691    if let Some(expr) = &parameter.annotation {
692        visitor.visit_annotation(expr);
693    }
694}
695
696pub fn walk_keyword<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, keyword: &'a Keyword) {
697    visitor.visit_expr(&keyword.value);
698}
699
700pub fn walk_with_item<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, with_item: &'a WithItem) {
701    visitor.visit_expr(&with_item.context_expr);
702    if let Some(expr) = &with_item.optional_vars {
703        visitor.visit_expr(expr);
704    }
705}
706
707pub fn walk_type_params<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, type_params: &'a TypeParams) {
708    for type_param in &type_params.type_params {
709        visitor.visit_type_param(type_param);
710    }
711}
712
713pub fn walk_type_param<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, type_param: &'a TypeParam) {
714    match type_param {
715        TypeParam::TypeVar(TypeParamTypeVar {
716            bound,
717            default,
718            name: _,
719            range: _,
720            node_index: _,
721        }) => {
722            if let Some(expr) = bound {
723                visitor.visit_expr(expr);
724            }
725            if let Some(expr) = default {
726                visitor.visit_expr(expr);
727            }
728        }
729        TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
730            default,
731            name: _,
732            range: _,
733            node_index: _,
734        }) => {
735            if let Some(expr) = default {
736                visitor.visit_expr(expr);
737            }
738        }
739        TypeParam::ParamSpec(TypeParamParamSpec {
740            default,
741            name: _,
742            range: _,
743            node_index: _,
744        }) => {
745            if let Some(expr) = default {
746                visitor.visit_expr(expr);
747            }
748        }
749    }
750}
751
752pub fn walk_match_case<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, match_case: &'a MatchCase) {
753    visitor.visit_pattern(&match_case.pattern);
754    if let Some(expr) = &match_case.guard {
755        visitor.visit_expr(expr);
756    }
757    visitor.visit_body(&match_case.body);
758}
759
760pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a Pattern) {
761    match pattern {
762        Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => {
763            visitor.visit_expr(value);
764        }
765        Pattern::MatchSingleton(_) => {}
766        Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => {
767            for pattern in patterns {
768                visitor.visit_pattern(pattern);
769            }
770        }
771        Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, .. }) => {
772            for expr in keys {
773                visitor.visit_expr(expr);
774            }
775            for pattern in patterns {
776                visitor.visit_pattern(pattern);
777            }
778        }
779        Pattern::MatchClass(ast::PatternMatchClass { cls, arguments, .. }) => {
780            visitor.visit_expr(cls);
781            visitor.visit_pattern_arguments(arguments);
782        }
783        Pattern::MatchStar(_) => {}
784        Pattern::MatchAs(ast::PatternMatchAs { pattern, .. }) => {
785            if let Some(pattern) = pattern {
786                visitor.visit_pattern(pattern);
787            }
788        }
789        Pattern::MatchOr(ast::PatternMatchOr { patterns, .. }) => {
790            for pattern in patterns {
791                visitor.visit_pattern(pattern);
792            }
793        }
794    }
795}
796
797pub fn walk_pattern_arguments<'a, V: Visitor<'a> + ?Sized>(
798    visitor: &mut V,
799    pattern_arguments: &'a PatternArguments,
800) {
801    for pattern in &pattern_arguments.patterns {
802        visitor.visit_pattern(pattern);
803    }
804    for keyword in &pattern_arguments.keywords {
805        visitor.visit_pattern_keyword(keyword);
806    }
807}
808
809pub fn walk_pattern_keyword<'a, V: Visitor<'a> + ?Sized>(
810    visitor: &mut V,
811    pattern_keyword: &'a PatternKeyword,
812) {
813    visitor.visit_pattern(&pattern_keyword.pattern);
814}
815
816pub fn walk_f_string<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, f_string: &'a FString) {
817    for interpolated_string_element in &f_string.elements {
818        visitor.visit_interpolated_string_element(interpolated_string_element);
819    }
820}
821
822pub fn walk_interpolated_string_element<'a, V: Visitor<'a> + ?Sized>(
823    visitor: &mut V,
824    interpolated_string_element: &'a InterpolatedStringElement,
825) {
826    if let ast::InterpolatedStringElement::Interpolation(ast::InterpolatedElement {
827        expression,
828        format_spec,
829        ..
830    }) = interpolated_string_element
831    {
832        visitor.visit_expr(expression);
833        if let Some(format_spec) = format_spec {
834            for spec_element in &format_spec.elements {
835                visitor.visit_interpolated_string_element(spec_element);
836            }
837        }
838    }
839}
840
841pub fn walk_t_string<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, t_string: &'a TString) {
842    for t_string_element in &t_string.elements {
843        visitor.visit_interpolated_string_element(t_string_element);
844    }
845}
846
847pub fn walk_expr_context<'a, V: Visitor<'a> + ?Sized>(
848    _visitor: &V,
849    _expr_context: &'a ExprContext,
850) {
851}
852
853pub fn walk_bool_op<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _bool_op: &'a BoolOp) {}
854
855pub fn walk_operator<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _operator: &'a Operator) {}
856
857pub fn walk_unary_op<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _unary_op: &'a UnaryOp) {}
858
859pub fn walk_cmp_op<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _cmp_op: &'a CmpOp) {}
860
861pub fn walk_alias<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _alias: &'a Alias) {}
862
863pub fn walk_string_literal<'a, V: Visitor<'a> + ?Sized>(
864    _visitor: &V,
865    _string_literal: &'a StringLiteral,
866) {
867}
868
869pub fn walk_bytes_literal<'a, V: Visitor<'a> + ?Sized>(
870    _visitor: &V,
871    _bytes_literal: &'a BytesLiteral,
872) {
873}