diff --git a/crates/ruff_python_ast/src/node.rs b/crates/ruff_python_ast/src/node.rs index 2bc1642af6..4f6798d07e 100644 --- a/crates/ruff_python_ast/src/node.rs +++ b/crates/ruff_python_ast/src/node.rs @@ -1,3 +1,4 @@ +use crate::visitor::preorder::PreorderVisitor; use crate::{ self as ast, Alias, Arguments, Comprehension, Decorator, ExceptHandler, Expr, Keyword, MatchCase, Mod, Parameter, ParameterWithDefault, Parameters, Pattern, Ranged, Stmt, TypeParam, @@ -17,6 +18,10 @@ pub trait AstNode: Ranged { /// Consumes `self` and returns its [`AnyNode`] representation. fn into_any_node(self) -> AnyNode; + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized; } #[derive(Clone, Debug, is_macro::Is, PartialEq)] @@ -672,7 +677,16 @@ impl AstNode for ast::ModModule { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ModModule { body, range: _ } = self; + visitor.visit_body(body); + } } + impl AstNode for ast::ModExpression { fn cast(kind: AnyNode) -> Option where @@ -700,6 +714,14 @@ impl AstNode for ast::ModExpression { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ModExpression { body, range: _ } = self; + visitor.visit_expr(body); + } } impl AstNode for ast::StmtFunctionDef { fn cast(kind: AnyNode) -> Option @@ -728,6 +750,36 @@ impl AstNode for ast::StmtFunctionDef { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtFunctionDef { + parameters, + body, + decorator_list, + returns, + type_params, + .. + } = self; + + for decorator in decorator_list { + visitor.visit_decorator(decorator); + } + + if let Some(type_params) = type_params { + visitor.visit_type_params(type_params); + } + + visitor.visit_parameters(parameters); + + for expr in returns { + visitor.visit_annotation(expr); + } + + visitor.visit_body(body); + } } impl AstNode for ast::StmtClassDef { fn cast(kind: AnyNode) -> Option @@ -756,6 +808,33 @@ impl AstNode for ast::StmtClassDef { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtClassDef { + arguments, + body, + decorator_list, + type_params, + .. + } = self; + + for decorator in decorator_list { + visitor.visit_decorator(decorator); + } + + if let Some(type_params) = type_params { + visitor.visit_type_params(type_params); + } + + if let Some(arguments) = arguments { + visitor.visit_arguments(arguments); + } + + visitor.visit_body(body); + } } impl AstNode for ast::StmtReturn { fn cast(kind: AnyNode) -> Option @@ -784,6 +863,16 @@ impl AstNode for ast::StmtReturn { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtReturn { value, range: _ } = self; + if let Some(expr) = value { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::StmtDelete { fn cast(kind: AnyNode) -> Option @@ -812,6 +901,16 @@ impl AstNode for ast::StmtDelete { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtDelete { targets, range: _ } = self; + for expr in targets { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::StmtTypeAlias { fn cast(kind: AnyNode) -> Option @@ -840,6 +939,24 @@ impl AstNode for ast::StmtTypeAlias { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtTypeAlias { + range: _, + name, + type_params, + value, + } = self; + + visitor.visit_expr(name); + if let Some(type_params) = type_params { + visitor.visit_type_params(type_params); + } + visitor.visit_expr(value); + } } impl AstNode for ast::StmtAssign { fn cast(kind: AnyNode) -> Option @@ -868,6 +985,23 @@ impl AstNode for ast::StmtAssign { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtAssign { + targets, + value, + range: _, + } = self; + + for expr in targets { + visitor.visit_expr(expr); + } + + visitor.visit_expr(value); + } } impl AstNode for ast::StmtAugAssign { fn cast(kind: AnyNode) -> Option @@ -896,6 +1030,22 @@ impl AstNode for ast::StmtAugAssign { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtAugAssign { + target, + op, + value, + range: _, + } = self; + + visitor.visit_expr(target); + visitor.visit_operator(op); + visitor.visit_expr(value); + } } impl AstNode for ast::StmtAnnAssign { fn cast(kind: AnyNode) -> Option @@ -924,6 +1074,25 @@ impl AstNode for ast::StmtAnnAssign { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtAnnAssign { + target, + annotation, + value, + range: _, + simple: _, + } = self; + + visitor.visit_expr(target); + visitor.visit_annotation(annotation); + if let Some(expr) = value { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::StmtFor { fn cast(kind: AnyNode) -> Option @@ -952,6 +1121,24 @@ impl AstNode for ast::StmtFor { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtFor { + target, + iter, + body, + orelse, + .. + } = self; + + visitor.visit_expr(target); + visitor.visit_expr(iter); + visitor.visit_body(body); + visitor.visit_body(orelse); + } } impl AstNode for ast::StmtWhile { fn cast(kind: AnyNode) -> Option @@ -980,6 +1167,22 @@ impl AstNode for ast::StmtWhile { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtWhile { + test, + body, + orelse, + range: _, + } = self; + + visitor.visit_expr(test); + visitor.visit_body(body); + visitor.visit_body(orelse); + } } impl AstNode for ast::StmtIf { fn cast(kind: AnyNode) -> Option @@ -1008,6 +1211,24 @@ impl AstNode for ast::StmtIf { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtIf { + test, + body, + elif_else_clauses, + range: _, + } = self; + + visitor.visit_expr(test); + visitor.visit_body(body); + for clause in elif_else_clauses { + visitor.visit_elif_else_clause(clause); + } + } } impl AstNode for ast::ElifElseClause { fn cast(kind: AnyNode) -> Option @@ -1036,6 +1257,21 @@ impl AstNode for ast::ElifElseClause { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ElifElseClause { + range: _, + test, + body, + } = self; + if let Some(test) = test { + visitor.visit_expr(test); + } + visitor.visit_body(body); + } } impl AstNode for ast::StmtWith { fn cast(kind: AnyNode) -> Option @@ -1064,6 +1300,23 @@ impl AstNode for ast::StmtWith { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtWith { + items, + body, + is_async: _, + range: _, + } = self; + + for with_item in items { + visitor.visit_with_item(with_item); + } + visitor.visit_body(body); + } } impl AstNode for ast::StmtMatch { fn cast(kind: AnyNode) -> Option @@ -1092,6 +1345,22 @@ impl AstNode for ast::StmtMatch { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtMatch { + subject, + cases, + range: _, + } = self; + + visitor.visit_expr(subject); + for match_case in cases { + visitor.visit_match_case(match_case); + } + } } impl AstNode for ast::StmtRaise { fn cast(kind: AnyNode) -> Option @@ -1120,6 +1389,24 @@ impl AstNode for ast::StmtRaise { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtRaise { + exc, + cause, + range: _, + } = self; + + if let Some(expr) = exc { + visitor.visit_expr(expr); + }; + if let Some(expr) = cause { + visitor.visit_expr(expr); + }; + } } impl AstNode for ast::StmtTry { fn cast(kind: AnyNode) -> Option @@ -1148,6 +1435,26 @@ impl AstNode for ast::StmtTry { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtTry { + body, + handlers, + orelse, + finalbody, + range: _, + } = self; + + visitor.visit_body(body); + for except_handler in handlers { + visitor.visit_except_handler(except_handler); + } + visitor.visit_body(orelse); + visitor.visit_body(finalbody); + } } impl AstNode for ast::StmtTryStar { fn cast(kind: AnyNode) -> Option @@ -1176,6 +1483,26 @@ impl AstNode for ast::StmtTryStar { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtTryStar { + body, + handlers, + orelse, + finalbody, + range: _, + } = self; + + visitor.visit_body(body); + for except_handler in handlers { + visitor.visit_except_handler(except_handler); + } + visitor.visit_body(orelse); + visitor.visit_body(finalbody); + } } impl AstNode for ast::StmtAssert { fn cast(kind: AnyNode) -> Option @@ -1204,6 +1531,21 @@ impl AstNode for ast::StmtAssert { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtAssert { + test, + msg, + range: _, + } = self; + visitor.visit_expr(test); + if let Some(expr) = msg { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::StmtImport { fn cast(kind: AnyNode) -> Option @@ -1232,6 +1574,17 @@ impl AstNode for ast::StmtImport { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtImport { names, range: _ } = self; + + for alias in names { + visitor.visit_alias(alias); + } + } } impl AstNode for ast::StmtImportFrom { fn cast(kind: AnyNode) -> Option @@ -1260,6 +1613,22 @@ impl AstNode for ast::StmtImportFrom { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtImportFrom { + range: _, + module: _, + names, + level: _, + } = self; + + for alias in names { + visitor.visit_alias(alias); + } + } } impl AstNode for ast::StmtGlobal { fn cast(kind: AnyNode) -> Option @@ -1288,6 +1657,13 @@ impl AstNode for ast::StmtGlobal { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } impl AstNode for ast::StmtNonlocal { fn cast(kind: AnyNode) -> Option @@ -1316,6 +1692,13 @@ impl AstNode for ast::StmtNonlocal { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } impl AstNode for ast::StmtExpr { fn cast(kind: AnyNode) -> Option @@ -1344,6 +1727,15 @@ impl AstNode for ast::StmtExpr { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::StmtExpr { value, range: _ } = self; + + visitor.visit_expr(value); + } } impl AstNode for ast::StmtPass { fn cast(kind: AnyNode) -> Option @@ -1372,6 +1764,13 @@ impl AstNode for ast::StmtPass { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } impl AstNode for ast::StmtBreak { fn cast(kind: AnyNode) -> Option @@ -1400,6 +1799,13 @@ impl AstNode for ast::StmtBreak { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } impl AstNode for ast::StmtContinue { fn cast(kind: AnyNode) -> Option @@ -1428,6 +1834,13 @@ impl AstNode for ast::StmtContinue { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } impl AstNode for ast::StmtIpyEscapeCommand { fn cast(kind: AnyNode) -> Option @@ -1456,6 +1869,13 @@ impl AstNode for ast::StmtIpyEscapeCommand { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + } } impl AstNode for ast::ExprBoolOp { fn cast(kind: AnyNode) -> Option @@ -1484,6 +1904,29 @@ impl AstNode for ast::ExprBoolOp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprBoolOp { + op, + values, + range: _, + } = self; + match values.as_slice() { + [left, rest @ ..] => { + visitor.visit_expr(left); + visitor.visit_bool_op(op); + for expr in rest { + visitor.visit_expr(expr); + } + } + [] => { + visitor.visit_bool_op(op); + } + } + } } impl AstNode for ast::ExprNamedExpr { fn cast(kind: AnyNode) -> Option @@ -1512,6 +1955,19 @@ impl AstNode for ast::ExprNamedExpr { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprNamedExpr { + target, + value, + range: _, + } = self; + visitor.visit_expr(target); + visitor.visit_expr(value); + } } impl AstNode for ast::ExprBinOp { fn cast(kind: AnyNode) -> Option @@ -1540,6 +1996,21 @@ impl AstNode for ast::ExprBinOp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprBinOp { + left, + op, + right, + range: _, + } = self; + visitor.visit_expr(left); + visitor.visit_operator(op); + visitor.visit_expr(right); + } } impl AstNode for ast::ExprUnaryOp { fn cast(kind: AnyNode) -> Option @@ -1568,6 +2039,20 @@ impl AstNode for ast::ExprUnaryOp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprUnaryOp { + op, + operand, + range: _, + } = self; + + visitor.visit_unary_op(op); + visitor.visit_expr(operand); + } } impl AstNode for ast::ExprLambda { fn cast(kind: AnyNode) -> Option @@ -1596,6 +2081,20 @@ impl AstNode for ast::ExprLambda { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprLambda { + parameters, + body, + range: _, + } = self; + + visitor.visit_parameters(parameters); + visitor.visit_expr(body); + } } impl AstNode for ast::ExprIfExp { fn cast(kind: AnyNode) -> Option @@ -1624,6 +2123,23 @@ impl AstNode for ast::ExprIfExp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprIfExp { + test, + body, + orelse, + range: _, + } = self; + + // `body if test else orelse` + visitor.visit_expr(body); + visitor.visit_expr(test); + visitor.visit_expr(orelse); + } } impl AstNode for ast::ExprDict { fn cast(kind: AnyNode) -> Option @@ -1652,6 +2168,24 @@ impl AstNode for ast::ExprDict { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprDict { + keys, + values, + range: _, + } = self; + + for (key, value) in keys.iter().zip(values) { + if let Some(key) = key { + visitor.visit_expr(key); + } + visitor.visit_expr(value); + } + } } impl AstNode for ast::ExprSet { fn cast(kind: AnyNode) -> Option @@ -1680,6 +2214,17 @@ impl AstNode for ast::ExprSet { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprSet { elts, range: _ } = self; + + for expr in elts { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::ExprListComp { fn cast(kind: AnyNode) -> Option @@ -1708,6 +2253,22 @@ impl AstNode for ast::ExprListComp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprListComp { + elt, + generators, + range: _, + } = self; + + visitor.visit_expr(elt); + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } } impl AstNode for ast::ExprSetComp { fn cast(kind: AnyNode) -> Option @@ -1736,6 +2297,22 @@ impl AstNode for ast::ExprSetComp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprSetComp { + elt, + generators, + range: _, + } = self; + + visitor.visit_expr(elt); + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } } impl AstNode for ast::ExprDictComp { fn cast(kind: AnyNode) -> Option @@ -1764,6 +2341,25 @@ impl AstNode for ast::ExprDictComp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprDictComp { + key, + value, + generators, + range: _, + } = self; + + visitor.visit_expr(key); + visitor.visit_expr(value); + + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } } impl AstNode for ast::ExprGeneratorExp { fn cast(kind: AnyNode) -> Option @@ -1792,6 +2388,21 @@ impl AstNode for ast::ExprGeneratorExp { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprGeneratorExp { + elt, + generators, + range: _, + } = self; + visitor.visit_expr(elt); + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } } impl AstNode for ast::ExprAwait { fn cast(kind: AnyNode) -> Option @@ -1820,6 +2431,14 @@ impl AstNode for ast::ExprAwait { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprAwait { value, range: _ } = self; + visitor.visit_expr(value); + } } impl AstNode for ast::ExprYield { fn cast(kind: AnyNode) -> Option @@ -1848,6 +2467,16 @@ impl AstNode for ast::ExprYield { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprYield { value, range: _ } = self; + if let Some(expr) = value { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::ExprYieldFrom { fn cast(kind: AnyNode) -> Option @@ -1876,6 +2505,14 @@ impl AstNode for ast::ExprYieldFrom { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprYieldFrom { value, range: _ } = self; + visitor.visit_expr(value); + } } impl AstNode for ast::ExprCompare { fn cast(kind: AnyNode) -> Option @@ -1904,6 +2541,25 @@ impl AstNode for ast::ExprCompare { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprCompare { + left, + ops, + comparators, + range: _, + } = self; + + visitor.visit_expr(left); + + for (op, comparator) in ops.iter().zip(comparators) { + visitor.visit_cmp_op(op); + visitor.visit_expr(comparator); + } + } } impl AstNode for ast::ExprCall { fn cast(kind: AnyNode) -> Option @@ -1932,6 +2588,19 @@ impl AstNode for ast::ExprCall { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprCall { + func, + arguments, + range: _, + } = self; + visitor.visit_expr(func); + visitor.visit_arguments(arguments); + } } impl AstNode for ast::ExprFormattedValue { fn cast(kind: AnyNode) -> Option @@ -1960,6 +2629,20 @@ impl AstNode for ast::ExprFormattedValue { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprFormattedValue { + value, format_spec, .. + } = self; + visitor.visit_expr(value); + + if let Some(expr) = format_spec { + visitor.visit_format_spec(expr); + } + } } impl AstNode for ast::ExprFString { fn cast(kind: AnyNode) -> Option @@ -1988,6 +2671,17 @@ impl AstNode for ast::ExprFString { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprFString { values, range: _ } = self; + + for expr in values { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::ExprConstant { fn cast(kind: AnyNode) -> Option @@ -2016,6 +2710,18 @@ impl AstNode for ast::ExprConstant { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprConstant { + value, + range: _, + kind: _, + } = self; + visitor.visit_constant(value); + } } impl AstNode for ast::ExprAttribute { fn cast(kind: AnyNode) -> Option @@ -2044,6 +2750,20 @@ impl AstNode for ast::ExprAttribute { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprAttribute { + value, + attr: _, + ctx: _, + range: _, + } = self; + + visitor.visit_expr(value); + } } impl AstNode for ast::ExprSubscript { fn cast(kind: AnyNode) -> Option @@ -2072,6 +2792,20 @@ impl AstNode for ast::ExprSubscript { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprSubscript { + value, + slice, + ctx: _, + range: _, + } = self; + visitor.visit_expr(value); + visitor.visit_expr(slice); + } } impl AstNode for ast::ExprStarred { fn cast(kind: AnyNode) -> Option @@ -2100,6 +2834,19 @@ impl AstNode for ast::ExprStarred { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprStarred { + value, + ctx: _, + range: _, + } = self; + + visitor.visit_expr(value); + } } impl AstNode for ast::ExprName { fn cast(kind: AnyNode) -> Option @@ -2128,6 +2875,18 @@ impl AstNode for ast::ExprName { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprName { + id: _, + ctx: _, + range: _, + } = self; + } } impl AstNode for ast::ExprList { fn cast(kind: AnyNode) -> Option @@ -2156,6 +2915,21 @@ impl AstNode for ast::ExprList { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprList { + elts, + ctx: _, + range: _, + } = self; + + for expr in elts { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::ExprTuple { fn cast(kind: AnyNode) -> Option @@ -2184,6 +2958,21 @@ impl AstNode for ast::ExprTuple { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprTuple { + elts, + ctx: _, + range: _, + } = self; + + for expr in elts { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::ExprSlice { fn cast(kind: AnyNode) -> Option @@ -2212,6 +3001,27 @@ impl AstNode for ast::ExprSlice { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprSlice { + lower, + upper, + step, + range: _, + } = self; + + if let Some(expr) = lower { + visitor.visit_expr(expr); + } + if let Some(expr) = upper { + visitor.visit_expr(expr); + } + if let Some(expr) = step { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::ExprIpyEscapeCommand { fn cast(kind: AnyNode) -> Option @@ -2240,6 +3050,18 @@ impl AstNode for ast::ExprIpyEscapeCommand { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExprIpyEscapeCommand { + range: _, + kind: _, + value: _, + } = self; + } } impl AstNode for ast::ExceptHandlerExceptHandler { fn cast(kind: AnyNode) -> Option @@ -2268,6 +3090,22 @@ impl AstNode for ast::ExceptHandlerExceptHandler { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ExceptHandlerExceptHandler { + range: _, + type_, + name: _, + body, + } = self; + if let Some(expr) = type_ { + visitor.visit_expr(expr); + } + visitor.visit_body(body); + } } impl AstNode for ast::PatternMatchValue { fn cast(kind: AnyNode) -> Option @@ -2296,6 +3134,14 @@ impl AstNode for ast::PatternMatchValue { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchValue { value, range: _ } = self; + visitor.visit_expr(value); + } } impl AstNode for ast::PatternMatchSingleton { fn cast(kind: AnyNode) -> Option @@ -2324,6 +3170,14 @@ impl AstNode for ast::PatternMatchSingleton { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchSingleton { value, range: _ } = self; + visitor.visit_constant(value); + } } impl AstNode for ast::PatternMatchSequence { fn cast(kind: AnyNode) -> Option @@ -2352,6 +3206,16 @@ impl AstNode for ast::PatternMatchSequence { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchSequence { patterns, range: _ } = self; + for pattern in patterns { + visitor.visit_pattern(pattern); + } + } } impl AstNode for ast::PatternMatchMapping { fn cast(kind: AnyNode) -> Option @@ -2380,6 +3244,22 @@ impl AstNode for ast::PatternMatchMapping { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchMapping { + keys, + patterns, + range: _, + rest: _, + } = self; + for (key, pattern) in keys.iter().zip(patterns) { + visitor.visit_expr(key); + visitor.visit_pattern(pattern); + } + } } impl AstNode for ast::PatternMatchClass { fn cast(kind: AnyNode) -> Option @@ -2408,6 +3288,27 @@ impl AstNode for ast::PatternMatchClass { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchClass { + cls, + patterns, + kwd_attrs: _, + kwd_patterns, + range: _, + } = self; + visitor.visit_expr(cls); + for pattern in patterns { + visitor.visit_pattern(pattern); + } + + for pattern in kwd_patterns { + visitor.visit_pattern(pattern); + } + } } impl AstNode for ast::PatternMatchStar { fn cast(kind: AnyNode) -> Option @@ -2436,6 +3337,14 @@ impl AstNode for ast::PatternMatchStar { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchStar { range: _, name: _ } = self; + } } impl AstNode for ast::PatternMatchAs { fn cast(kind: AnyNode) -> Option @@ -2464,6 +3373,20 @@ impl AstNode for ast::PatternMatchAs { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchAs { + pattern, + range: _, + name: _, + } = self; + if let Some(pattern) = pattern { + visitor.visit_pattern(pattern); + } + } } impl AstNode for ast::PatternMatchOr { fn cast(kind: AnyNode) -> Option @@ -2492,6 +3415,16 @@ impl AstNode for ast::PatternMatchOr { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::PatternMatchOr { patterns, range: _ } = self; + for pattern in patterns { + visitor.visit_pattern(pattern); + } + } } impl AstNode for Comprehension { @@ -2521,6 +3454,25 @@ impl AstNode for Comprehension { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Comprehension { + range: _, + target, + iter, + ifs, + is_async: _, + } = self; + visitor.visit_expr(target); + visitor.visit_expr(iter); + + for expr in ifs { + visitor.visit_expr(expr); + } + } } impl AstNode for Arguments { fn cast(kind: AnyNode) -> Option @@ -2549,6 +3501,25 @@ impl AstNode for Arguments { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Arguments { + range: _, + args, + keywords, + } = self; + + for arg in args { + visitor.visit_expr(arg); + } + + for keyword in keywords { + visitor.visit_keyword(keyword); + } + } } impl AstNode for Parameters { fn cast(kind: AnyNode) -> Option @@ -2577,6 +3548,35 @@ impl AstNode for Parameters { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Parameters { + range: _, + posonlyargs, + args, + vararg, + kwonlyargs, + kwarg, + } = self; + for arg in posonlyargs.iter().chain(args) { + visitor.visit_parameter_with_default(arg); + } + + if let Some(arg) = vararg { + visitor.visit_parameter(arg); + } + + for arg in kwonlyargs { + visitor.visit_parameter_with_default(arg); + } + + if let Some(arg) = kwarg { + visitor.visit_parameter(arg); + } + } } impl AstNode for Parameter { fn cast(kind: AnyNode) -> Option @@ -2605,6 +3605,21 @@ impl AstNode for Parameter { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Parameter { + range: _, + name: _, + annotation, + } = self; + + if let Some(expr) = annotation { + visitor.visit_annotation(expr); + } + } } impl AstNode for ParameterWithDefault { fn cast(kind: AnyNode) -> Option @@ -2633,6 +3648,21 @@ impl AstNode for ParameterWithDefault { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::ParameterWithDefault { + range: _, + parameter, + default, + } = self; + visitor.visit_parameter(parameter); + if let Some(expr) = default { + visitor.visit_expr(expr); + } + } } impl AstNode for Keyword { fn cast(kind: AnyNode) -> Option @@ -2661,6 +3691,19 @@ impl AstNode for Keyword { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Keyword { + range: _, + arg: _, + value, + } = self; + + visitor.visit_expr(value); + } } impl AstNode for Alias { fn cast(kind: AnyNode) -> Option @@ -2689,6 +3732,18 @@ impl AstNode for Alias { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Alias { + range: _, + name: _, + asname: _, + } = self; + } } impl AstNode for WithItem { fn cast(kind: AnyNode) -> Option @@ -2717,6 +3772,23 @@ impl AstNode for WithItem { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::WithItem { + range: _, + context_expr, + optional_vars, + } = self; + + visitor.visit_expr(context_expr); + + if let Some(expr) = optional_vars { + visitor.visit_expr(expr); + } + } } impl AstNode for MatchCase { fn cast(kind: AnyNode) -> Option @@ -2745,6 +3817,24 @@ impl AstNode for MatchCase { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::MatchCase { + range: _, + pattern, + guard, + body, + } = self; + + visitor.visit_pattern(pattern); + if let Some(expr) = guard { + visitor.visit_expr(expr); + } + visitor.visit_body(body); + } } impl AstNode for Decorator { @@ -2774,6 +3864,18 @@ impl AstNode for Decorator { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::Decorator { + range: _, + expression, + } = self; + + visitor.visit_expr(expression); + } } impl AstNode for ast::TypeParams { fn cast(kind: AnyNode) -> Option @@ -2802,6 +3904,20 @@ impl AstNode for ast::TypeParams { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::TypeParams { + range: _, + type_params, + } = self; + + for type_param in type_params { + visitor.visit_type_param(type_param); + } + } } impl AstNode for ast::TypeParamTypeVar { fn cast(kind: AnyNode) -> Option @@ -2830,6 +3946,21 @@ impl AstNode for ast::TypeParamTypeVar { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::TypeParamTypeVar { + bound, + name: _, + range: _, + } = self; + + if let Some(expr) = bound { + visitor.visit_expr(expr); + } + } } impl AstNode for ast::TypeParamTypeVarTuple { fn cast(kind: AnyNode) -> Option @@ -2858,6 +3989,14 @@ impl AstNode for ast::TypeParamTypeVarTuple { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::TypeParamTypeVarTuple { range: _, name: _ } = self; + } } impl AstNode for ast::TypeParamParamSpec { fn cast(kind: AnyNode) -> Option @@ -2886,6 +4025,14 @@ impl AstNode for ast::TypeParamParamSpec { fn into_any_node(self) -> AnyNode { AnyNode::from(self) } + + #[inline] + fn visit_preorder<'a, V>(&'a self, _visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + let ast::TypeParamParamSpec { range: _, name: _ } = self; + } } impl From for AnyNode { fn from(stmt: Stmt) -> Self { @@ -4259,6 +5406,94 @@ impl AnyNodeRef<'_> { AnyNodeRef::ExceptHandlerExceptHandler(_) | AnyNodeRef::ElifElseClause(_) ) } + + pub fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + where + V: PreorderVisitor<'a> + ?Sized, + { + match self { + AnyNodeRef::ModModule(node) => node.visit_preorder(visitor), + AnyNodeRef::ModExpression(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtFunctionDef(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtClassDef(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtReturn(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtDelete(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtTypeAlias(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtAssign(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtAugAssign(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtAnnAssign(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtFor(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtWhile(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtIf(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtWith(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtMatch(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtRaise(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtTry(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtTryStar(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtAssert(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtImport(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtImportFrom(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtGlobal(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtNonlocal(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtExpr(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtPass(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtBreak(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtContinue(node) => node.visit_preorder(visitor), + AnyNodeRef::StmtIpyEscapeCommand(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprBoolOp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprNamedExpr(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprBinOp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprUnaryOp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprLambda(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprIfExp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprDict(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprSet(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprListComp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprSetComp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprDictComp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprGeneratorExp(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprAwait(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprYield(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprYieldFrom(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprCompare(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprCall(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprFormattedValue(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprFString(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprConstant(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprAttribute(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprSubscript(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprStarred(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprName(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprList(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprTuple(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprSlice(node) => node.visit_preorder(visitor), + AnyNodeRef::ExprIpyEscapeCommand(node) => node.visit_preorder(visitor), + AnyNodeRef::ExceptHandlerExceptHandler(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchValue(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchSingleton(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchSequence(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchMapping(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchClass(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchStar(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchAs(node) => node.visit_preorder(visitor), + AnyNodeRef::PatternMatchOr(node) => node.visit_preorder(visitor), + AnyNodeRef::Comprehension(node) => node.visit_preorder(visitor), + AnyNodeRef::Arguments(node) => node.visit_preorder(visitor), + AnyNodeRef::Parameters(node) => node.visit_preorder(visitor), + AnyNodeRef::Parameter(node) => node.visit_preorder(visitor), + AnyNodeRef::ParameterWithDefault(node) => node.visit_preorder(visitor), + AnyNodeRef::Keyword(node) => node.visit_preorder(visitor), + AnyNodeRef::Alias(node) => node.visit_preorder(visitor), + AnyNodeRef::WithItem(node) => node.visit_preorder(visitor), + AnyNodeRef::MatchCase(node) => node.visit_preorder(visitor), + AnyNodeRef::Decorator(node) => node.visit_preorder(visitor), + AnyNodeRef::TypeParams(node) => node.visit_preorder(visitor), + AnyNodeRef::TypeParamTypeVar(node) => node.visit_preorder(visitor), + AnyNodeRef::TypeParamTypeVarTuple(node) => node.visit_preorder(visitor), + AnyNodeRef::TypeParamParamSpec(node) => node.visit_preorder(visitor), + AnyNodeRef::ElifElseClause(node) => node.visit_preorder(visitor), + } + } } impl<'a> From<&'a ast::ModModule> for AnyNodeRef<'a> { diff --git a/crates/ruff_python_ast/src/visitor/preorder.rs b/crates/ruff_python_ast/src/visitor/preorder.rs index b96b5228b1..229f111a57 100644 --- a/crates/ruff_python_ast/src/visitor/preorder.rs +++ b/crates/ruff_python_ast/src/visitor/preorder.rs @@ -1,9 +1,8 @@ -use crate::node::AnyNodeRef; +use crate::node::{AnyNodeRef, AstNode}; use crate::{ - self as ast, Alias, Arguments, BoolOp, CmpOp, Comprehension, Constant, Decorator, - ElifElseClause, ExceptHandler, Expr, Keyword, MatchCase, Mod, Operator, Parameter, - ParameterWithDefault, Parameters, Pattern, Stmt, TypeParam, TypeParamTypeVar, TypeParams, - UnaryOp, WithItem, + Alias, Arguments, BoolOp, CmpOp, Comprehension, Constant, Decorator, ElifElseClause, + ExceptHandler, Expr, Keyword, MatchCase, Mod, Operator, Parameter, ParameterWithDefault, + Parameters, Pattern, Stmt, TypeParam, TypeParams, UnaryOp, WithItem, }; /// Visitor that traverses all nodes recursively in pre-order. @@ -152,10 +151,8 @@ where let node = AnyNodeRef::from(module); if visitor.enter_node(node).is_traverse() { match module { - Mod::Module(ast::ModModule { body, range: _ }) => { - visitor.visit_body(body); - } - Mod::Expression(ast::ModExpression { body, range: _ }) => visitor.visit_expr(body), + Mod::Module(module) => module.visit_preorder(visitor), + Mod::Expression(module) => module.visit_preorder(visitor), } } @@ -179,246 +176,32 @@ where if visitor.enter_node(node).is_traverse() { match stmt { - Stmt::Expr(ast::StmtExpr { value, range: _ }) => visitor.visit_expr(value), - - Stmt::FunctionDef(ast::StmtFunctionDef { - parameters, - body, - decorator_list, - returns, - type_params, - .. - }) => { - for decorator in decorator_list { - visitor.visit_decorator(decorator); - } - - if let Some(type_params) = type_params { - visitor.visit_type_params(type_params); - } - - visitor.visit_parameters(parameters); - - for expr in returns { - visitor.visit_annotation(expr); - } - - visitor.visit_body(body); - } - - Stmt::ClassDef(ast::StmtClassDef { - arguments, - body, - decorator_list, - type_params, - .. - }) => { - for decorator in decorator_list { - visitor.visit_decorator(decorator); - } - - if let Some(type_params) = type_params { - visitor.visit_type_params(type_params); - } - - if let Some(arguments) = arguments { - visitor.visit_arguments(arguments); - } - - visitor.visit_body(body); - } - - Stmt::Return(ast::StmtReturn { value, range: _ }) => { - if let Some(expr) = value { - visitor.visit_expr(expr); - } - } - - Stmt::Delete(ast::StmtDelete { targets, range: _ }) => { - for expr in targets { - visitor.visit_expr(expr); - } - } - - Stmt::TypeAlias(ast::StmtTypeAlias { - range: _, - name, - type_params, - value, - }) => { - visitor.visit_expr(name); - if let Some(type_params) = type_params { - visitor.visit_type_params(type_params); - } - visitor.visit_expr(value); - } - - Stmt::Assign(ast::StmtAssign { - targets, - value, - range: _, - }) => { - for expr in targets { - visitor.visit_expr(expr); - } - - visitor.visit_expr(value); - } - - Stmt::AugAssign(ast::StmtAugAssign { - target, - op, - value, - range: _, - }) => { - visitor.visit_expr(target); - visitor.visit_operator(op); - visitor.visit_expr(value); - } - - Stmt::AnnAssign(ast::StmtAnnAssign { - target, - annotation, - value, - range: _, - simple: _, - }) => { - visitor.visit_expr(target); - visitor.visit_annotation(annotation); - if let Some(expr) = value { - visitor.visit_expr(expr); - } - } - - Stmt::For(ast::StmtFor { - target, - iter, - body, - orelse, - .. - }) => { - visitor.visit_expr(target); - visitor.visit_expr(iter); - visitor.visit_body(body); - visitor.visit_body(orelse); - } - - Stmt::While(ast::StmtWhile { - test, - body, - orelse, - range: _, - }) => { - visitor.visit_expr(test); - visitor.visit_body(body); - visitor.visit_body(orelse); - } - - Stmt::If(ast::StmtIf { - test, - body, - elif_else_clauses, - range: _, - }) => { - visitor.visit_expr(test); - visitor.visit_body(body); - for clause in elif_else_clauses { - visitor.visit_elif_else_clause(clause); - } - } - - Stmt::With(ast::StmtWith { - items, - body, - is_async: _, - range: _, - }) => { - for with_item in items { - visitor.visit_with_item(with_item); - } - visitor.visit_body(body); - } - - Stmt::Match(ast::StmtMatch { - subject, - cases, - range: _, - }) => { - visitor.visit_expr(subject); - for match_case in cases { - visitor.visit_match_case(match_case); - } - } - - Stmt::Raise(ast::StmtRaise { - exc, - cause, - range: _, - }) => { - if let Some(expr) = exc { - visitor.visit_expr(expr); - }; - if let Some(expr) = cause { - visitor.visit_expr(expr); - }; - } - - Stmt::Try(ast::StmtTry { - body, - handlers, - orelse, - finalbody, - range: _, - }) - | Stmt::TryStar(ast::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _, - }) => { - visitor.visit_body(body); - for except_handler in handlers { - visitor.visit_except_handler(except_handler); - } - visitor.visit_body(orelse); - visitor.visit_body(finalbody); - } - - Stmt::Assert(ast::StmtAssert { - test, - msg, - range: _, - }) => { - visitor.visit_expr(test); - if let Some(expr) = msg { - visitor.visit_expr(expr); - } - } - - Stmt::Import(ast::StmtImport { names, range: _ }) => { - for alias in names { - visitor.visit_alias(alias); - } - } - - Stmt::ImportFrom(ast::StmtImportFrom { - range: _, - module: _, - names, - level: _, - }) => { - for alias in names { - visitor.visit_alias(alias); - } - } - - Stmt::Pass(_) - | Stmt::Break(_) - | Stmt::Continue(_) - | Stmt::Global(_) - | Stmt::Nonlocal(_) - | Stmt::IpyEscapeCommand(_) => {} + Stmt::Expr(stmt) => stmt.visit_preorder(visitor), + Stmt::FunctionDef(stmt) => stmt.visit_preorder(visitor), + Stmt::ClassDef(stmt) => stmt.visit_preorder(visitor), + Stmt::Return(stmt) => stmt.visit_preorder(visitor), + Stmt::Delete(stmt) => stmt.visit_preorder(visitor), + Stmt::TypeAlias(stmt) => stmt.visit_preorder(visitor), + Stmt::Assign(stmt) => stmt.visit_preorder(visitor), + Stmt::AugAssign(stmt) => stmt.visit_preorder(visitor), + Stmt::AnnAssign(stmt) => stmt.visit_preorder(visitor), + Stmt::For(stmt) => stmt.visit_preorder(visitor), + Stmt::While(stmt) => stmt.visit_preorder(visitor), + Stmt::If(stmt) => stmt.visit_preorder(visitor), + Stmt::With(stmt) => stmt.visit_preorder(visitor), + Stmt::Match(stmt) => stmt.visit_preorder(visitor), + Stmt::Raise(stmt) => stmt.visit_preorder(visitor), + Stmt::Try(stmt) => stmt.visit_preorder(visitor), + Stmt::TryStar(stmt) => stmt.visit_preorder(visitor), + Stmt::Assert(stmt) => stmt.visit_preorder(visitor), + Stmt::Import(stmt) => stmt.visit_preorder(visitor), + Stmt::ImportFrom(stmt) => stmt.visit_preorder(visitor), + Stmt::Pass(stmt) => stmt.visit_preorder(visitor), + Stmt::Break(stmt) => stmt.visit_preorder(visitor), + Stmt::Continue(stmt) => stmt.visit_preorder(visitor), + Stmt::Global(stmt) => stmt.visit_preorder(visitor), + Stmt::Nonlocal(stmt) => stmt.visit_preorder(visitor), + Stmt::IpyEscapeCommand(stmt) => stmt.visit_preorder(visitor), } } @@ -452,7 +235,7 @@ where { let node = AnyNodeRef::from(decorator); if visitor.enter_node(node).is_traverse() { - visitor.visit_expr(&decorator.expression); + decorator.visit_preorder(visitor); } visitor.leave_node(node); @@ -465,261 +248,34 @@ where let node = AnyNodeRef::from(expr); if visitor.enter_node(node).is_traverse() { match expr { - Expr::BoolOp(ast::ExprBoolOp { - op, - values, - range: _, - }) => match values.as_slice() { - [left, rest @ ..] => { - visitor.visit_expr(left); - visitor.visit_bool_op(op); - for expr in rest { - visitor.visit_expr(expr); - } - } - [] => { - visitor.visit_bool_op(op); - } - }, - - Expr::NamedExpr(ast::ExprNamedExpr { - target, - value, - range: _, - }) => { - visitor.visit_expr(target); - visitor.visit_expr(value); - } - - Expr::BinOp(ast::ExprBinOp { - left, - op, - right, - range: _, - }) => { - visitor.visit_expr(left); - visitor.visit_operator(op); - visitor.visit_expr(right); - } - - Expr::UnaryOp(ast::ExprUnaryOp { - op, - operand, - range: _, - }) => { - visitor.visit_unary_op(op); - visitor.visit_expr(operand); - } - - Expr::Lambda(ast::ExprLambda { - parameters, - body, - range: _, - }) => { - visitor.visit_parameters(parameters); - visitor.visit_expr(body); - } - - Expr::IfExp(ast::ExprIfExp { - test, - body, - orelse, - range: _, - }) => { - // `body if test else orelse` - visitor.visit_expr(body); - visitor.visit_expr(test); - visitor.visit_expr(orelse); - } - - Expr::Dict(ast::ExprDict { - keys, - values, - range: _, - }) => { - for (key, value) in keys.iter().zip(values) { - if let Some(key) = key { - visitor.visit_expr(key); - } - visitor.visit_expr(value); - } - } - - Expr::Set(ast::ExprSet { elts, range: _ }) => { - for expr in elts { - visitor.visit_expr(expr); - } - } - - Expr::ListComp(ast::ExprListComp { - elt, - generators, - range: _, - }) => { - visitor.visit_expr(elt); - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::SetComp(ast::ExprSetComp { - elt, - generators, - range: _, - }) => { - visitor.visit_expr(elt); - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::DictComp(ast::ExprDictComp { - key, - value, - generators, - range: _, - }) => { - visitor.visit_expr(key); - visitor.visit_expr(value); - - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::GeneratorExp(ast::ExprGeneratorExp { - elt, - generators, - range: _, - }) => { - visitor.visit_expr(elt); - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::Await(ast::ExprAwait { value, range: _ }) - | Expr::YieldFrom(ast::ExprYieldFrom { value, range: _ }) => visitor.visit_expr(value), - - Expr::Yield(ast::ExprYield { value, range: _ }) => { - if let Some(expr) = value { - visitor.visit_expr(expr); - } - } - - Expr::Compare(ast::ExprCompare { - left, - ops, - comparators, - range: _, - }) => { - visitor.visit_expr(left); - - for (op, comparator) in ops.iter().zip(comparators) { - visitor.visit_cmp_op(op); - visitor.visit_expr(comparator); - } - } - - Expr::Call(ast::ExprCall { - func, - arguments, - range: _, - }) => { - visitor.visit_expr(func); - visitor.visit_arguments(arguments); - } - - Expr::FormattedValue(ast::ExprFormattedValue { - value, format_spec, .. - }) => { - visitor.visit_expr(value); - - if let Some(expr) = format_spec { - visitor.visit_format_spec(expr); - } - } - - Expr::FString(ast::ExprFString { values, range: _ }) => { - for expr in values { - visitor.visit_expr(expr); - } - } - - Expr::Constant(ast::ExprConstant { - value, - range: _, - kind: _, - }) => visitor.visit_constant(value), - - Expr::Attribute(ast::ExprAttribute { - value, - attr: _, - ctx: _, - range: _, - }) => { - visitor.visit_expr(value); - } - - Expr::Subscript(ast::ExprSubscript { - value, - slice, - ctx: _, - range: _, - }) => { - visitor.visit_expr(value); - visitor.visit_expr(slice); - } - Expr::Starred(ast::ExprStarred { - value, - ctx: _, - range: _, - }) => { - visitor.visit_expr(value); - } - - Expr::Name(ast::ExprName { - id: _, - ctx: _, - range: _, - }) => {} - - Expr::List(ast::ExprList { - elts, - ctx: _, - range: _, - }) => { - for expr in elts { - visitor.visit_expr(expr); - } - } - Expr::Tuple(ast::ExprTuple { - elts, - ctx: _, - range: _, - }) => { - for expr in elts { - visitor.visit_expr(expr); - } - } - - Expr::Slice(ast::ExprSlice { - lower, - upper, - step, - range: _, - }) => { - if let Some(expr) = lower { - visitor.visit_expr(expr); - } - if let Some(expr) = upper { - visitor.visit_expr(expr); - } - if let Some(expr) = step { - visitor.visit_expr(expr); - } - } - Expr::IpyEscapeCommand(_) => (), + Expr::BoolOp(expr) => expr.visit_preorder(visitor), + Expr::NamedExpr(expr) => expr.visit_preorder(visitor), + Expr::BinOp(expr) => expr.visit_preorder(visitor), + Expr::UnaryOp(expr) => expr.visit_preorder(visitor), + Expr::Lambda(expr) => expr.visit_preorder(visitor), + Expr::IfExp(expr) => expr.visit_preorder(visitor), + Expr::Dict(expr) => expr.visit_preorder(visitor), + Expr::Set(expr) => expr.visit_preorder(visitor), + Expr::ListComp(expr) => expr.visit_preorder(visitor), + Expr::SetComp(expr) => expr.visit_preorder(visitor), + Expr::DictComp(expr) => expr.visit_preorder(visitor), + Expr::GeneratorExp(expr) => expr.visit_preorder(visitor), + Expr::Await(expr) => expr.visit_preorder(visitor), + Expr::Yield(expr) => expr.visit_preorder(visitor), + Expr::YieldFrom(expr) => expr.visit_preorder(visitor), + Expr::Compare(expr) => expr.visit_preorder(visitor), + Expr::Call(expr) => expr.visit_preorder(visitor), + Expr::FormattedValue(expr) => expr.visit_preorder(visitor), + Expr::FString(expr) => expr.visit_preorder(visitor), + Expr::Constant(expr) => expr.visit_preorder(visitor), + Expr::Attribute(expr) => expr.visit_preorder(visitor), + Expr::Subscript(expr) => expr.visit_preorder(visitor), + Expr::Starred(expr) => expr.visit_preorder(visitor), + Expr::Name(expr) => expr.visit_preorder(visitor), + Expr::List(expr) => expr.visit_preorder(visitor), + Expr::Tuple(expr) => expr.visit_preorder(visitor), + Expr::Slice(expr) => expr.visit_preorder(visitor), + Expr::IpyEscapeCommand(expr) => expr.visit_preorder(visitor), } } @@ -732,12 +288,7 @@ where { let node = AnyNodeRef::from(comprehension); if visitor.enter_node(node).is_traverse() { - visitor.visit_expr(&comprehension.target); - visitor.visit_expr(&comprehension.iter); - - for expr in &comprehension.ifs { - visitor.visit_expr(expr); - } + comprehension.visit_preorder(visitor); } visitor.leave_node(node); @@ -749,10 +300,7 @@ where { let node = AnyNodeRef::from(elif_else_clause); if visitor.enter_node(node).is_traverse() { - if let Some(test) = &elif_else_clause.test { - visitor.visit_expr(test); - } - visitor.visit_body(&elif_else_clause.body); + elif_else_clause.visit_preorder(visitor); } visitor.leave_node(node); @@ -765,17 +313,7 @@ where let node = AnyNodeRef::from(except_handler); if visitor.enter_node(node).is_traverse() { match except_handler { - ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { - range: _, - type_, - name: _, - body, - }) => { - if let Some(expr) = type_ { - visitor.visit_expr(expr); - } - visitor.visit_body(body); - } + ExceptHandler::ExceptHandler(except_handler) => except_handler.visit_preorder(visitor), } } visitor.leave_node(node); @@ -799,13 +337,7 @@ where { let node = AnyNodeRef::from(arguments); if visitor.enter_node(node).is_traverse() { - for arg in &arguments.args { - visitor.visit_expr(arg); - } - - for keyword in &arguments.keywords { - visitor.visit_keyword(keyword); - } + arguments.visit_preorder(visitor); } visitor.leave_node(node); @@ -817,21 +349,7 @@ where { let node = AnyNodeRef::from(parameters); if visitor.enter_node(node).is_traverse() { - for arg in parameters.posonlyargs.iter().chain(¶meters.args) { - visitor.visit_parameter_with_default(arg); - } - - if let Some(arg) = ¶meters.vararg { - visitor.visit_parameter(arg); - } - - for arg in ¶meters.kwonlyargs { - visitor.visit_parameter_with_default(arg); - } - - if let Some(arg) = ¶meters.kwarg { - visitor.visit_parameter(arg); - } + parameters.visit_preorder(visitor); } visitor.leave_node(node); @@ -844,9 +362,7 @@ where let node = AnyNodeRef::from(parameter); if visitor.enter_node(node).is_traverse() { - if let Some(expr) = ¶meter.annotation { - visitor.visit_annotation(expr); - } + parameter.visit_preorder(visitor); } visitor.leave_node(node); } @@ -859,10 +375,7 @@ pub fn walk_parameter_with_default<'a, V>( { let node = AnyNodeRef::from(parameter_with_default); if visitor.enter_node(node).is_traverse() { - visitor.visit_parameter(¶meter_with_default.parameter); - if let Some(expr) = ¶meter_with_default.default { - visitor.visit_expr(expr); - } + parameter_with_default.visit_preorder(visitor); } visitor.leave_node(node); @@ -876,7 +389,7 @@ where let node = AnyNodeRef::from(keyword); if visitor.enter_node(node).is_traverse() { - visitor.visit_expr(&keyword.value); + keyword.visit_preorder(visitor); } visitor.leave_node(node); } @@ -887,11 +400,7 @@ where { let node = AnyNodeRef::from(with_item); if visitor.enter_node(node).is_traverse() { - visitor.visit_expr(&with_item.context_expr); - - if let Some(expr) = &with_item.optional_vars { - visitor.visit_expr(expr); - } + with_item.visit_preorder(visitor); } visitor.leave_node(node); } @@ -902,9 +411,7 @@ where { let node = AnyNodeRef::from(type_params); if visitor.enter_node(node).is_traverse() { - for type_param in &type_params.type_params { - visitor.visit_type_param(type_param); - } + type_params.visit_preorder(visitor); } visitor.leave_node(node); } @@ -916,16 +423,9 @@ where let node = AnyNodeRef::from(type_param); if visitor.enter_node(node).is_traverse() { match type_param { - TypeParam::TypeVar(TypeParamTypeVar { - bound, - name: _, - range: _, - }) => { - if let Some(expr) = bound { - visitor.visit_expr(expr); - } - } - TypeParam::TypeVarTuple(_) | TypeParam::ParamSpec(_) => {} + TypeParam::TypeVar(type_param) => type_param.visit_preorder(visitor), + TypeParam::TypeVarTuple(type_param) => type_param.visit_preorder(visitor), + TypeParam::ParamSpec(type_param) => type_param.visit_preorder(visitor), } } visitor.leave_node(node); @@ -937,11 +437,7 @@ where { let node = AnyNodeRef::from(match_case); if visitor.enter_node(node).is_traverse() { - visitor.visit_pattern(&match_case.pattern); - if let Some(expr) = &match_case.guard { - visitor.visit_expr(expr); - } - visitor.visit_body(&match_case.body); + match_case.visit_preorder(visitor); } visitor.leave_node(node); } @@ -953,66 +449,14 @@ where let node = AnyNodeRef::from(pattern); if visitor.enter_node(node).is_traverse() { match pattern { - Pattern::MatchValue(ast::PatternMatchValue { value, range: _ }) => { - visitor.visit_expr(value); - } - - Pattern::MatchSingleton(ast::PatternMatchSingleton { value, range: _ }) => { - visitor.visit_constant(value); - } - - Pattern::MatchSequence(ast::PatternMatchSequence { patterns, range: _ }) => { - for pattern in patterns { - visitor.visit_pattern(pattern); - } - } - - Pattern::MatchMapping(ast::PatternMatchMapping { - keys, - patterns, - range: _, - rest: _, - }) => { - for (key, pattern) in keys.iter().zip(patterns) { - visitor.visit_expr(key); - visitor.visit_pattern(pattern); - } - } - - Pattern::MatchClass(ast::PatternMatchClass { - cls, - patterns, - kwd_attrs: _, - kwd_patterns, - range: _, - }) => { - visitor.visit_expr(cls); - for pattern in patterns { - visitor.visit_pattern(pattern); - } - - for pattern in kwd_patterns { - visitor.visit_pattern(pattern); - } - } - - Pattern::MatchStar(_) => {} - - Pattern::MatchAs(ast::PatternMatchAs { - pattern, - range: _, - name: _, - }) => { - if let Some(pattern) = pattern { - visitor.visit_pattern(pattern); - } - } - - Pattern::MatchOr(ast::PatternMatchOr { patterns, range: _ }) => { - for pattern in patterns { - visitor.visit_pattern(pattern); - } - } + Pattern::MatchValue(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchSingleton(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchSequence(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchMapping(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchClass(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchStar(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchAs(pattern) => pattern.visit_preorder(visitor), + Pattern::MatchOr(pattern) => pattern.visit_preorder(visitor), } } visitor.leave_node(node); @@ -1051,6 +495,8 @@ where V: PreorderVisitor<'a> + ?Sized, { let node = AnyNodeRef::from(alias); - visitor.enter_node(node); + if visitor.enter_node(node).is_traverse() { + alias.visit_preorder(visitor); + } visitor.leave_node(node); }