Skip to main content

ruff_python_ast/
visitor.rs

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