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