Skip to main content

ruff_python_ast/visitor/
transformer.rs

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