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                visitor.visit_elif_else_clause(clause);
269            }
270        }
271        Stmt::With(ast::StmtWith { items, body, .. }) => {
272            for with_item in items {
273                visitor.visit_with_item(with_item);
274            }
275            visitor.visit_body(body);
276        }
277        Stmt::Match(ast::StmtMatch {
278            subject,
279            cases,
280            range: _,
281            node_index: _,
282        }) => {
283            visitor.visit_expr(subject);
284            for match_case in cases {
285                visitor.visit_match_case(match_case);
286            }
287        }
288        Stmt::Raise(ast::StmtRaise {
289            exc,
290            cause,
291            range: _,
292            node_index: _,
293        }) => {
294            if let Some(expr) = exc {
295                visitor.visit_expr(expr);
296            }
297            if let Some(expr) = cause {
298                visitor.visit_expr(expr);
299            }
300        }
301        Stmt::Try(ast::StmtTry {
302            body,
303            handlers,
304            orelse,
305            finalbody,
306            is_star: _,
307            range: _,
308            node_index: _,
309        }) => {
310            visitor.visit_body(body);
311            for except_handler in handlers {
312                visitor.visit_except_handler(except_handler);
313            }
314            visitor.visit_body(orelse);
315            visitor.visit_body(finalbody);
316        }
317        Stmt::Assert(ast::StmtAssert {
318            test,
319            msg,
320            range: _,
321            node_index: _,
322        }) => {
323            visitor.visit_expr(test);
324            if let Some(expr) = msg {
325                visitor.visit_expr(expr);
326            }
327        }
328        Stmt::Import(ast::StmtImport {
329            names,
330            is_lazy: _,
331            range: _,
332            node_index: _,
333        }) => {
334            for alias in names {
335                visitor.visit_alias(alias);
336            }
337        }
338        Stmt::ImportFrom(ast::StmtImportFrom { names, .. }) => {
339            for alias in names {
340                visitor.visit_alias(alias);
341            }
342        }
343        Stmt::Global(_) => {}
344        Stmt::Nonlocal(_) => {}
345        Stmt::Expr(ast::StmtExpr {
346            value,
347            range: _,
348            node_index: _,
349        }) => visitor.visit_expr(value),
350        Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) | Stmt::IpyEscapeCommand(_) => {}
351    }
352}
353
354pub fn walk_annotation<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
355    visitor.visit_expr(expr);
356}
357
358pub fn walk_decorator<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, decorator: &'a Decorator) {
359    visitor.visit_expr(&decorator.expression);
360}
361
362pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
363    match expr {
364        Expr::BoolOp(ast::ExprBoolOp {
365            op,
366            values,
367            range: _,
368            node_index: _,
369        }) => {
370            visitor.visit_bool_op(op);
371            for expr in values {
372                visitor.visit_expr(expr);
373            }
374        }
375        Expr::Named(ast::ExprNamed {
376            target,
377            value,
378            range: _,
379            node_index: _,
380        }) => {
381            visitor.visit_expr(value);
382            visitor.visit_expr(target);
383        }
384        Expr::BinOp(ast::ExprBinOp {
385            left,
386            op,
387            right,
388            range: _,
389            node_index: _,
390        }) => {
391            visitor.visit_expr(left);
392            visitor.visit_operator(op);
393            visitor.visit_expr(right);
394        }
395        Expr::UnaryOp(ast::ExprUnaryOp {
396            op,
397            operand,
398            range: _,
399            node_index: _,
400        }) => {
401            visitor.visit_unary_op(op);
402            visitor.visit_expr(operand);
403        }
404        Expr::Lambda(ast::ExprLambda {
405            parameters,
406            body,
407            range: _,
408            node_index: _,
409        }) => {
410            if let Some(parameters) = parameters {
411                visitor.visit_parameters(parameters);
412            }
413            visitor.visit_expr(body);
414        }
415        Expr::If(ast::ExprIf {
416            test,
417            body,
418            orelse,
419            range: _,
420            node_index: _,
421        }) => {
422            visitor.visit_expr(test);
423            visitor.visit_expr(body);
424            visitor.visit_expr(orelse);
425        }
426        Expr::Dict(ast::ExprDict {
427            items,
428            range: _,
429            node_index: _,
430        }) => {
431            for ast::DictItem { key, value } in items {
432                if let Some(key) = key {
433                    visitor.visit_expr(key);
434                }
435                visitor.visit_expr(value);
436            }
437        }
438        Expr::Set(ast::ExprSet {
439            elts,
440            range: _,
441            node_index: _,
442        }) => {
443            for expr in elts {
444                visitor.visit_expr(expr);
445            }
446        }
447        Expr::ListComp(ast::ExprListComp {
448            elt,
449            generators,
450            range: _,
451            node_index: _,
452        }) => {
453            for comprehension in generators {
454                visitor.visit_comprehension(comprehension);
455            }
456            visitor.visit_expr(elt);
457        }
458        Expr::SetComp(ast::ExprSetComp {
459            elt,
460            generators,
461            range: _,
462            node_index: _,
463        }) => {
464            for comprehension in generators {
465                visitor.visit_comprehension(comprehension);
466            }
467            visitor.visit_expr(elt);
468        }
469        Expr::DictComp(ast::ExprDictComp {
470            key,
471            value,
472            generators,
473            range: _,
474            node_index: _,
475        }) => {
476            for comprehension in generators {
477                visitor.visit_comprehension(comprehension);
478            }
479            if let Some(key) = key {
480                visitor.visit_expr(key);
481            }
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_start: _,
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}