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 { value, .. }) => {
163            if let Some(expr) = value {
164                visitor.visit_expr(expr);
165            }
166        }
167        Stmt::Delete(ast::StmtDelete { targets, .. }) => {
168            for expr in targets {
169                visitor.visit_expr(expr);
170            }
171        }
172        Stmt::TypeAlias(ast::StmtTypeAlias {
173            range: _,
174            node_index: _,
175            name,
176            type_params,
177            value,
178        }) => {
179            visitor.visit_expr(value);
180            if let Some(type_params) = type_params {
181                visitor.visit_type_params(type_params);
182            }
183            visitor.visit_expr(name);
184        }
185        Stmt::Assign(ast::StmtAssign { targets, value, .. }) => {
186            visitor.visit_expr(value);
187            for expr in targets {
188                visitor.visit_expr(expr);
189            }
190        }
191        Stmt::AugAssign(ast::StmtAugAssign {
192            target, op, value, ..
193        }) => {
194            visitor.visit_expr(value);
195            visitor.visit_operator(op);
196            visitor.visit_expr(target);
197        }
198        Stmt::AnnAssign(ast::StmtAnnAssign {
199            target,
200            annotation,
201            value,
202            ..
203        }) => {
204            if let Some(expr) = value {
205                visitor.visit_expr(expr);
206            }
207            visitor.visit_annotation(annotation);
208            visitor.visit_expr(target);
209        }
210        Stmt::For(ast::StmtFor {
211            target,
212            iter,
213            body,
214            orelse,
215            ..
216        }) => {
217            visitor.visit_expr(iter);
218            visitor.visit_expr(target);
219            visitor.visit_body(body);
220            visitor.visit_body(orelse);
221        }
222        Stmt::While(ast::StmtWhile {
223            test, body, orelse, ..
224        }) => {
225            visitor.visit_expr(test);
226            visitor.visit_body(body);
227            visitor.visit_body(orelse);
228        }
229        Stmt::If(ast::StmtIf {
230            test,
231            body,
232            elif_else_clauses,
233            ..
234        }) => {
235            visitor.visit_expr(test);
236            visitor.visit_body(body);
237            for clause in elif_else_clauses {
238                visitor.visit_elif_else_clause(clause);
239            }
240        }
241        Stmt::With(ast::StmtWith { items, body, .. }) => {
242            for with_item in items {
243                visitor.visit_with_item(with_item);
244            }
245            visitor.visit_body(body);
246        }
247        Stmt::Match(ast::StmtMatch { subject, cases, .. }) => {
248            visitor.visit_expr(subject);
249            for match_case in cases {
250                visitor.visit_match_case(match_case);
251            }
252        }
253        Stmt::Raise(ast::StmtRaise { exc, cause, .. }) => {
254            if let Some(expr) = exc {
255                visitor.visit_expr(expr);
256            }
257            if let Some(expr) = cause {
258                visitor.visit_expr(expr);
259            }
260        }
261        Stmt::Try(ast::StmtTry {
262            body,
263            handlers,
264            orelse,
265            finalbody,
266            ..
267        }) => {
268            visitor.visit_body(body);
269            for except_handler in handlers {
270                visitor.visit_except_handler(except_handler);
271            }
272            visitor.visit_body(orelse);
273            visitor.visit_body(finalbody);
274        }
275        Stmt::Assert(ast::StmtAssert { test, msg, .. }) => {
276            visitor.visit_expr(test);
277            if let Some(expr) = msg {
278                visitor.visit_expr(expr);
279            }
280        }
281        Stmt::Import(ast::StmtImport { names, .. }) => {
282            for alias in names {
283                visitor.visit_alias(alias);
284            }
285        }
286        Stmt::ImportFrom(ast::StmtImportFrom { names, .. }) => {
287            for alias in names {
288                visitor.visit_alias(alias);
289            }
290        }
291        Stmt::Global(_) => {}
292        Stmt::Nonlocal(_) => {}
293        Stmt::Expr(ast::StmtExpr { value, .. }) => visitor.visit_expr(value),
294        Stmt::Pass(_) | Stmt::Break(_) | Stmt::Continue(_) | Stmt::IpyEscapeCommand(_) => {}
295    }
296}
297
298pub fn walk_annotation<V: Transformer + ?Sized>(visitor: &V, expr: &mut Expr) {
299    visitor.visit_expr(expr);
300}
301
302pub fn walk_decorator<V: Transformer + ?Sized>(visitor: &V, decorator: &mut Decorator) {
303    visitor.visit_expr(&mut decorator.expression);
304}
305
306pub fn walk_expr<V: Transformer + ?Sized>(visitor: &V, expr: &mut Expr) {
307    match expr {
308        Expr::BoolOp(ast::ExprBoolOp { op, values, .. }) => {
309            visitor.visit_bool_op(op);
310            for expr in values {
311                visitor.visit_expr(expr);
312            }
313        }
314        Expr::Named(ast::ExprNamed { target, value, .. }) => {
315            visitor.visit_expr(value);
316            visitor.visit_expr(target);
317        }
318        Expr::BinOp(ast::ExprBinOp {
319            left, op, right, ..
320        }) => {
321            visitor.visit_expr(left);
322            visitor.visit_operator(op);
323            visitor.visit_expr(right);
324        }
325        Expr::UnaryOp(ast::ExprUnaryOp { op, operand, .. }) => {
326            visitor.visit_unary_op(op);
327            visitor.visit_expr(operand);
328        }
329        Expr::Lambda(ast::ExprLambda {
330            parameters, body, ..
331        }) => {
332            if let Some(parameters) = parameters {
333                visitor.visit_parameters(parameters);
334            }
335            visitor.visit_expr(body);
336        }
337        Expr::If(ast::ExprIf {
338            test, body, orelse, ..
339        }) => {
340            visitor.visit_expr(test);
341            visitor.visit_expr(body);
342            visitor.visit_expr(orelse);
343        }
344        Expr::Dict(ast::ExprDict { items, .. }) => {
345            for ast::DictItem { key, value } in items {
346                if let Some(key) = key {
347                    visitor.visit_expr(key);
348                }
349                visitor.visit_expr(value);
350            }
351        }
352        Expr::Set(ast::ExprSet { elts, .. }) => {
353            for expr in elts {
354                visitor.visit_expr(expr);
355            }
356        }
357        Expr::ListComp(ast::ExprListComp {
358            elt, generators, ..
359        }) => {
360            for comprehension in generators {
361                visitor.visit_comprehension(comprehension);
362            }
363            visitor.visit_expr(elt);
364        }
365        Expr::SetComp(ast::ExprSetComp {
366            elt, generators, ..
367        }) => {
368            for comprehension in generators {
369                visitor.visit_comprehension(comprehension);
370            }
371            visitor.visit_expr(elt);
372        }
373        Expr::DictComp(ast::ExprDictComp {
374            key,
375            value,
376            generators,
377            ..
378        }) => {
379            for comprehension in generators {
380                visitor.visit_comprehension(comprehension);
381            }
382            if let Some(key) = key {
383                visitor.visit_expr(key);
384            }
385            visitor.visit_expr(value);
386        }
387        Expr::Generator(ast::ExprGenerator {
388            elt, generators, ..
389        }) => {
390            for comprehension in generators {
391                visitor.visit_comprehension(comprehension);
392            }
393            visitor.visit_expr(elt);
394        }
395        Expr::Await(ast::ExprAwait { value, .. }) => visitor.visit_expr(value),
396        Expr::Yield(ast::ExprYield { value, .. }) => {
397            if let Some(expr) = value {
398                visitor.visit_expr(expr);
399            }
400        }
401        Expr::YieldFrom(ast::ExprYieldFrom { value, .. }) => visitor.visit_expr(value),
402        Expr::Compare(ast::ExprCompare {
403            ops,
404            operands,
405            range: _,
406            node_index: _,
407            runtime_comparators: _,
408        }) => {
409            if let Some((left, comparators)) = operands.split_first_mut() {
410                visitor.visit_expr(left);
411                for cmp_op in &mut **ops {
412                    visitor.visit_cmp_op(cmp_op);
413                }
414                for expr in comparators {
415                    visitor.visit_expr(expr);
416                }
417            }
418        }
419        Expr::Call(ast::ExprCall {
420            func, arguments, ..
421        }) => {
422            visitor.visit_expr(func);
423            visitor.visit_arguments(arguments);
424        }
425        Expr::FString(ast::ExprFString { value, .. }) => {
426            for f_string_part in value.iter_mut() {
427                match f_string_part {
428                    ast::FStringPartMut::Literal(string_literal) => {
429                        visitor.visit_string_literal(string_literal);
430                    }
431                    ast::FStringPartMut::FString(f_string) => {
432                        visitor.visit_f_string(f_string);
433                    }
434                }
435            }
436        }
437        Expr::TString(ast::ExprTString { value, .. }) => {
438            for t_string in value.iter_mut() {
439                visitor.visit_t_string(t_string);
440            }
441        }
442        Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) => {
443            for string_literal in value.iter_mut() {
444                visitor.visit_string_literal(string_literal);
445            }
446        }
447        Expr::BytesLiteral(ast::ExprBytesLiteral { value, .. }) => {
448            for bytes_literal in value.iter_mut() {
449                visitor.visit_bytes_literal(bytes_literal);
450            }
451        }
452        Expr::NumberLiteral(_)
453        | Expr::Constant(_)
454        | Expr::BooleanLiteral(_)
455        | Expr::NoneLiteral(_)
456        | Expr::EllipsisLiteral(_) => {}
457        Expr::Attribute(ast::ExprAttribute { value, ctx, .. }) => {
458            visitor.visit_expr(value);
459            visitor.visit_expr_context(ctx);
460        }
461        Expr::Subscript(ast::ExprSubscript {
462            value, slice, ctx, ..
463        }) => {
464            visitor.visit_expr(value);
465            visitor.visit_expr(slice);
466            visitor.visit_expr_context(ctx);
467        }
468        Expr::Starred(ast::ExprStarred { value, ctx, .. }) => {
469            visitor.visit_expr(value);
470            visitor.visit_expr_context(ctx);
471        }
472        Expr::Name(ast::ExprName { ctx, .. }) => {
473            visitor.visit_expr_context(ctx);
474        }
475        Expr::List(ast::ExprList { elts, ctx, .. }) => {
476            for expr in elts {
477                visitor.visit_expr(expr);
478            }
479            visitor.visit_expr_context(ctx);
480        }
481        Expr::Tuple(ast::ExprTuple { elts, ctx, .. }) => {
482            for expr in elts {
483                visitor.visit_expr(expr);
484            }
485            visitor.visit_expr_context(ctx);
486        }
487        Expr::Slice(ast::ExprSlice {
488            lower, upper, step, ..
489        }) => {
490            if let Some(expr) = lower {
491                visitor.visit_expr(expr);
492            }
493            if let Some(expr) = upper {
494                visitor.visit_expr(expr);
495            }
496            if let Some(expr) = step {
497                visitor.visit_expr(expr);
498            }
499        }
500        Expr::IpyEscapeCommand(_) => {}
501    }
502}
503
504pub fn walk_comprehension<V: Transformer + ?Sized>(visitor: &V, comprehension: &mut Comprehension) {
505    visitor.visit_expr(&mut comprehension.iter);
506    visitor.visit_expr(&mut comprehension.target);
507    for expr in &mut comprehension.ifs {
508        visitor.visit_expr(expr);
509    }
510}
511
512pub fn walk_except_handler<V: Transformer + ?Sized>(
513    visitor: &V,
514    except_handler: &mut ExceptHandler,
515) {
516    match except_handler {
517        ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, body, .. }) => {
518            if let Some(expr) = type_ {
519                visitor.visit_expr(expr);
520            }
521            visitor.visit_body(body);
522        }
523    }
524}
525
526pub fn walk_arguments<V: Transformer + ?Sized>(visitor: &V, arguments: &mut Arguments) {
527    // Note that there might be keywords before the last arg, e.g. in
528    // f(*args, a=2, *args2, **kwargs)`, but we follow Python in evaluating first `args` and then
529    // `keywords`. See also [Arguments::arguments_source_order`].
530    for arg in &mut *arguments.args {
531        visitor.visit_expr(arg);
532    }
533    for keyword in &mut *arguments.keywords {
534        visitor.visit_keyword(keyword);
535    }
536}
537
538pub fn walk_parameters<V: Transformer + ?Sized>(visitor: &V, parameters: &mut Parameters) {
539    // Defaults are evaluated before annotations.
540    for arg in &mut parameters.posonlyargs {
541        if let Some(default) = &mut arg.default {
542            visitor.visit_expr(default);
543        }
544    }
545    for arg in &mut parameters.args {
546        if let Some(default) = &mut arg.default {
547            visitor.visit_expr(default);
548        }
549    }
550    for arg in &mut parameters.kwonlyargs {
551        if let Some(default) = &mut arg.default {
552            visitor.visit_expr(default);
553        }
554    }
555
556    for arg in &mut parameters.posonlyargs {
557        visitor.visit_parameter(&mut arg.parameter);
558    }
559    for arg in &mut parameters.args {
560        visitor.visit_parameter(&mut arg.parameter);
561    }
562    if let Some(arg) = &mut parameters.vararg {
563        visitor.visit_parameter(arg);
564    }
565    for arg in &mut parameters.kwonlyargs {
566        visitor.visit_parameter(&mut arg.parameter);
567    }
568    if let Some(arg) = &mut parameters.kwarg {
569        visitor.visit_parameter(arg);
570    }
571}
572
573pub fn walk_parameter<V: Transformer + ?Sized>(visitor: &V, parameter: &mut Parameter) {
574    if let Some(expr) = &mut parameter.annotation {
575        visitor.visit_annotation(expr);
576    }
577}
578
579pub fn walk_keyword<V: Transformer + ?Sized>(visitor: &V, keyword: &mut Keyword) {
580    visitor.visit_expr(&mut keyword.value);
581}
582
583pub fn walk_with_item<V: Transformer + ?Sized>(visitor: &V, with_item: &mut WithItem) {
584    visitor.visit_expr(&mut with_item.context_expr);
585    if let Some(expr) = &mut with_item.optional_vars {
586        visitor.visit_expr(expr);
587    }
588}
589
590pub fn walk_type_params<V: Transformer + ?Sized>(visitor: &V, type_params: &mut TypeParams) {
591    for type_param in &mut type_params.type_params {
592        visitor.visit_type_param(type_param);
593    }
594}
595
596pub fn walk_type_param<V: Transformer + ?Sized>(visitor: &V, type_param: &mut TypeParam) {
597    match type_param {
598        TypeParam::TypeVar(TypeParamTypeVar { bound, default, .. }) => {
599            if let Some(expr) = bound {
600                visitor.visit_expr(expr);
601            }
602            if let Some(expr) = default {
603                visitor.visit_expr(expr);
604            }
605        }
606        TypeParam::TypeVarTuple(TypeParamTypeVarTuple { default, .. }) => {
607            if let Some(expr) = default {
608                visitor.visit_expr(expr);
609            }
610        }
611        TypeParam::ParamSpec(TypeParamParamSpec { default, .. }) => {
612            if let Some(expr) = default {
613                visitor.visit_expr(expr);
614            }
615        }
616    }
617}
618
619pub fn walk_match_case<V: Transformer + ?Sized>(visitor: &V, match_case: &mut MatchCase) {
620    visitor.visit_pattern(&mut match_case.pattern);
621    if let Some(expr) = &mut match_case.guard {
622        visitor.visit_expr(expr);
623    }
624    visitor.visit_body(&mut match_case.body);
625}
626
627pub fn walk_pattern<V: Transformer + ?Sized>(visitor: &V, pattern: &mut Pattern) {
628    match pattern {
629        Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => {
630            visitor.visit_expr(value);
631        }
632        Pattern::MatchSingleton(_) => {}
633        Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => {
634            for pattern in patterns {
635                visitor.visit_pattern(pattern);
636            }
637        }
638        Pattern::MatchMapping(ast::PatternMatchMapping { keys, patterns, .. }) => {
639            for expr in keys {
640                visitor.visit_expr(expr);
641            }
642            for pattern in patterns {
643                visitor.visit_pattern(pattern);
644            }
645        }
646        Pattern::MatchClass(ast::PatternMatchClass { cls, arguments, .. }) => {
647            visitor.visit_expr(cls);
648            visitor.visit_pattern_arguments(arguments);
649        }
650        Pattern::MatchStar(_) => {}
651        Pattern::MatchAs(ast::PatternMatchAs { pattern, .. }) => {
652            if let Some(pattern) = pattern {
653                visitor.visit_pattern(pattern);
654            }
655        }
656        Pattern::MatchOr(ast::PatternMatchOr { patterns, .. }) => {
657            for pattern in patterns {
658                visitor.visit_pattern(pattern);
659            }
660        }
661    }
662}
663
664pub fn walk_pattern_arguments<V: Transformer + ?Sized>(
665    visitor: &V,
666    pattern_arguments: &mut PatternArguments,
667) {
668    for pattern in &mut pattern_arguments.patterns {
669        visitor.visit_pattern(pattern);
670    }
671    for keyword in &mut pattern_arguments.keywords {
672        visitor.visit_pattern_keyword(keyword);
673    }
674}
675
676pub fn walk_pattern_keyword<V: Transformer + ?Sized>(
677    visitor: &V,
678    pattern_keyword: &mut PatternKeyword,
679) {
680    visitor.visit_pattern(&mut pattern_keyword.pattern);
681}
682
683pub fn walk_f_string<V: Transformer + ?Sized>(visitor: &V, f_string: &mut FString) {
684    for element in &mut f_string.elements {
685        visitor.visit_interpolated_string_element(element);
686    }
687}
688
689pub fn walk_interpolated_string_element<V: Transformer + ?Sized>(
690    visitor: &V,
691    interpolated_string_element: &mut InterpolatedStringElement,
692) {
693    if let ast::InterpolatedStringElement::Interpolation(ast::InterpolatedElement {
694        expression,
695        format_spec,
696        ..
697    }) = interpolated_string_element
698    {
699        visitor.visit_expr(expression);
700        if let Some(format_spec) = format_spec {
701            for spec_element in &mut format_spec.elements {
702                visitor.visit_interpolated_string_element(spec_element);
703            }
704        }
705    }
706}
707
708pub fn walk_t_string<V: Transformer + ?Sized>(visitor: &V, t_string: &mut TString) {
709    for element in &mut t_string.elements {
710        visitor.visit_interpolated_string_element(element);
711    }
712}
713
714pub fn walk_expr_context<V: Transformer + ?Sized>(_visitor: &V, _expr_context: &mut ExprContext) {}
715
716pub fn walk_bool_op<V: Transformer + ?Sized>(_visitor: &V, _bool_op: &mut BoolOp) {}
717
718pub fn walk_operator<V: Transformer + ?Sized>(_visitor: &V, _operator: &mut Operator) {}
719
720pub fn walk_unary_op<V: Transformer + ?Sized>(_visitor: &V, _unary_op: &mut UnaryOp) {}
721
722pub fn walk_cmp_op<V: Transformer + ?Sized>(_visitor: &V, _cmp_op: &mut CmpOp) {}
723
724pub fn walk_alias<V: Transformer + ?Sized>(_visitor: &V, _alias: &mut Alias) {}
725
726pub fn walk_string_literal<V: Transformer + ?Sized>(
727    _visitor: &V,
728    _string_literal: &mut StringLiteral,
729) {
730}
731
732pub fn walk_bytes_literal<V: Transformer + ?Sized>(
733    _visitor: &V,
734    _bytes_literal: &mut BytesLiteral,
735) {
736}