From 4043ca9d925ca63fa46a6ad6c89207ba097ecf1e Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Wed, 29 Nov 2023 15:27:34 +0800 Subject: [PATCH] feat(ast): add enter node and scope for `VisitMut` trait (#1570) --- crates/oxc_ast/src/visit_mut.rs | 540 ++++++++++++++++++++++++++++++-- 1 file changed, 509 insertions(+), 31 deletions(-) diff --git a/crates/oxc_ast/src/visit_mut.rs b/crates/oxc_ast/src/visit_mut.rs index 900705c10..c51e1a9fb 100644 --- a/crates/oxc_ast/src/visit_mut.rs +++ b/crates/oxc_ast/src/visit_mut.rs @@ -2,16 +2,42 @@ use oxc_allocator::Vec; use oxc_span::Span; +use oxc_syntax::scope::ScopeFlags; -use crate::ast::*; +use crate::{ast::*, AstKind}; /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in place. pub trait VisitMut<'a>: Sized { + fn enter_node(&mut self, _kind: AstKind<'a>) {} + fn leave_node(&mut self, _kind: AstKind<'a>) {} + + fn enter_scope(&mut self, _flags: ScopeFlags) {} + fn leave_scope(&mut self) {} + + fn alloc(&self, t: &T) -> &'a T { + // SAFETY: + // This should be safe as long as `src` is an reference from the allocator. + // But honestly, I'm not really sure if this is safe. + unsafe { std::mem::transmute(t) } + } + fn visit_program(&mut self, program: &mut Program<'a>) { + let kind = AstKind::Program(self.alloc(program)); + self.enter_scope({ + let mut flags = ScopeFlags::Top; + if program.is_strict() { + flags |= ScopeFlags::StrictMode; + } + flags + }); + self.enter_node(kind); for directive in program.directives.iter_mut() { self.visit_directive(directive); } self.visit_statements(&mut program.body); + + self.leave_node(kind); + self.leave_scope(); } /* ---------- Statement ---------- */ @@ -53,35 +79,67 @@ pub trait VisitMut<'a>: Sized { } fn visit_block_statement(&mut self, stmt: &mut BlockStatement<'a>) { + let kind = AstKind::BlockStatement(self.alloc(stmt)); + self.enter_scope(ScopeFlags::empty()); + self.enter_node(kind); self.visit_statements(&mut stmt.body); + self.leave_node(kind); + self.leave_scope(); } fn visit_break_statement(&mut self, stmt: &mut BreakStatement) { + let kind = AstKind::BreakStatement(self.alloc(stmt)); + self.enter_node(kind); if let Some(break_target) = &mut stmt.label { self.visit_label_identifier(break_target); } + self.leave_node(kind); } fn visit_continue_statement(&mut self, stmt: &mut ContinueStatement) { + let kind = AstKind::ContinueStatement(self.alloc(stmt)); + self.enter_node(kind); if let Some(continue_target) = &mut stmt.label { self.visit_label_identifier(continue_target); } + self.leave_node(kind); } - fn visit_debugger_statement(&mut self, _stmt: &mut DebuggerStatement) {} + fn visit_debugger_statement(&mut self, stmt: &mut DebuggerStatement) { + let kind = AstKind::DebuggerStatement(self.alloc(stmt)); + self.enter_node(kind); + self.leave_node(kind); + } fn visit_do_while_statement(&mut self, stmt: &mut DoWhileStatement<'a>) { + let kind = AstKind::DoWhileStatement(self.alloc(stmt)); + self.enter_node(kind); self.visit_statement(&mut stmt.body); self.visit_expression(&mut stmt.test); + self.leave_node(kind); } - fn visit_empty_statement(&mut self, _stmt: &mut EmptyStatement) {} + fn visit_empty_statement(&mut self, stmt: &mut EmptyStatement) { + let kind = AstKind::EmptyStatement(self.alloc(stmt)); + self.enter_node(kind); + self.leave_node(kind); + } fn visit_expression_statement(&mut self, stmt: &mut ExpressionStatement<'a>) { + let kind = AstKind::ExpressionStatement(self.alloc(stmt)); + self.enter_node(kind); self.visit_expression(&mut stmt.expression); + self.leave_node(kind); } fn visit_for_statement(&mut self, stmt: &mut ForStatement<'a>) { + let kind = AstKind::ForStatement(self.alloc(stmt)); + let is_lexical_declaration = + stmt.init.as_ref().is_some_and(ForStatementInit::is_lexical_declaration); + if is_lexical_declaration { + self.enter_scope(ScopeFlags::empty()); + } + self.enter_node(kind); if let Some(init) = &mut stmt.init { self.visit_for_statement_init(init); } @@ -92,9 +150,15 @@ pub trait VisitMut<'a>: Sized { self.visit_expression(update); } self.visit_statement(&mut stmt.body); + self.leave_node(kind); + if is_lexical_declaration { + self.leave_scope(); + } } fn visit_for_statement_init(&mut self, init: &mut ForStatementInit<'a>) { + let kind = AstKind::ForStatementInit(self.alloc(init)); + self.enter_node(kind); match init { ForStatementInit::VariableDeclaration(decl) => { self.visit_variable_declaration(decl); @@ -104,18 +168,39 @@ pub trait VisitMut<'a>: Sized { self.visit_using_declaration(decl); } } + self.leave_node(kind); } fn visit_for_in_statement(&mut self, stmt: &mut ForInStatement<'a>) { + let kind = AstKind::ForInStatement(self.alloc(stmt)); + let is_lexical_declaration = stmt.left.is_lexical_declaration(); + if is_lexical_declaration { + self.enter_scope(ScopeFlags::empty()); + } + self.enter_node(kind); self.visit_for_statement_left(&mut stmt.left); self.visit_expression(&mut stmt.right); self.visit_statement(&mut stmt.body); + self.leave_node(kind); + if is_lexical_declaration { + self.leave_scope(); + } } fn visit_for_of_statement(&mut self, stmt: &mut ForOfStatement<'a>) { + let kind = AstKind::ForOfStatement(self.alloc(stmt)); + let is_lexical_declaration = stmt.left.is_lexical_declaration(); + if is_lexical_declaration { + self.enter_scope(ScopeFlags::empty()); + } + self.enter_node(kind); self.visit_for_statement_left(&mut stmt.left); self.visit_expression(&mut stmt.right); self.visit_statement(&mut stmt.body); + self.leave_node(kind); + if is_lexical_declaration { + self.leave_scope(); + } } fn visit_for_statement_left(&mut self, left: &mut ForStatementLeft<'a>) { @@ -131,43 +216,65 @@ pub trait VisitMut<'a>: Sized { } fn visit_if_statement(&mut self, stmt: &mut IfStatement<'a>) { + let kind = AstKind::IfStatement(self.alloc(stmt)); + self.enter_node(kind); self.visit_expression(&mut stmt.test); self.visit_statement(&mut stmt.consequent); if let Some(alternate) = &mut stmt.alternate { self.visit_statement(alternate); } + self.leave_node(kind); } fn visit_labeled_statement(&mut self, stmt: &mut LabeledStatement<'a>) { + let kind = AstKind::LabeledStatement(self.alloc(stmt)); + self.enter_node(kind); self.visit_label_identifier(&mut stmt.label); self.visit_statement(&mut stmt.body); + self.leave_node(kind); } fn visit_return_statement(&mut self, stmt: &mut ReturnStatement<'a>) { + let kind = AstKind::ReturnStatement(self.alloc(stmt)); + self.enter_node(kind); if let Some(arg) = &mut stmt.argument { self.visit_expression(arg); } + self.leave_node(kind); } fn visit_switch_statement(&mut self, stmt: &mut SwitchStatement<'a>) { + let kind = AstKind::SwitchStatement(self.alloc(stmt)); + self.enter_scope(ScopeFlags::empty()); + self.enter_node(kind); self.visit_expression(&mut stmt.discriminant); for case in stmt.cases.iter_mut() { self.visit_switch_case(case); } + self.leave_node(kind); + self.leave_scope(); } fn visit_switch_case(&mut self, case: &mut SwitchCase<'a>) { + let kind = AstKind::SwitchCase(self.alloc(case)); + self.enter_node(kind); if let Some(expr) = &mut case.test { self.visit_expression(expr); } self.visit_statements(&mut case.consequent); + self.leave_node(kind); } fn visit_throw_statement(&mut self, stmt: &mut ThrowStatement<'a>) { + let kind = AstKind::ThrowStatement(self.alloc(stmt)); + self.enter_node(kind); self.visit_expression(&mut stmt.argument); + self.leave_node(kind); } fn visit_try_statement(&mut self, stmt: &mut TryStatement<'a>) { + let kind = AstKind::TryStatement(self.alloc(stmt)); + self.enter_node(kind); self.visit_block_statement(&mut stmt.block); if let Some(handler) = &mut stmt.handler { self.visit_catch_clause(handler); @@ -175,57 +282,93 @@ pub trait VisitMut<'a>: Sized { if let Some(finalizer) = &mut stmt.finalizer { self.visit_finally_clause(finalizer); } + self.leave_node(kind); } fn visit_catch_clause(&mut self, clause: &mut CatchClause<'a>) { + let kind = AstKind::CatchClause(self.alloc(clause)); + self.enter_scope(ScopeFlags::empty()); + self.enter_node(kind); if let Some(param) = &mut clause.param { self.visit_binding_pattern(param); } self.visit_statements(&mut clause.body.body); + self.leave_node(kind); + self.leave_scope(); } fn visit_finally_clause(&mut self, clause: &mut BlockStatement<'a>) { + let kind = AstKind::FinallyClause(self.alloc(clause)); + self.enter_node(kind); self.visit_block_statement(clause); + self.leave_node(kind); } fn visit_while_statement(&mut self, stmt: &mut WhileStatement<'a>) { + let kind = AstKind::WhileStatement(self.alloc(stmt)); + self.enter_node(kind); self.visit_expression(&mut stmt.test); self.visit_statement(&mut stmt.body); + self.leave_node(kind); } fn visit_with_statement(&mut self, stmt: &mut WithStatement<'a>) { + let kind = AstKind::WithStatement(self.alloc(stmt)); + self.enter_node(kind); self.visit_expression(&mut stmt.object); self.visit_statement(&mut stmt.body); + self.leave_node(kind); } fn visit_directive(&mut self, directive: &mut Directive) { + let kind = AstKind::Directive(self.alloc(directive)); + self.enter_node(kind); self.visit_string_literal(&mut directive.expression); + self.leave_node(kind); } /* ---------- Declaration ---------- */ fn visit_variable_declaration(&mut self, decl: &mut VariableDeclaration<'a>) { + let kind = AstKind::VariableDeclaration(self.alloc(decl)); + self.enter_node(kind); for declarator in decl.declarations.iter_mut() { self.visit_variable_declarator(declarator); } + self.leave_node(kind); } fn visit_variable_declarator(&mut self, declarator: &mut VariableDeclarator<'a>) { + let kind = AstKind::VariableDeclarator(self.alloc(declarator)); + self.enter_node(kind); self.visit_binding_pattern(&mut declarator.id); if let Some(init) = &mut declarator.init { self.visit_expression(init); } + self.leave_node(kind); } fn visit_using_declaration(&mut self, declaration: &mut UsingDeclaration<'a>) { + let kind = AstKind::UsingDeclaration(self.alloc(declaration)); + self.enter_node(kind); for decl in declaration.declarations.iter_mut() { self.visit_variable_declarator(decl); } + self.leave_node(kind); } /* ---------- Function ---------- */ - fn visit_function(&mut self, func: &mut Function<'a>) { + fn visit_function(&mut self, func: &mut Function<'a>, flags: Option) { + let kind = AstKind::Function(self.alloc(func)); + self.enter_scope({ + let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function; + if func.is_strict() { + flags |= ScopeFlags::StrictMode; + } + flags + }); + self.enter_node(kind); if let Some(ident) = &mut func.id { self.visit_binding_identifier(ident); } @@ -239,41 +382,67 @@ pub trait VisitMut<'a>: Sized { if let Some(annotation) = &mut func.return_type { self.visit_ts_type_annotation(annotation); } + self.leave_node(kind); + self.leave_scope(); } fn visit_function_body(&mut self, body: &mut FunctionBody<'a>) { + let kind = AstKind::FunctionBody(self.alloc(body)); + self.enter_node(kind); for directive in body.directives.iter_mut() { self.visit_directive(directive); } self.visit_statements(&mut body.statements); + self.leave_node(kind); } fn visit_formal_parameters(&mut self, params: &mut FormalParameters<'a>) { + let kind = AstKind::FormalParameters(self.alloc(params)); + self.enter_node(kind); for param in params.items.iter_mut() { self.visit_formal_parameter(param); } if let Some(rest) = &mut params.rest { self.visit_rest_element(rest); } + self.leave_node(kind); } fn visit_formal_parameter(&mut self, param: &mut FormalParameter<'a>) { + let kind = AstKind::FormalParameter(self.alloc(param)); + self.enter_node(kind); for decorator in param.decorators.iter_mut() { self.visit_decorator(decorator); } self.visit_binding_pattern(&mut param.pattern); + self.leave_node(kind); } /* ---------- Class ---------- */ fn visit_decorator(&mut self, decorator: &mut Decorator<'a>) { + let kind = AstKind::Decorator(self.alloc(decorator)); + self.enter_node(kind); self.visit_expression(&mut decorator.expression); + self.leave_node(kind); } fn visit_class(&mut self, class: &mut Class<'a>) { for decorator in class.decorators.iter_mut() { self.visit_decorator(decorator); } + + let kind = AstKind::Class(self.alloc(class)); + + // FIXME(don): Should we enter a scope when visiting class declarations? + let is_class_expr = class.r#type == ClassType::ClassExpression; + if is_class_expr { + // Class expressions create a temporary scope with the class name as its only variable + // E.g., `let c = class A { foo() { console.log(A) } }` + self.enter_scope(ScopeFlags::empty()); + } + + self.enter_node(kind); if let Some(id) = &mut class.id { self.visit_binding_identifier(id); } @@ -288,10 +457,17 @@ pub trait VisitMut<'a>: Sized { self.visit_ts_type_parameter_instantiation(super_parameters); } self.visit_class_body(&mut class.body); + self.leave_node(kind); + if is_class_expr { + self.leave_scope(); + } } fn visit_class_heritage(&mut self, expr: &mut Expression<'a>) { + let kind = AstKind::ClassHeritage(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(expr); + self.leave_node(kind); } fn visit_class_body(&mut self, body: &mut ClassBody<'a>) { @@ -317,18 +493,35 @@ pub trait VisitMut<'a>: Sized { } fn visit_static_block(&mut self, block: &mut StaticBlock<'a>) { + let kind = AstKind::StaticBlock(self.alloc(block)); + self.enter_scope(ScopeFlags::ClassStaticBlock); + self.enter_node(kind); self.visit_statements(&mut block.body); + self.leave_node(kind); + self.leave_scope(); } fn visit_method_definition(&mut self, def: &mut MethodDefinition<'a>) { + let kind = AstKind::MethodDefinition(self.alloc(def)); + self.enter_node(kind); for decorator in def.decorators.iter_mut() { self.visit_decorator(decorator); } + + let flags = match def.kind { + MethodDefinitionKind::Get => ScopeFlags::GetAccessor, + MethodDefinitionKind::Set => ScopeFlags::SetAccessor, + MethodDefinitionKind::Constructor => ScopeFlags::Constructor, + MethodDefinitionKind::Method => ScopeFlags::empty(), + }; self.visit_property_key(&mut def.key); - self.visit_function(&mut def.value); + self.visit_function(&mut def.value, Some(flags)); + self.leave_node(kind); } fn visit_property_definition(&mut self, def: &mut PropertyDefinition<'a>) { + let kind = AstKind::PropertyDefinition(self.alloc(def)); + self.enter_node(kind); for decorator in def.decorators.iter_mut() { self.visit_decorator(decorator); } @@ -339,6 +532,7 @@ pub trait VisitMut<'a>: Sized { if let Some(annotation) = &mut def.type_annotation { self.visit_ts_type_annotation(annotation); } + self.leave_node(kind); } /* ---------- Expression ---------- */ @@ -369,7 +563,7 @@ pub trait VisitMut<'a>: Sized { Expression::ChainExpression(expr) => self.visit_chain_expression(expr), Expression::ClassExpression(expr) => self.visit_class(expr), Expression::ConditionalExpression(expr) => self.visit_conditional_expression(expr), - Expression::FunctionExpression(expr) => self.visit_function(expr), + Expression::FunctionExpression(expr) => self.visit_function(expr, None), Expression::ImportExpression(expr) => self.visit_import_expression(expr), Expression::LogicalExpression(expr) => self.visit_logical_expression(expr), Expression::MemberExpression(expr) => self.visit_member_expression(expr), @@ -401,62 +595,101 @@ pub trait VisitMut<'a>: Sized { } } - fn visit_meta_property(&mut self, _meta: &mut MetaProperty) {} + fn visit_meta_property(&mut self, meta: &mut MetaProperty) { + let kind = AstKind::MetaProperty(self.alloc(meta)); + self.enter_node(kind); + self.leave_node(kind); + } fn visit_array_expression(&mut self, expr: &mut ArrayExpression<'a>) { + let kind = AstKind::ArrayExpression(self.alloc(expr)); + self.enter_node(kind); for elem in expr.elements.iter_mut() { self.visit_array_expression_element(elem); } + self.leave_node(kind); } fn visit_array_expression_element(&mut self, arg: &mut ArrayExpressionElement<'a>) { + let kind = AstKind::ArrayExpressionElement(self.alloc(arg)); + self.enter_node(kind); match arg { ArrayExpressionElement::SpreadElement(spread) => self.visit_spread_element(spread), ArrayExpressionElement::Expression(expr) => self.visit_expression_array_element(expr), ArrayExpressionElement::Elision(span) => self.visit_elision(*span), } + self.leave_node(kind); } fn visit_argument(&mut self, arg: &mut Argument<'a>) { + let kind = AstKind::Argument(self.alloc(arg)); + self.enter_node(kind); match arg { Argument::SpreadElement(spread) => self.visit_spread_element(spread), Argument::Expression(expr) => self.visit_expression(expr), } + self.leave_node(kind); } fn visit_spread_element(&mut self, elem: &mut SpreadElement<'a>) { + let kind = AstKind::SpreadElement(self.alloc(elem)); + self.enter_node(kind); self.visit_expression(&mut elem.argument); + self.leave_node(kind); } fn visit_expression_array_element(&mut self, expr: &mut Expression<'a>) { + let kind = AstKind::ExpressionArrayElement(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(expr); + self.leave_node(kind); } - fn visit_elision(&mut self, _span: Span) {} + fn visit_elision(&mut self, span: Span) { + let kind = AstKind::Elision(span); + self.enter_node(kind); + self.leave_node(kind); + } fn visit_assignment_expression(&mut self, expr: &mut AssignmentExpression<'a>) { + let kind = AstKind::AssignmentExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_assignment_target(&mut expr.left); self.visit_expression(&mut expr.right); + self.leave_node(kind); } fn visit_arrow_expression(&mut self, expr: &mut ArrowExpression<'a>) { + let kind = AstKind::ArrowExpression(self.alloc(expr)); + self.enter_scope(ScopeFlags::Function | ScopeFlags::Arrow); + self.enter_node(kind); self.visit_formal_parameters(&mut expr.params); self.visit_function_body(&mut expr.body); if let Some(parameters) = &mut expr.type_parameters { self.visit_ts_type_parameter_declaration(parameters); } + self.leave_node(kind); + self.leave_scope(); } fn visit_await_expression(&mut self, expr: &mut AwaitExpression<'a>) { + let kind = AstKind::AwaitExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.argument); + self.leave_node(kind); } fn visit_binary_expression(&mut self, expr: &mut BinaryExpression<'a>) { + let kind = AstKind::BinaryExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.left); self.visit_expression(&mut expr.right); + self.leave_node(kind); } fn visit_call_expression(&mut self, expr: &mut CallExpression<'a>) { + let kind = AstKind::CallExpression(self.alloc(expr)); + self.enter_node(kind); for arg in expr.arguments.iter_mut() { self.visit_argument(arg); } @@ -464,10 +697,14 @@ pub trait VisitMut<'a>: Sized { if let Some(parameters) = &mut expr.type_parameters { self.visit_ts_type_parameter_instantiation(parameters); } + self.leave_node(kind); } fn visit_chain_expression(&mut self, expr: &mut ChainExpression<'a>) { + let kind = AstKind::ChainExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_chain_element(&mut expr.expression); + self.leave_node(kind); } fn visit_chain_element(&mut self, elem: &mut ChainElement<'a>) { @@ -478,9 +715,12 @@ pub trait VisitMut<'a>: Sized { } fn visit_conditional_expression(&mut self, expr: &mut ConditionalExpression<'a>) { + let kind = AstKind::ConditionalExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.test); self.visit_expression(&mut expr.consequent); self.visit_expression(&mut expr.alternate); + self.leave_node(kind); } fn visit_import_expression(&mut self, expr: &mut ImportExpression<'a>) { @@ -491,11 +731,16 @@ pub trait VisitMut<'a>: Sized { } fn visit_logical_expression(&mut self, expr: &mut LogicalExpression<'a>) { + let kind = AstKind::LogicalExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.left); self.visit_expression(&mut expr.right); + self.leave_node(kind); } fn visit_member_expression(&mut self, expr: &mut MemberExpression<'a>) { + let kind = AstKind::MemberExpression(self.alloc(expr)); + self.enter_node(kind); match expr { MemberExpression::ComputedMemberExpression(expr) => { self.visit_computed_member_expression(expr); @@ -507,6 +752,7 @@ pub trait VisitMut<'a>: Sized { self.visit_private_field_expression(expr); } } + self.leave_node(kind); } fn visit_computed_member_expression(&mut self, expr: &mut ComputedMemberExpression<'a>) { @@ -525,6 +771,8 @@ pub trait VisitMut<'a>: Sized { } fn visit_new_expression(&mut self, expr: &mut NewExpression<'a>) { + let kind = AstKind::NewExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.callee); if let Some(parameters) = &mut expr.type_parameters { self.visit_ts_type_parameter_instantiation(parameters); @@ -532,12 +780,16 @@ pub trait VisitMut<'a>: Sized { for arg in expr.arguments.iter_mut() { self.visit_argument(arg); } + self.leave_node(kind); } fn visit_object_expression(&mut self, expr: &mut ObjectExpression<'a>) { + let kind = AstKind::ObjectExpression(self.alloc(expr)); + self.enter_node(kind); for prop in expr.properties.iter_mut() { self.visit_object_property_kind(prop); } + self.leave_node(kind); } fn visit_object_property_kind(&mut self, prop: &mut ObjectPropertyKind<'a>) { @@ -548,20 +800,29 @@ pub trait VisitMut<'a>: Sized { } fn visit_object_property(&mut self, prop: &mut ObjectProperty<'a>) { + let kind = AstKind::ObjectProperty(self.alloc(prop)); + self.enter_node(kind); self.visit_property_key(&mut prop.key); self.visit_expression(&mut prop.value); + self.leave_node(kind); } fn visit_property_key(&mut self, key: &mut PropertyKey<'a>) { + let kind = AstKind::PropertyKey(self.alloc(key)); + self.enter_node(kind); match key { PropertyKey::Identifier(ident) => self.visit_identifier_name(ident), PropertyKey::PrivateIdentifier(ident) => self.visit_private_identifier(ident), PropertyKey::Expression(expr) => self.visit_expression(expr), } + self.leave_node(kind); } fn visit_parenthesized_expression(&mut self, expr: &mut ParenthesizedExpression<'a>) { + let kind = AstKind::ParenthesizedExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.expression); + self.leave_node(kind); } fn visit_private_in_expression(&mut self, expr: &mut PrivateInExpression<'a>) { @@ -570,35 +831,60 @@ pub trait VisitMut<'a>: Sized { } fn visit_sequence_expression(&mut self, expr: &mut SequenceExpression<'a>) { + let kind = AstKind::SequenceExpression(self.alloc(expr)); + self.enter_node(kind); for expr in expr.expressions.iter_mut() { self.visit_expression(expr); } + self.leave_node(kind); } fn visit_tagged_template_expression(&mut self, expr: &mut TaggedTemplateExpression<'a>) { + let kind = AstKind::TaggedTemplateExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.tag); self.visit_template_literal(&mut expr.quasi); + self.leave_node(kind); } - fn visit_this_expression(&mut self, _expr: &mut ThisExpression) {} + fn visit_this_expression(&mut self, expr: &mut ThisExpression) { + let kind = AstKind::ThisExpression(self.alloc(expr)); + self.enter_node(kind); + self.leave_node(kind); + } fn visit_unary_expression(&mut self, expr: &mut UnaryExpression<'a>) { + let kind = AstKind::UnaryExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.argument); + self.leave_node(kind); } fn visit_update_expression(&mut self, expr: &mut UpdateExpression<'a>) { + let kind = AstKind::UpdateExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_simple_assignment_target(&mut expr.argument); + self.leave_node(kind); } fn visit_yield_expression(&mut self, expr: &mut YieldExpression<'a>) { + let kind = AstKind::YieldExpression(self.alloc(expr)); + self.enter_node(kind); if let Some(argument) = &mut expr.argument { self.visit_expression(argument); } + self.leave_node(kind); } - fn visit_super(&mut self, _expr: &mut Super) {} + fn visit_super(&mut self, expr: &mut Super) { + let kind = AstKind::Super(self.alloc(expr)); + self.enter_node(kind); + self.leave_node(kind); + } fn visit_assignment_target(&mut self, target: &mut AssignmentTarget<'a>) { + let kind = AstKind::AssignmentTarget(self.alloc(target)); + self.enter_node(kind); match target { AssignmentTarget::SimpleAssignmentTarget(target) => { self.visit_simple_assignment_target(target); @@ -607,9 +893,12 @@ pub trait VisitMut<'a>: Sized { self.visit_assignment_target_pattern(pat); } } + self.leave_node(kind); } fn visit_simple_assignment_target(&mut self, target: &mut SimpleAssignmentTarget<'a>) { + let kind = AstKind::SimpleAssignmentTarget(self.alloc(target)); + self.enter_node(kind); match target { SimpleAssignmentTarget::AssignmentTargetIdentifier(ident) => { self.visit_identifier_reference(ident); @@ -630,6 +919,7 @@ pub trait VisitMut<'a>: Sized { self.visit_expression(&mut expr.expression); } } + self.leave_node(kind); } fn visit_assignment_target_pattern(&mut self, pat: &mut AssignmentTargetPattern<'a>) { @@ -670,8 +960,11 @@ pub trait VisitMut<'a>: Sized { &mut self, target: &mut AssignmentTargetWithDefault<'a>, ) { + let kind = AstKind::AssignmentTargetWithDefault(self.alloc(target)); + self.enter_node(kind); self.visit_assignment_target(&mut target.binding); self.visit_expression(&mut target.init); + self.leave_node(kind); } fn visit_object_assignment_target(&mut self, target: &mut ObjectAssignmentTarget<'a>) { @@ -715,28 +1008,42 @@ pub trait VisitMut<'a>: Sized { /* ---------- Expression ---------- */ fn visit_jsx_element(&mut self, elem: &mut JSXElement<'a>) { + let kind = AstKind::JSXElement(self.alloc(elem)); + self.enter_node(kind); self.visit_jsx_opening_element(&mut elem.opening_element); for child in elem.children.iter_mut() { self.visit_jsx_child(child); } + self.leave_node(kind); } fn visit_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) { + let kind = AstKind::JSXOpeningElement(self.alloc(elem)); + self.enter_node(kind); + self.visit_jsx_element_name(&mut elem.name); for attribute in elem.attributes.iter_mut() { self.visit_jsx_attribute_item(attribute); } + self.leave_node(kind); } - fn visit_jsx_element_name(&mut self, __name: &mut JSXElementName<'a>) {} + fn visit_jsx_element_name(&mut self, name: &mut JSXElementName<'a>) { + let kind = AstKind::JSXElementName(self.alloc(name)); + self.enter_node(kind); + self.leave_node(kind); + } fn visit_jsx_attribute_item(&mut self, item: &mut JSXAttributeItem<'a>) { + let kind = AstKind::JSXAttributeItem(self.alloc(item)); + self.enter_node(kind); match item { JSXAttributeItem::Attribute(attribute) => self.visit_jsx_attribute(attribute), JSXAttributeItem::SpreadAttribute(attribute) => { self.visit_jsx_spread_attribute(attribute); } } + self.leave_node(kind); } fn visit_jsx_attribute(&mut self, attribute: &mut JSXAttribute<'a>) { @@ -761,7 +1068,10 @@ pub trait VisitMut<'a>: Sized { } fn visit_jsx_expression_container(&mut self, expr: &mut JSXExpressionContainer<'a>) { + let kind = AstKind::JSXExpressionContainer(self.alloc(expr)); + self.enter_node(kind); self.visit_jsx_expression(&mut expr.expression); + self.leave_node(kind); } fn visit_jsx_expression(&mut self, expr: &mut JSXExpression<'a>) { @@ -772,9 +1082,12 @@ pub trait VisitMut<'a>: Sized { } fn visit_jsx_fragment(&mut self, elem: &mut JSXFragment<'a>) { + let kind = AstKind::JSXFragment(self.alloc(elem)); + self.enter_node(kind); for child in elem.children.iter_mut() { self.visit_jsx_child(child); } + self.leave_node(kind); } fn visit_jsx_child(&mut self, child: &mut JSXChild<'a>) { @@ -783,7 +1096,7 @@ pub trait VisitMut<'a>: Sized { JSXChild::Fragment(elem) => self.visit_jsx_fragment(elem), JSXChild::ExpressionContainer(expr) => self.visit_jsx_expression_container(expr), JSXChild::Spread(expr) => self.visit_jsx_spread_child(expr), - JSXChild::Text(_) => {} + JSXChild::Text(expr) => self.visit_jsx_text(expr), } } @@ -791,6 +1104,12 @@ pub trait VisitMut<'a>: Sized { self.visit_expression(&mut child.expression); } + fn visit_jsx_text(&mut self, child: &JSXText) { + let kind = AstKind::JSXText(self.alloc(child)); + self.enter_node(kind); + self.leave_node(kind); + } + /* ---------- Pattern ---------- */ fn visit_binding_pattern(&mut self, pat: &mut BindingPattern<'a>) { @@ -807,12 +1126,22 @@ pub trait VisitMut<'a>: Sized { } } - fn visit_binding_identifier(&mut self, __ident: &mut BindingIdentifier) {} + fn visit_binding_identifier(&mut self, ident: &mut BindingIdentifier) { + let kind = AstKind::BindingIdentifier(self.alloc(ident)); + self.enter_node(kind); + self.leave_node(kind); + } fn visit_object_pattern(&mut self, pat: &mut ObjectPattern<'a>) { + let kind = AstKind::ObjectPattern(self.alloc(pat)); + self.enter_node(kind); for prop in pat.properties.iter_mut() { self.visit_binding_property(prop); } + if let Some(rest) = &mut pat.rest { + self.visit_rest_element(rest); + } + self.leave_node(kind); } fn visit_binding_property(&mut self, prop: &mut BindingProperty<'a>) { @@ -821,61 +1150,115 @@ pub trait VisitMut<'a>: Sized { } fn visit_array_pattern(&mut self, pat: &mut ArrayPattern<'a>) { + let kind = AstKind::ArrayPattern(self.alloc(pat)); + self.enter_node(kind); for pat in pat.elements.iter_mut().flatten() { self.visit_binding_pattern(pat); } if let Some(rest) = &mut pat.rest { self.visit_rest_element(rest); } + self.leave_node(kind); } fn visit_rest_element(&mut self, pat: &mut RestElement<'a>) { + let kind = AstKind::RestElement(self.alloc(pat)); + self.enter_node(kind); self.visit_binding_pattern(&mut pat.argument); + self.leave_node(kind); } fn visit_assignment_pattern(&mut self, pat: &mut AssignmentPattern<'a>) { + let kind = AstKind::AssignmentPattern(self.alloc(pat)); + self.enter_node(kind); self.visit_binding_pattern(&mut pat.left); self.visit_expression(&mut pat.right); + self.leave_node(kind); } /* ---------- Identifier ---------- */ - fn visit_identifier_reference(&mut self, _ident: &mut IdentifierReference) {} + fn visit_identifier_reference(&mut self, ident: &mut IdentifierReference) { + let kind = AstKind::IdentifierReference(self.alloc(ident)); + self.enter_node(kind); + self.leave_node(kind); + } - fn visit_private_identifier(&mut self, _ident: &mut PrivateIdentifier) {} + fn visit_private_identifier(&mut self, ident: &mut PrivateIdentifier) { + let kind = AstKind::PrivateIdentifier(self.alloc(ident)); + self.enter_node(kind); + self.leave_node(kind); + } - fn visit_label_identifier(&mut self, _ident: &mut LabelIdentifier) {} + fn visit_label_identifier(&mut self, ident: &mut LabelIdentifier) { + let kind = AstKind::LabelIdentifier(self.alloc(ident)); + self.enter_node(kind); + self.leave_node(kind); + } - fn visit_identifier_name(&mut self, _ident: &mut IdentifierName) {} + fn visit_identifier_name(&mut self, ident: &mut IdentifierName) { + let kind = AstKind::IdentifierName(self.alloc(ident)); + self.enter_node(kind); + self.leave_node(kind); + } /* ---------- Literal ---------- */ - fn visit_number_literal(&mut self, _lit: &mut NumberLiteral<'a>) {} + fn visit_number_literal(&mut self, lit: &mut NumberLiteral<'a>) { + let kind = AstKind::NumberLiteral(self.alloc(lit)); + self.enter_node(kind); + self.leave_node(kind); + } - fn visit_boolean_literal(&mut self, _lit: &mut BooleanLiteral) {} + fn visit_boolean_literal(&mut self, lit: &mut BooleanLiteral) { + let kind = AstKind::BooleanLiteral(self.alloc(lit)); + self.enter_node(kind); + self.leave_node(kind); + } - fn visit_null_literal(&mut self, _lit: &mut NullLiteral) {} + fn visit_null_literal(&mut self, lit: &mut NullLiteral) { + let kind = AstKind::NullLiteral(self.alloc(lit)); + self.enter_node(kind); + self.leave_node(kind); + } - fn visit_bigint_literal(&mut self, _lit: &mut BigintLiteral) {} + fn visit_bigint_literal(&mut self, lit: &mut BigintLiteral) { + let kind = AstKind::BigintLiteral(self.alloc(lit)); + self.enter_node(kind); + self.leave_node(kind); + } - fn visit_string_literal(&mut self, _lit: &mut StringLiteral) {} + fn visit_string_literal(&mut self, lit: &mut StringLiteral) { + let kind = AstKind::StringLiteral(self.alloc(lit)); + self.enter_node(kind); + self.leave_node(kind); + } fn visit_template_literal(&mut self, lit: &mut TemplateLiteral<'a>) { + let kind = AstKind::TemplateLiteral(self.alloc(lit)); + self.enter_node(kind); for elem in lit.quasis.iter_mut() { self.visit_template_element(elem); } for expr in lit.expressions.iter_mut() { self.visit_expression(expr); } + self.leave_node(kind); } - fn visit_reg_expr_literal(&mut self, _lit: &mut RegExpLiteral) {} + fn visit_reg_expr_literal(&mut self, lit: &mut RegExpLiteral) { + let kind = AstKind::RegExpLiteral(self.alloc(lit)); + self.enter_node(kind); + self.leave_node(kind); + } fn visit_template_element(&mut self, _elem: &mut TemplateElement) {} /* ---------- Module ---------- */ fn visit_module_declaration(&mut self, decl: &mut ModuleDeclaration<'a>) { + let kind = AstKind::ModuleDeclaration(self.alloc(decl)); + self.enter_node(kind); match decl { ModuleDeclaration::ImportDeclaration(decl) => { self.visit_import_declaration(decl); @@ -894,6 +1277,7 @@ pub trait VisitMut<'a>: Sized { } ModuleDeclaration::TSNamespaceExportDeclaration(_) => {} } + self.leave_node(kind); } fn visit_import_declaration(&mut self, decl: &mut ImportDeclaration<'a>) { @@ -939,7 +1323,7 @@ pub trait VisitMut<'a>: Sized { match &mut decl.declaration { ExportDefaultDeclarationKind::Expression(expr) => self.visit_expression(expr), ExportDefaultDeclarationKind::FunctionDeclaration(func) => { - self.visit_function(func); + self.visit_function(func, None); } ExportDefaultDeclarationKind::ClassDeclaration(class) => self.visit_class(class), _ => {} @@ -953,16 +1337,31 @@ pub trait VisitMut<'a>: Sized { } fn visit_enum_member(&mut self, member: &mut TSEnumMember<'a>) { + let kind = AstKind::TSEnumMember(self.alloc(member)); + self.enter_node(kind); if let Some(initializer) = &mut member.initializer { self.visit_expression(initializer); } + self.leave_node(kind); + } + + fn visit_enum_body(&mut self, body: &mut TSEnumBody<'a>) { + let kind = AstKind::TSEnumBody(self.alloc(body)); + self.enter_scope(ScopeFlags::empty()); + self.enter_node(kind); + for member in body.members.iter_mut() { + self.visit_enum_member(member); + } + self.leave_node(kind); + self.leave_scope(); } fn visit_enum(&mut self, decl: &mut TSEnumDeclaration<'a>) { + let kind = AstKind::TSEnumDeclaration(self.alloc(decl)); + self.enter_node(kind); self.visit_binding_identifier(&mut decl.id); - for member in decl.body.members.iter_mut() { - self.visit_enum_member(member); - } + self.visit_enum_body(&mut decl.body); + self.leave_node(kind); } fn visit_declaration(&mut self, decl: &mut Declaration<'a>) { @@ -972,7 +1371,7 @@ pub trait VisitMut<'a>: Sized { fn visit_declaration_match(&mut self, decl: &mut Declaration<'a>) { match decl { Declaration::VariableDeclaration(decl) => self.visit_variable_declaration(decl), - Declaration::FunctionDeclaration(func) => self.visit_function(func), + Declaration::FunctionDeclaration(func) => self.visit_function(func, None), Declaration::ClassDeclaration(class) => self.visit_class(class), Declaration::UsingDeclaration(decl) => self.visit_using_declaration(decl), Declaration::TSModuleDeclaration(module) => { @@ -992,10 +1391,15 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_import_equals_declaration(&mut self, decl: &mut TSImportEqualsDeclaration<'a>) { + let kind = AstKind::TSImportEqualsDeclaration(self.alloc(decl)); + self.enter_node(kind); self.visit_binding_identifier(&mut decl.id); + self.leave_node(kind); } fn visit_ts_module_declaration(&mut self, decl: &mut TSModuleDeclaration<'a>) { + let kind = AstKind::TSModuleDeclaration(self.alloc(decl)); + self.enter_node(kind); match &mut decl.id { TSModuleDeclarationName::Identifier(ident) => self.visit_identifier_name(ident), TSModuleDeclarationName::StringLiteral(lit) => self.visit_string_literal(lit), @@ -1006,21 +1410,32 @@ pub trait VisitMut<'a>: Sized { } TSModuleDeclarationBody::TSModuleBlock(block) => self.visit_ts_module_block(block), } + self.leave_node(kind); } fn visit_ts_module_block(&mut self, block: &mut TSModuleBlock<'a>) { + let kind = AstKind::TSModuleBlock(self.alloc(block)); + self.enter_scope(ScopeFlags::TsModuleBlock); + self.enter_node(kind); self.visit_statements(&mut block.body); + self.leave_node(kind); + self.leave_scope(); } fn visit_ts_type_alias_declaration(&mut self, decl: &mut TSTypeAliasDeclaration<'a>) { + let kind = AstKind::TSTypeAliasDeclaration(self.alloc(decl)); + self.enter_node(kind); self.visit_binding_identifier(&mut decl.id); if let Some(parameters) = &mut decl.type_parameters { self.visit_ts_type_parameter_declaration(parameters); } self.visit_ts_type(&mut decl.type_annotation); + self.leave_node(kind); } fn visit_ts_interface_declaration(&mut self, decl: &mut TSInterfaceDeclaration<'a>) { + let kind = AstKind::TSInterfaceDeclaration(self.alloc(decl)); + self.enter_node(kind); self.visit_binding_identifier(&mut decl.id); if let Some(parameters) = &mut decl.type_parameters { self.visit_ts_type_parameter_declaration(parameters); @@ -1028,25 +1443,38 @@ pub trait VisitMut<'a>: Sized { for signature in decl.body.body.iter_mut() { self.visit_ts_signature(signature); } + self.leave_node(kind); } fn visit_ts_as_expression(&mut self, expr: &mut TSAsExpression<'a>) { + let kind = AstKind::TSAsExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.expression); self.visit_ts_type(&mut expr.type_annotation); + self.leave_node(kind); } fn visit_ts_satisfies_expression(&mut self, expr: &mut TSSatisfiesExpression<'a>) { + let kind = AstKind::TSSatisfiesExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.expression); self.visit_ts_type(&mut expr.type_annotation); + self.leave_node(kind); } fn visit_ts_non_null_expression(&mut self, expr: &mut TSNonNullExpression<'a>) { + let kind = AstKind::TSNonNullExpression(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.expression); + self.leave_node(kind); } fn visit_ts_type_assertion(&mut self, expr: &mut TSTypeAssertion<'a>) { + let kind = AstKind::TSTypeAssertion(self.alloc(expr)); + self.enter_node(kind); self.visit_expression(&mut expr.expression); self.visit_ts_type(&mut expr.type_annotation); + self.leave_node(kind); } fn visit_ts_instantiation_expression(&mut self, expr: &mut TSInstantiationExpression<'a>) { @@ -1055,7 +1483,10 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_annotation(&mut self, annotation: &mut TSTypeAnnotation<'a>) { + let kind = AstKind::TSTypeAnnotation(self.alloc(annotation)); + self.enter_node(kind); self.visit_ts_type(&mut annotation.type_annotation); + self.leave_node(kind); } fn visit_ts_type(&mut self, ty: &mut TSType<'a>) { @@ -1082,14 +1513,20 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_literal(&mut self, ty: &mut TSTypeLiteral<'a>) { + let kind = AstKind::TSTypeLiteral(self.alloc(ty)); + self.enter_node(kind); for signature in ty.members.iter_mut() { self.visit_ts_signature(signature); } + self.leave_node(kind); } fn visit_ts_indexed_access_type(&mut self, ty: &mut TSIndexedAccessType<'a>) { + let kind = AstKind::TSIndexedAccessType(self.alloc(ty)); + self.enter_node(kind); self.visit_ts_type(&mut ty.object_type); self.visit_ts_type(&mut ty.index_type); + self.leave_node(kind); } fn visit_ts_type_predicate(&mut self, ty: &mut TSTypePredicate<'a>) { @@ -1136,6 +1573,9 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_parameter(&mut self, ty: &mut TSTypeParameter<'a>) { + let kind = AstKind::TSTypeParameter(self.alloc(ty)); + self.enter_scope(ScopeFlags::empty()); + self.enter_node(kind); if let Some(constraint) = &mut ty.constraint { self.visit_ts_type(constraint); } @@ -1143,18 +1583,26 @@ pub trait VisitMut<'a>: Sized { if let Some(default) = &mut ty.default { self.visit_ts_type(default); } + self.leave_node(kind); + self.leave_scope(); } fn visit_ts_type_parameter_instantiation(&mut self, ty: &mut TSTypeParameterInstantiation<'a>) { + let kind = AstKind::TSTypeParameterInstantiation(self.alloc(ty)); + self.enter_node(kind); for ts_parameter in ty.params.iter_mut() { self.visit_ts_type(ts_parameter); } + self.leave_node(kind); } fn visit_ts_type_parameter_declaration(&mut self, ty: &mut TSTypeParameterDeclaration<'a>) { + let kind = AstKind::TSTypeParameterDeclaration(self.alloc(ty)); + self.enter_node(kind); for ts_parameter in ty.params.iter_mut() { self.visit_ts_type_parameter(ts_parameter); } + self.leave_node(kind); } fn visit_ts_constructor_type(&mut self, ty: &mut TSConstructorType<'a>) { @@ -1183,32 +1631,55 @@ pub trait VisitMut<'a>: Sized { } } - fn visit_ts_null_keyword(&mut self, _ty: &mut TSNullKeyword) {} + fn visit_ts_null_keyword(&mut self, ty: &mut TSNullKeyword) { + let kind = AstKind::TSNullKeyword(self.alloc(ty)); + self.enter_node(kind); + self.leave_node(kind); + } - fn visit_ts_any_keyword(&mut self, _ty: &mut TSAnyKeyword) {} + fn visit_ts_any_keyword(&mut self, ty: &mut TSAnyKeyword) { + let kind = AstKind::TSAnyKeyword(self.alloc(ty)); + self.enter_node(kind); + self.leave_node(kind); + } - fn visit_ts_void_keyword(&mut self, _ty: &mut TSVoidKeyword) {} + fn visit_ts_void_keyword(&mut self, ty: &mut TSVoidKeyword) { + let kind = AstKind::TSVoidKeyword(self.alloc(ty)); + self.enter_node(kind); + self.leave_node(kind); + } fn visit_ts_intersection_type(&mut self, ty: &mut TSIntersectionType<'a>) { + let kind = AstKind::TSIntersectionType(self.alloc(ty)); + self.enter_node(kind); for ty in ty.types.iter_mut() { self.visit_ts_type(ty); } + self.leave_node(kind); } fn visit_ts_type_reference(&mut self, ty: &mut TSTypeReference<'a>) { + let kind = AstKind::TSTypeReference(self.alloc(ty)); + self.enter_node(kind); self.visit_ts_type_name(&mut ty.type_name); if let Some(parameters) = &mut ty.type_parameters { self.visit_ts_type_parameter_instantiation(parameters); } + self.leave_node(kind); } fn visit_ts_union_type(&mut self, ty: &mut TSUnionType<'a>) { + let kind = AstKind::TSUnionType(self.alloc(ty)); + self.enter_node(kind); for ty in ty.types.iter_mut() { self.visit_ts_type(ty); } + self.leave_node(kind); } fn visit_ts_literal_type(&mut self, ty: &mut TSLiteralType<'a>) { + let kind = AstKind::TSLiteralType(self.alloc(ty)); + self.enter_node(kind); match &mut ty.literal { TSLiteral::BigintLiteral(lit) => self.visit_bigint_literal(lit), TSLiteral::BooleanLiteral(lit) => self.visit_boolean_literal(lit), @@ -1219,6 +1690,7 @@ pub trait VisitMut<'a>: Sized { TSLiteral::TemplateLiteral(lit) => self.visit_template_literal(lit), TSLiteral::UnaryExpression(expr) => self.visit_unary_expression(expr), } + self.leave_node(kind); } fn visit_ts_signature(&mut self, signature: &mut TSSignature<'a>) { @@ -1249,6 +1721,8 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_method_signature(&mut self, signature: &mut TSMethodSignature<'a>) { + let kind = AstKind::TSMethodSignature(self.alloc(signature)); + self.enter_node(kind); self.visit_formal_parameters(&mut signature.params); if let Some(parameters) = &mut signature.type_parameters { self.visit_ts_type_parameter_declaration(parameters); @@ -1256,6 +1730,7 @@ pub trait VisitMut<'a>: Sized { if let Some(annotation) = &mut signature.return_type { self.visit_ts_type_annotation(annotation); } + self.leave_node(kind); } fn visit_ts_index_signature_name(&mut self, name: &mut TSIndexSignatureName<'a>) { @@ -1271,10 +1746,13 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_property_signature(&mut self, signature: &mut TSPropertySignature<'a>) { + let kind = AstKind::TSPropertySignature(self.alloc(signature)); + self.enter_node(kind); self.visit_property_key(&mut signature.key); if let Some(annotation) = &mut signature.type_annotation { self.visit_ts_type_annotation(annotation); } + self.leave_node(kind); } fn visit_ts_call_signature_declaration(