Skip to main content

rustpython_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            is_lazy: _,
334            range: _,
335            node_index: _,
336        }) => {
337            for alias in names {
338                visitor.visit_alias(alias);
339            }
340        }
341        Stmt::ImportFrom(ast::StmtImportFrom { names, .. }) => {
342            for alias in names {
343                visitor.visit_alias(alias);
344            }
345        }
346        Stmt::Global(_) => {}
347        Stmt::Nonlocal(_) => {}
348        Stmt::Expr(ast::StmtExpr {
349            value,
350            range: _,
351            node_index: _,
352        }) => visitor.visit_expr(value),
353        Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) | Stmt::IpyEscapeCommand(_) => {}
354    }
355}
356
357pub fn walk_annotation<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
358    visitor.visit_expr(expr);
359}
360
361pub fn walk_decorator<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, decorator: &'a Decorator) {
362    visitor.visit_expr(&decorator.expression);
363}
364
365pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
366    match expr {
367        Expr::BoolOp(ast::ExprBoolOp {
368            op,
369            values,
370            range: _,
371            node_index: _,
372        }) => {
373            visitor.visit_bool_op(op);
374            for expr in values {
375                visitor.visit_expr(expr);
376            }
377        }
378        Expr::Named(ast::ExprNamed {
379            target,
380            value,
381            range: _,
382            node_index: _,
383        }) => {
384            visitor.visit_expr(value);
385            visitor.visit_expr(target);
386        }
387        Expr::BinOp(ast::ExprBinOp {
388            left,
389            op,
390            right,
391            range: _,
392            node_index: _,
393        }) => {
394            visitor.visit_expr(left);
395            visitor.visit_operator(op);
396            visitor.visit_expr(right);
397        }
398        Expr::UnaryOp(ast::ExprUnaryOp {
399            op,
400            operand,
401            range: _,
402            node_index: _,
403        }) => {
404            visitor.visit_unary_op(op);
405            visitor.visit_expr(operand);
406        }
407        Expr::Lambda(ast::ExprLambda {
408            parameters,
409            body,
410            range: _,
411            node_index: _,
412        }) => {
413            if let Some(parameters) = parameters {
414                visitor.visit_parameters(parameters);
415            }
416            visitor.visit_expr(body);
417        }
418        Expr::If(ast::ExprIf {
419            test,
420            body,
421            orelse,
422            range: _,
423            node_index: _,
424        }) => {
425            visitor.visit_expr(test);
426            visitor.visit_expr(body);
427            visitor.visit_expr(orelse);
428        }
429        Expr::Dict(ast::ExprDict {
430            items,
431            range: _,
432            node_index: _,
433        }) => {
434            for ast::DictItem { key, value } in items {
435                if let Some(key) = key {
436                    visitor.visit_expr(key);
437                }
438                visitor.visit_expr(value);
439            }
440        }
441        Expr::Set(ast::ExprSet {
442            elts,
443            range: _,
444            node_index: _,
445        }) => {
446            for expr in elts {
447                visitor.visit_expr(expr);
448            }
449        }
450        Expr::ListComp(ast::ExprListComp {
451            elt,
452            generators,
453            range: _,
454            node_index: _,
455        }) => {
456            for comprehension in generators {
457                visitor.visit_comprehension(comprehension);
458            }
459            visitor.visit_expr(elt);
460        }
461        Expr::SetComp(ast::ExprSetComp {
462            elt,
463            generators,
464            range: _,
465            node_index: _,
466        }) => {
467            for comprehension in generators {
468                visitor.visit_comprehension(comprehension);
469            }
470            visitor.visit_expr(elt);
471        }
472        Expr::DictComp(ast::ExprDictComp {
473            key,
474            value,
475            generators,
476            range: _,
477            node_index: _,
478        }) => {
479            for comprehension in generators {
480                visitor.visit_comprehension(comprehension);
481            }
482            visitor.visit_expr(key);
483            visitor.visit_expr(value);
484        }
485        Expr::Generator(ast::ExprGenerator {
486            elt,
487            generators,
488            range: _,
489            node_index: _,
490            parenthesized: _,
491        }) => {
492            for comprehension in generators {
493                visitor.visit_comprehension(comprehension);
494            }
495            visitor.visit_expr(elt);
496        }
497        Expr::Await(ast::ExprAwait {
498            value,
499            range: _,
500            node_index: _,
501        }) => visitor.visit_expr(value),
502        Expr::Yield(ast::ExprYield {
503            value,
504            range: _,
505            node_index: _,
506        }) => {
507            if let Some(expr) = value {
508                visitor.visit_expr(expr);
509            }
510        }
511        Expr::YieldFrom(ast::ExprYieldFrom {
512            value,
513            range: _,
514            node_index: _,
515        }) => visitor.visit_expr(value),
516        Expr::Compare(ast::ExprCompare {
517            left,
518            ops,
519            comparators,
520            range: _,
521            node_index: _,
522        }) => {
523            visitor.visit_expr(left);
524            for cmp_op in ops {
525                visitor.visit_cmp_op(cmp_op);
526            }
527            for expr in comparators {
528                visitor.visit_expr(expr);
529            }
530        }
531        Expr::Call(ast::ExprCall {
532            func,
533            arguments,
534            range: _,
535            node_index: _,
536        }) => {
537            visitor.visit_expr(func);
538            visitor.visit_arguments(arguments);
539        }
540        Expr::FString(ast::ExprFString { value, .. }) => {
541            for part in value {
542                match part {
543                    FStringPart::Literal(string_literal) => {
544                        visitor.visit_string_literal(string_literal);
545                    }
546                    FStringPart::FString(f_string) => visitor.visit_f_string(f_string),
547                }
548            }
549        }
550        Expr::TString(ast::ExprTString { value, .. }) => {
551            for t_string in value {
552                visitor.visit_t_string(t_string);
553            }
554        }
555        Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => {
556            for string_literal in value {
557                visitor.visit_string_literal(string_literal);
558            }
559        }
560        Expr::BytesLiteral(ast::ExprBytesLiteral { value, .. }) => {
561            for bytes_literal in value {
562                visitor.visit_bytes_literal(bytes_literal);
563            }
564        }
565        Expr::NumberLiteral(_)
566        | Expr::BooleanLiteral(_)
567        | Expr::NoneLiteral(_)
568        | Expr::EllipsisLiteral(_) => {}
569        Expr::Attribute(ast::ExprAttribute { value, ctx, .. }) => {
570            visitor.visit_expr(value);
571            visitor.visit_expr_context(ctx);
572        }
573        Expr::Subscript(ast::ExprSubscript {
574            value,
575            slice,
576            ctx,
577            range: _,
578            node_index: _,
579        }) => {
580            visitor.visit_expr(value);
581            visitor.visit_expr(slice);
582            visitor.visit_expr_context(ctx);
583        }
584        Expr::Starred(ast::ExprStarred {
585            value,
586            ctx,
587            range: _,
588            node_index: _,
589        }) => {
590            visitor.visit_expr(value);
591            visitor.visit_expr_context(ctx);
592        }
593        Expr::Name(ast::ExprName { ctx, .. }) => {
594            visitor.visit_expr_context(ctx);
595        }
596        Expr::List(ast::ExprList {
597            elts,
598            ctx,
599            range: _,
600            node_index: _,
601        }) => {
602            for expr in elts {
603                visitor.visit_expr(expr);
604            }
605            visitor.visit_expr_context(ctx);
606        }
607        Expr::Tuple(ast::ExprTuple {
608            elts,
609            ctx,
610            range: _,
611            node_index: _,
612            parenthesized: _,
613        }) => {
614            for expr in elts {
615                visitor.visit_expr(expr);
616            }
617            visitor.visit_expr_context(ctx);
618        }
619        Expr::Slice(ast::ExprSlice {
620            lower,
621            upper,
622            step,
623            range: _,
624            node_index: _,
625        }) => {
626            if let Some(expr) = lower {
627                visitor.visit_expr(expr);
628            }
629            if let Some(expr) = upper {
630                visitor.visit_expr(expr);
631            }
632            if let Some(expr) = step {
633                visitor.visit_expr(expr);
634            }
635        }
636        Expr::IpyEscapeCommand(_) => {}
637    }
638}
639
640pub fn walk_comprehension<'a, V: Visitor<'a> + ?Sized>(
641    visitor: &mut V,
642    comprehension: &'a Comprehension,
643) {
644    visitor.visit_expr(&comprehension.iter);
645    visitor.visit_expr(&comprehension.target);
646    for expr in &comprehension.ifs {
647        visitor.visit_expr(expr);
648    }
649}
650
651pub fn walk_except_handler<'a, V: Visitor<'a> + ?Sized>(
652    visitor: &mut V,
653    except_handler: &'a ExceptHandler,
654) {
655    match except_handler {
656        ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, body, .. }) => {
657            if let Some(expr) = type_ {
658                visitor.visit_expr(expr);
659            }
660            visitor.visit_body(body);
661        }
662    }
663}
664
665pub fn walk_arguments<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arguments: &'a Arguments) {
666    // Note that there might be keywords before the last arg, e.g. in
667    // f(*args, a=2, *args2, **kwargs)`, but we follow Python in evaluating first `args` and then
668    // `keywords`. See also [Arguments::arguments_source_order`].
669    for arg in &*arguments.args {
670        visitor.visit_expr(arg);
671    }
672    for keyword in &*arguments.keywords {
673        visitor.visit_keyword(keyword);
674    }
675}
676
677pub fn walk_parameters<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, parameters: &'a Parameters) {
678    // Defaults are evaluated before annotations.
679    for default in parameters
680        .iter_non_variadic_params()
681        .filter_map(|param| param.default.as_deref())
682    {
683        visitor.visit_expr(default);
684    }
685
686    for parameter in parameters.iter().map(AnyParameterRef::as_parameter) {
687        visitor.visit_parameter(parameter);
688    }
689}
690
691pub fn walk_parameter<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, parameter: &'a Parameter) {
692    if let Some(expr) = &parameter.annotation {
693        visitor.visit_annotation(expr);
694    }
695}
696
697pub fn walk_keyword<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, keyword: &'a Keyword) {
698    visitor.visit_expr(&keyword.value);
699}
700
701pub fn walk_with_item<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, with_item: &'a WithItem) {
702    visitor.visit_expr(&with_item.context_expr);
703    if let Some(expr) = &with_item.optional_vars {
704        visitor.visit_expr(expr);
705    }
706}
707
708pub fn walk_type_params<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, type_params: &'a TypeParams) {
709    for type_param in &type_params.type_params {
710        visitor.visit_type_param(type_param);
711    }
712}
713
714pub fn walk_type_param<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, type_param: &'a TypeParam) {
715    match type_param {
716        TypeParam::TypeVar(TypeParamTypeVar {
717            bound,
718            default,
719            name: _,
720            range: _,
721            node_index: _,
722        }) => {
723            if let Some(expr) = bound {
724                visitor.visit_expr(expr);
725            }
726            if let Some(expr) = default {
727                visitor.visit_expr(expr);
728            }
729        }
730        TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
731            default,
732            name: _,
733            range: _,
734            node_index: _,
735        }) => {
736            if let Some(expr) = default {
737                visitor.visit_expr(expr);
738            }
739        }
740        TypeParam::ParamSpec(TypeParamParamSpec {
741            default,
742            name: _,
743            range: _,
744            node_index: _,
745        }) => {
746            if let Some(expr) = default {
747                visitor.visit_expr(expr);
748            }
749        }
750    }
751}
752
753pub fn walk_match_case<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, match_case: &'a MatchCase) {
754    visitor.visit_pattern(&match_case.pattern);
755    if let Some(expr) = &match_case.guard {
756        visitor.visit_expr(expr);
757    }
758    visitor.visit_body(&match_case.body);
759}
760
761pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a Pattern) {
762    match pattern {
763        Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => {
764            visitor.visit_expr(value);
765        }
766        Pattern::MatchSingleton(_) => {}
767        Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => {
768            for pattern in patterns {
769                visitor.visit_pattern(pattern);
770            }
771        }
772        Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, .. }) => {
773            for expr in keys {
774                visitor.visit_expr(expr);
775            }
776            for pattern in patterns {
777                visitor.visit_pattern(pattern);
778            }
779        }
780        Pattern::MatchClass(ast::PatternMatchClass { cls, arguments, .. }) => {
781            visitor.visit_expr(cls);
782            visitor.visit_pattern_arguments(arguments);
783        }
784        Pattern::MatchStar(_) => {}
785        Pattern::MatchAs(ast::PatternMatchAs { pattern, .. }) => {
786            if let Some(pattern) = pattern {
787                visitor.visit_pattern(pattern);
788            }
789        }
790        Pattern::MatchOr(ast::PatternMatchOr { patterns, .. }) => {
791            for pattern in patterns {
792                visitor.visit_pattern(pattern);
793            }
794        }
795    }
796}
797
798pub fn walk_pattern_arguments<'a, V: Visitor<'a> + ?Sized>(
799    visitor: &mut V,
800    pattern_arguments: &'a PatternArguments,
801) {
802    for pattern in &pattern_arguments.patterns {
803        visitor.visit_pattern(pattern);
804    }
805    for keyword in &pattern_arguments.keywords {
806        visitor.visit_pattern_keyword(keyword);
807    }
808}
809
810pub fn walk_pattern_keyword<'a, V: Visitor<'a> + ?Sized>(
811    visitor: &mut V,
812    pattern_keyword: &'a PatternKeyword,
813) {
814    visitor.visit_pattern(&pattern_keyword.pattern);
815}
816
817pub fn walk_f_string<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, f_string: &'a FString) {
818    for interpolated_string_element in &f_string.elements {
819        visitor.visit_interpolated_string_element(interpolated_string_element);
820    }
821}
822
823pub fn walk_interpolated_string_element<'a, V: Visitor<'a> + ?Sized>(
824    visitor: &mut V,
825    interpolated_string_element: &'a InterpolatedStringElement,
826) {
827    if let ast::InterpolatedStringElement::Interpolation(ast::InterpolatedElement {
828        expression,
829        format_spec,
830        ..
831    }) = interpolated_string_element
832    {
833        visitor.visit_expr(expression);
834        if let Some(format_spec) = format_spec {
835            for spec_element in &format_spec.elements {
836                visitor.visit_interpolated_string_element(spec_element);
837            }
838        }
839    }
840}
841
842pub fn walk_t_string<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, t_string: &'a TString) {
843    for t_string_element in &t_string.elements {
844        visitor.visit_interpolated_string_element(t_string_element);
845    }
846}
847
848pub fn walk_expr_context<'a, V: Visitor<'a> + ?Sized>(
849    _visitor: &V,
850    _expr_context: &'a ExprContext,
851) {
852}
853
854pub fn walk_bool_op<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _bool_op: &'a BoolOp) {}
855
856pub fn walk_operator<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _operator: &'a Operator) {}
857
858pub fn walk_unary_op<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _unary_op: &'a UnaryOp) {}
859
860pub fn walk_cmp_op<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _cmp_op: &'a CmpOp) {}
861
862pub fn walk_alias<'a, V: Visitor<'a> + ?Sized>(_visitor: &V, _alias: &'a Alias) {}
863
864pub fn walk_string_literal<'a, V: Visitor<'a> + ?Sized>(
865    _visitor: &V,
866    _string_literal: &'a StringLiteral,
867) {
868}
869
870pub fn walk_bytes_literal<'a, V: Visitor<'a> + ?Sized>(
871    _visitor: &V,
872    _bytes_literal: &'a BytesLiteral,
873) {
874}