From 813226b6488c47ead44abadc36fd8a50b958e120 Mon Sep 17 00:00:00 2001 From: Ali Rezvani <3788964+rzvxa@users.noreply.github.com> Date: Sat, 23 Mar 2024 17:18:30 +0330 Subject: [PATCH] refactor(ast): get rid of unsafe transmutation in VisitMut trait. (#2764) This will close #2745, In this PR I attempt to fix this issue using a combination of ideas discussed in the issue mentioned above, I've created this early draft so people can pitch in if there is something I should consider doing. The first goal of this PR is to resolve the issue with the possible illegal references, As a result of my approach it would also end up with a bunch of walk_* and walk_*_mut functions to help with the abstraction. I want to eliminate enter_node and leave_node functions, but I still haven't started working on it since I first want to familiarize myself with all of its usage throughout the project. I'm hesitating to do it at the moment, When we want to do this it would require quite a bit of refactoring so we should make sure it is probably going to work and end up being a better implementation. --- crates/oxc_ast/src/ast_kind.rs | 19 +- crates/oxc_ast/src/lib.rs | 4 +- crates/oxc_ast/src/visit_mut.rs | 437 +++++++++--------- .../src/es2015/arrow_functions.rs | 12 +- .../oxc_transformer/src/es2015/new_target.rs | 78 ++-- crates/oxc_transformer/src/lib.rs | 35 +- 6 files changed, 319 insertions(+), 266 deletions(-) diff --git a/crates/oxc_ast/src/ast_kind.rs b/crates/oxc_ast/src/ast_kind.rs index bb0078a8a..753c4c9c3 100644 --- a/crates/oxc_ast/src/ast_kind.rs +++ b/crates/oxc_ast/src/ast_kind.rs @@ -3,9 +3,22 @@ use oxc_span::{Atom, GetSpan, Span}; #[allow(clippy::wildcard_imports)] use crate::ast::*; -/// Untyped AST Node Kind -#[derive(Debug, Clone, Copy)] -pub enum AstKind<'a> { +macro_rules! ast_kinds { + { $($ident:ident($type:ty),)* } => ( + #[derive(Debug, Clone, Copy)] + pub enum AstType { + $($ident,)* + } + + /// Untyped AST Node Kind + #[derive(Debug, Clone, Copy)] + pub enum AstKind<'a> { + $($ident($type),)* + } + ) +} + +ast_kinds! { Program(&'a Program<'a>), Directive(&'a Directive<'a>), Hashbang(&'a Hashbang<'a>), diff --git a/crates/oxc_ast/src/lib.rs b/crates/oxc_ast/src/lib.rs index c1e84fd21..332ebd83e 100644 --- a/crates/oxc_ast/src/lib.rs +++ b/crates/oxc_ast/src/lib.rs @@ -20,13 +20,13 @@ mod span; pub mod syntax_directed_operations; mod trivia; mod visit; -mod visit_mut; +pub mod visit_mut; pub use num_bigint::BigUint; pub use crate::{ ast_builder::AstBuilder, - ast_kind::AstKind, + ast_kind::{AstKind, AstType}, trivia::{Comment, CommentKind, Trivias, TriviasMap}, visit::Visit, visit_mut::VisitMut, diff --git a/crates/oxc_ast/src/visit_mut.rs b/crates/oxc_ast/src/visit_mut.rs index f19a0b016..6ac3dcd2c 100644 --- a/crates/oxc_ast/src/visit_mut.rs +++ b/crates/oxc_ast/src/visit_mut.rs @@ -4,25 +4,18 @@ use oxc_allocator::Vec; use oxc_span::Span; use oxc_syntax::scope::ScopeFlags; -use crate::{ast::*, AstKind}; +use crate::{ast::*, AstType}; /// 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_node(&mut self, _kind: AstType) {} + fn leave_node(&mut self, _kind: AstType) {} 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)); + let kind = AstType::Program; self.enter_scope({ let mut flags = ScopeFlags::Top; if program.is_strict() { @@ -79,7 +72,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_block_statement(&mut self, stmt: &mut BlockStatement<'a>) { - let kind = AstKind::BlockStatement(self.alloc(stmt)); + let kind = AstType::BlockStatement; self.enter_scope(ScopeFlags::empty()); self.enter_node(kind); self.visit_statements(&mut stmt.body); @@ -88,7 +81,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_break_statement(&mut self, stmt: &mut BreakStatement<'a>) { - let kind = AstKind::BreakStatement(self.alloc(stmt)); + let kind = AstType::BreakStatement; self.enter_node(kind); if let Some(break_target) = &mut stmt.label { self.visit_label_identifier(break_target); @@ -97,7 +90,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_continue_statement(&mut self, stmt: &mut ContinueStatement<'a>) { - let kind = AstKind::ContinueStatement(self.alloc(stmt)); + let kind = AstType::ContinueStatement; self.enter_node(kind); if let Some(continue_target) = &mut stmt.label { self.visit_label_identifier(continue_target); @@ -105,35 +98,35 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_debugger_statement(&mut self, stmt: &mut DebuggerStatement) { - let kind = AstKind::DebuggerStatement(self.alloc(stmt)); + fn visit_debugger_statement(&mut self, _stmt: &mut DebuggerStatement) { + let kind = AstType::DebuggerStatement; 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)); + let kind = AstType::DoWhileStatement; 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) { - let kind = AstKind::EmptyStatement(self.alloc(stmt)); + fn visit_empty_statement(&mut self, _stmt: &mut EmptyStatement) { + let kind = AstType::EmptyStatement; 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)); + let kind = AstType::ExpressionStatement; 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 kind = AstType::ForStatement; let is_lexical_declaration = stmt.init.as_ref().is_some_and(ForStatementInit::is_lexical_declaration); if is_lexical_declaration { @@ -157,7 +150,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_for_statement_init(&mut self, init: &mut ForStatementInit<'a>) { - let kind = AstKind::ForStatementInit(self.alloc(init)); + let kind = AstType::ForStatementInit; self.enter_node(kind); match init { ForStatementInit::VariableDeclaration(decl) => { @@ -172,7 +165,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_for_in_statement(&mut self, stmt: &mut ForInStatement<'a>) { - let kind = AstKind::ForInStatement(self.alloc(stmt)); + let kind = AstType::ForInStatement; let is_lexical_declaration = stmt.left.is_lexical_declaration(); if is_lexical_declaration { self.enter_scope(ScopeFlags::empty()); @@ -188,7 +181,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_for_of_statement(&mut self, stmt: &mut ForOfStatement<'a>) { - let kind = AstKind::ForOfStatement(self.alloc(stmt)); + let kind = AstType::ForOfStatement; let is_lexical_declaration = stmt.left.is_lexical_declaration(); if is_lexical_declaration { self.enter_scope(ScopeFlags::empty()); @@ -216,7 +209,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_if_statement(&mut self, stmt: &mut IfStatement<'a>) { - let kind = AstKind::IfStatement(self.alloc(stmt)); + let kind = AstType::IfStatement; self.enter_node(kind); self.visit_expression(&mut stmt.test); self.visit_statement(&mut stmt.consequent); @@ -227,7 +220,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_labeled_statement(&mut self, stmt: &mut LabeledStatement<'a>) { - let kind = AstKind::LabeledStatement(self.alloc(stmt)); + let kind = AstType::LabeledStatement; self.enter_node(kind); self.visit_label_identifier(&mut stmt.label); self.visit_statement(&mut stmt.body); @@ -235,7 +228,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_return_statement(&mut self, stmt: &mut ReturnStatement<'a>) { - let kind = AstKind::ReturnStatement(self.alloc(stmt)); + let kind = AstType::ReturnStatement; self.enter_node(kind); if let Some(arg) = &mut stmt.argument { self.visit_expression(arg); @@ -244,7 +237,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_switch_statement(&mut self, stmt: &mut SwitchStatement<'a>) { - let kind = AstKind::SwitchStatement(self.alloc(stmt)); + let kind = AstType::SwitchStatement; self.enter_node(kind); self.visit_expression(&mut stmt.discriminant); self.enter_scope(ScopeFlags::empty()); @@ -256,7 +249,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_switch_case(&mut self, case: &mut SwitchCase<'a>) { - let kind = AstKind::SwitchCase(self.alloc(case)); + let kind = AstType::SwitchCase; self.enter_node(kind); if let Some(expr) = &mut case.test { self.visit_expression(expr); @@ -266,14 +259,14 @@ pub trait VisitMut<'a>: Sized { } fn visit_throw_statement(&mut self, stmt: &mut ThrowStatement<'a>) { - let kind = AstKind::ThrowStatement(self.alloc(stmt)); + let kind = AstType::ThrowStatement; 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)); + let kind = AstType::TryStatement; self.enter_node(kind); self.visit_block_statement(&mut stmt.block); if let Some(handler) = &mut stmt.handler { @@ -286,7 +279,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_catch_clause(&mut self, clause: &mut CatchClause<'a>) { - let kind = AstKind::CatchClause(self.alloc(clause)); + let kind = AstType::CatchClause; self.enter_scope(ScopeFlags::empty()); self.enter_node(kind); if let Some(param) = &mut clause.param { @@ -298,14 +291,14 @@ pub trait VisitMut<'a>: Sized { } fn visit_finally_clause(&mut self, clause: &mut BlockStatement<'a>) { - let kind = AstKind::FinallyClause(self.alloc(clause)); + let kind = AstType::FinallyClause; 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)); + let kind = AstType::WhileStatement; self.enter_node(kind); self.visit_expression(&mut stmt.test); self.visit_statement(&mut stmt.body); @@ -313,7 +306,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_with_statement(&mut self, stmt: &mut WithStatement<'a>) { - let kind = AstKind::WithStatement(self.alloc(stmt)); + let kind = AstType::WithStatement; self.enter_node(kind); self.visit_expression(&mut stmt.object); self.visit_statement(&mut stmt.body); @@ -321,7 +314,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_directive(&mut self, directive: &mut Directive<'a>) { - let kind = AstKind::Directive(self.alloc(directive)); + let kind = AstType::Directive; self.enter_node(kind); self.visit_string_literal(&mut directive.expression); self.leave_node(kind); @@ -330,7 +323,7 @@ pub trait VisitMut<'a>: Sized { /* ---------- Declaration ---------- */ fn visit_variable_declaration(&mut self, decl: &mut VariableDeclaration<'a>) { - let kind = AstKind::VariableDeclaration(self.alloc(decl)); + let kind = AstType::VariableDeclaration; self.enter_node(kind); for declarator in decl.declarations.iter_mut() { self.visit_variable_declarator(declarator); @@ -339,7 +332,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_variable_declarator(&mut self, declarator: &mut VariableDeclarator<'a>) { - let kind = AstKind::VariableDeclarator(self.alloc(declarator)); + let kind = AstType::VariableDeclarator; self.enter_node(kind); self.visit_binding_pattern(&mut declarator.id); if let Some(init) = &mut declarator.init { @@ -349,7 +342,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_using_declaration(&mut self, declaration: &mut UsingDeclaration<'a>) { - let kind = AstKind::UsingDeclaration(self.alloc(declaration)); + let kind = AstType::UsingDeclaration; self.enter_node(kind); for decl in declaration.declarations.iter_mut() { self.visit_variable_declarator(decl); @@ -360,34 +353,11 @@ pub trait VisitMut<'a>: Sized { /* ---------- Function ---------- */ 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); - } - self.visit_formal_parameters(&mut func.params); - if let Some(body) = &mut func.body { - self.visit_function_body(body); - } - if let Some(parameters) = &mut func.type_parameters { - self.visit_ts_type_parameter_declaration(parameters); - } - if let Some(annotation) = &mut func.return_type { - self.visit_ts_type_annotation(annotation); - } - self.leave_node(kind); - self.leave_scope(); + walk_function_mut(self, func, flags); } fn visit_function_body(&mut self, body: &mut FunctionBody<'a>) { - let kind = AstKind::FunctionBody(self.alloc(body)); + let kind = AstType::FunctionBody; self.enter_node(kind); for directive in body.directives.iter_mut() { self.visit_directive(directive); @@ -397,7 +367,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_formal_parameters(&mut self, params: &mut FormalParameters<'a>) { - let kind = AstKind::FormalParameters(self.alloc(params)); + let kind = AstType::FormalParameters; self.enter_node(kind); for param in params.items.iter_mut() { self.visit_formal_parameter(param); @@ -409,7 +379,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_formal_parameter(&mut self, param: &mut FormalParameter<'a>) { - let kind = AstKind::FormalParameter(self.alloc(param)); + let kind = AstType::FormalParameter; self.enter_node(kind); for decorator in param.decorators.iter_mut() { self.visit_decorator(decorator); @@ -421,7 +391,7 @@ pub trait VisitMut<'a>: Sized { /* ---------- Class ---------- */ fn visit_decorator(&mut self, decorator: &mut Decorator<'a>) { - let kind = AstKind::Decorator(self.alloc(decorator)); + let kind = AstType::Decorator; self.enter_node(kind); self.visit_expression(&mut decorator.expression); self.leave_node(kind); @@ -432,7 +402,7 @@ pub trait VisitMut<'a>: Sized { self.visit_decorator(decorator); } - let kind = AstKind::Class(self.alloc(class)); + let kind = AstType::Class; // FIXME(don): Should we enter a scope when visiting class declarations? let is_class_expr = class.r#type == ClassType::ClassExpression; @@ -464,7 +434,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_class_heritage(&mut self, expr: &mut Expression<'a>) { - let kind = AstKind::ClassHeritage(self.alloc(expr)); + let kind = AstType::ClassHeritage; self.enter_node(kind); self.visit_expression(expr); self.leave_node(kind); @@ -487,7 +457,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_static_block(&mut self, block: &mut StaticBlock<'a>) { - let kind = AstKind::StaticBlock(self.alloc(block)); + let kind = AstType::StaticBlock; self.enter_scope(ScopeFlags::ClassStaticBlock); self.enter_node(kind); self.visit_statements(&mut block.body); @@ -496,25 +466,11 @@ pub trait VisitMut<'a>: Sized { } 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, Some(flags)); - self.leave_node(kind); + walk_method_definition_mut(self, def); } fn visit_property_definition(&mut self, def: &mut PropertyDefinition<'a>) { - let kind = AstKind::PropertyDefinition(self.alloc(def)); + let kind = AstType::PropertyDefinition; self.enter_node(kind); for decorator in def.decorators.iter_mut() { self.visit_decorator(decorator); @@ -589,14 +545,14 @@ pub trait VisitMut<'a>: Sized { } } - fn visit_meta_property(&mut self, meta: &mut MetaProperty<'a>) { - let kind = AstKind::MetaProperty(self.alloc(meta)); + fn visit_meta_property(&mut self, _meta: &mut MetaProperty<'a>) { + let kind = AstType::MetaProperty; 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)); + let kind = AstType::ArrayExpression; self.enter_node(kind); for elem in expr.elements.iter_mut() { self.visit_array_expression_element(elem); @@ -605,7 +561,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_array_expression_element(&mut self, arg: &mut ArrayExpressionElement<'a>) { - let kind = AstKind::ArrayExpressionElement(self.alloc(arg)); + let kind = AstType::ArrayExpressionElement; self.enter_node(kind); match arg { ArrayExpressionElement::SpreadElement(spread) => self.visit_spread_element(spread), @@ -616,7 +572,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_argument(&mut self, arg: &mut Argument<'a>) { - let kind = AstKind::Argument(self.alloc(arg)); + let kind = AstType::Argument; self.enter_node(kind); match arg { Argument::SpreadElement(spread) => self.visit_spread_element(spread), @@ -626,27 +582,27 @@ pub trait VisitMut<'a>: Sized { } fn visit_spread_element(&mut self, elem: &mut SpreadElement<'a>) { - let kind = AstKind::SpreadElement(self.alloc(elem)); + let kind = AstType::SpreadElement; 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)); + let kind = AstType::ExpressionArrayElement; self.enter_node(kind); self.visit_expression(expr); self.leave_node(kind); } - fn visit_elision(&mut self, span: Span) { - let kind = AstKind::Elision(span); + fn visit_elision(&mut self, _span: Span) { + let kind = AstType::Elision; 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)); + let kind = AstType::AssignmentExpression; self.enter_node(kind); self.visit_assignment_target(&mut expr.left); self.visit_expression(&mut expr.right); @@ -654,7 +610,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_arrow_expression(&mut self, expr: &mut ArrowFunctionExpression<'a>) { - let kind = AstKind::ArrowFunctionExpression(self.alloc(expr)); + let kind = AstType::ArrowFunctionExpression; self.enter_scope(ScopeFlags::Function | ScopeFlags::Arrow); self.enter_node(kind); self.visit_formal_parameters(&mut expr.params); @@ -667,14 +623,14 @@ pub trait VisitMut<'a>: Sized { } fn visit_await_expression(&mut self, expr: &mut AwaitExpression<'a>) { - let kind = AstKind::AwaitExpression(self.alloc(expr)); + let kind = AstType::AwaitExpression; 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)); + let kind = AstType::BinaryExpression; self.enter_node(kind); self.visit_expression(&mut expr.left); self.visit_expression(&mut expr.right); @@ -682,7 +638,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_call_expression(&mut self, expr: &mut CallExpression<'a>) { - let kind = AstKind::CallExpression(self.alloc(expr)); + let kind = AstType::CallExpression; self.enter_node(kind); for arg in expr.arguments.iter_mut() { self.visit_argument(arg); @@ -695,7 +651,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_chain_expression(&mut self, expr: &mut ChainExpression<'a>) { - let kind = AstKind::ChainExpression(self.alloc(expr)); + let kind = AstType::ChainExpression; self.enter_node(kind); self.visit_chain_element(&mut expr.expression); self.leave_node(kind); @@ -709,7 +665,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_conditional_expression(&mut self, expr: &mut ConditionalExpression<'a>) { - let kind = AstKind::ConditionalExpression(self.alloc(expr)); + let kind = AstType::ConditionalExpression; self.enter_node(kind); self.visit_expression(&mut expr.test); self.visit_expression(&mut expr.consequent); @@ -725,7 +681,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_logical_expression(&mut self, expr: &mut LogicalExpression<'a>) { - let kind = AstKind::LogicalExpression(self.alloc(expr)); + let kind = AstType::LogicalExpression; self.enter_node(kind); self.visit_expression(&mut expr.left); self.visit_expression(&mut expr.right); @@ -733,7 +689,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_member_expression(&mut self, expr: &mut MemberExpression<'a>) { - let kind = AstKind::MemberExpression(self.alloc(expr)); + let kind = AstType::MemberExpression; self.enter_node(kind); match expr { MemberExpression::ComputedMemberExpression(expr) => { @@ -765,7 +721,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_new_expression(&mut self, expr: &mut NewExpression<'a>) { - let kind = AstKind::NewExpression(self.alloc(expr)); + let kind = AstType::NewExpression; self.enter_node(kind); self.visit_expression(&mut expr.callee); if let Some(parameters) = &mut expr.type_parameters { @@ -778,7 +734,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_object_expression(&mut self, expr: &mut ObjectExpression<'a>) { - let kind = AstKind::ObjectExpression(self.alloc(expr)); + let kind = AstType::ObjectExpression; self.enter_node(kind); for prop in expr.properties.iter_mut() { self.visit_object_property_kind(prop); @@ -794,18 +750,11 @@ 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); - if let Some(init) = &mut prop.init { - self.visit_expression(init); - } - self.leave_node(kind); + walk_object_property_mut(self, prop); } fn visit_property_key(&mut self, key: &mut PropertyKey<'a>) { - let kind = AstKind::PropertyKey(self.alloc(key)); + let kind = AstType::PropertyKey; self.enter_node(kind); match key { PropertyKey::Identifier(ident) => self.visit_identifier_name(ident), @@ -816,7 +765,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_parenthesized_expression(&mut self, expr: &mut ParenthesizedExpression<'a>) { - let kind = AstKind::ParenthesizedExpression(self.alloc(expr)); + let kind = AstType::ParenthesizedExpression; self.enter_node(kind); self.visit_expression(&mut expr.expression); self.leave_node(kind); @@ -828,7 +777,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_sequence_expression(&mut self, expr: &mut SequenceExpression<'a>) { - let kind = AstKind::SequenceExpression(self.alloc(expr)); + let kind = AstType::SequenceExpression; self.enter_node(kind); for expr in expr.expressions.iter_mut() { self.visit_expression(expr); @@ -837,35 +786,35 @@ pub trait VisitMut<'a>: Sized { } fn visit_tagged_template_expression(&mut self, expr: &mut TaggedTemplateExpression<'a>) { - let kind = AstKind::TaggedTemplateExpression(self.alloc(expr)); + let kind = AstType::TaggedTemplateExpression; 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) { - let kind = AstKind::ThisExpression(self.alloc(expr)); + fn visit_this_expression(&mut self, _expr: &mut ThisExpression) { + let kind = AstType::ThisExpression; 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)); + let kind = AstType::UnaryExpression; 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)); + let kind = AstType::UpdateExpression; 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)); + let kind = AstType::YieldExpression; self.enter_node(kind); if let Some(argument) = &mut expr.argument { self.visit_expression(argument); @@ -873,14 +822,14 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_super(&mut self, expr: &mut Super) { - let kind = AstKind::Super(self.alloc(expr)); + fn visit_super(&mut self, _expr: &mut Super) { + let kind = AstType::Super; 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)); + let kind = AstType::AssignmentTarget; self.enter_node(kind); match target { AssignmentTarget::SimpleAssignmentTarget(target) => { @@ -894,7 +843,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_simple_assignment_target(&mut self, target: &mut SimpleAssignmentTarget<'a>) { - let kind = AstKind::SimpleAssignmentTarget(self.alloc(target)); + let kind = AstType::SimpleAssignmentTarget; self.enter_node(kind); match target { SimpleAssignmentTarget::AssignmentTargetIdentifier(ident) => { @@ -957,7 +906,7 @@ pub trait VisitMut<'a>: Sized { &mut self, target: &mut AssignmentTargetWithDefault<'a>, ) { - let kind = AstKind::AssignmentTargetWithDefault(self.alloc(target)); + let kind = AstType::AssignmentTargetWithDefault; self.enter_node(kind); self.visit_assignment_target(&mut target.binding); self.visit_expression(&mut target.init); @@ -1009,7 +958,7 @@ pub trait VisitMut<'a>: Sized { /* ---------- Expression ---------- */ fn visit_jsx_element(&mut self, elem: &mut JSXElement<'a>) { - let kind = AstKind::JSXElement(self.alloc(elem)); + let kind = AstType::JSXElement; self.enter_node(kind); self.visit_jsx_opening_element(&mut elem.opening_element); for child in elem.children.iter_mut() { @@ -1022,7 +971,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) { - let kind = AstKind::JSXOpeningElement(self.alloc(elem)); + let kind = AstType::JSXOpeningElement; self.enter_node(kind); self.visit_jsx_element_name(&mut elem.name); @@ -1033,14 +982,14 @@ pub trait VisitMut<'a>: Sized { } fn visit_jsx_closing_element(&mut self, elem: &mut JSXClosingElement<'a>) { - let kind = AstKind::JSXClosingElement(self.alloc(elem)); + let kind = AstType::JSXClosingElement; self.enter_node(kind); self.visit_jsx_element_name(&mut elem.name); self.leave_node(kind); } fn visit_jsx_element_name(&mut self, name: &mut JSXElementName<'a>) { - let kind = AstKind::JSXElementName(self.alloc(name)); + let kind = AstType::JSXElementName; self.enter_node(kind); match name { JSXElementName::Identifier(ident) => self.visit_jsx_identifier(ident), @@ -1050,14 +999,14 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_jsx_identifier(&mut self, ident: &mut JSXIdentifier<'a>) { - let kind = AstKind::JSXIdentifier(self.alloc(ident)); + fn visit_jsx_identifier(&mut self, _ident: &mut JSXIdentifier<'a>) { + let kind = AstType::JSXIdentifier; self.enter_node(kind); self.leave_node(kind); } fn visit_jsx_member_expression(&mut self, expr: &mut JSXMemberExpression<'a>) { - let kind = AstKind::JSXMemberExpression(self.alloc(expr)); + let kind = AstType::JSXMemberExpression; self.enter_node(kind); self.visit_jsx_member_expression_object(&mut expr.object); self.visit_jsx_identifier(&mut expr.property); @@ -1065,7 +1014,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_jsx_member_expression_object(&mut self, expr: &mut JSXMemberExpressionObject<'a>) { - let kind = AstKind::JSXMemberExpressionObject(self.alloc(expr)); + let kind = AstType::JSXMemberExpressionObject; self.enter_node(kind); match expr { JSXMemberExpressionObject::Identifier(ident) => self.visit_jsx_identifier(ident), @@ -1077,7 +1026,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_jsx_namespaced_name(&mut self, name: &mut JSXNamespacedName<'a>) { - let kind = AstKind::JSXNamespacedName(self.alloc(name)); + let kind = AstType::JSXNamespacedName; self.enter_node(kind); self.visit_jsx_identifier(&mut name.namespace); self.visit_jsx_identifier(&mut name.property); @@ -1085,7 +1034,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_jsx_attribute_item(&mut self, item: &mut JSXAttributeItem<'a>) { - let kind = AstKind::JSXAttributeItem(self.alloc(item)); + let kind = AstType::JSXAttributeItem; self.enter_node(kind); match item { JSXAttributeItem::Attribute(attribute) => self.visit_jsx_attribute(attribute), @@ -1118,7 +1067,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_jsx_expression_container(&mut self, expr: &mut JSXExpressionContainer<'a>) { - let kind = AstKind::JSXExpressionContainer(self.alloc(expr)); + let kind = AstType::JSXExpressionContainer; self.enter_node(kind); self.visit_jsx_expression(&mut expr.expression); self.leave_node(kind); @@ -1132,7 +1081,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_jsx_fragment(&mut self, elem: &mut JSXFragment<'a>) { - let kind = AstKind::JSXFragment(self.alloc(elem)); + let kind = AstType::JSXFragment; self.enter_node(kind); for child in elem.children.iter_mut() { self.visit_jsx_child(child); @@ -1154,8 +1103,8 @@ pub trait VisitMut<'a>: Sized { self.visit_expression(&mut child.expression); } - fn visit_jsx_text(&mut self, child: &JSXText<'a>) { - let kind = AstKind::JSXText(self.alloc(child)); + fn visit_jsx_text(&mut self, _child: &JSXText<'a>) { + let kind = AstType::JSXText; self.enter_node(kind); self.leave_node(kind); } @@ -1176,14 +1125,14 @@ pub trait VisitMut<'a>: Sized { } } - fn visit_binding_identifier(&mut self, ident: &mut BindingIdentifier<'a>) { - let kind = AstKind::BindingIdentifier(self.alloc(ident)); + fn visit_binding_identifier(&mut self, _ident: &mut BindingIdentifier<'a>) { + let kind = AstType::BindingIdentifier; 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)); + let kind = AstType::ObjectPattern; self.enter_node(kind); for prop in pat.properties.iter_mut() { self.visit_binding_property(prop); @@ -1200,7 +1149,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_array_pattern(&mut self, pat: &mut ArrayPattern<'a>) { - let kind = AstKind::ArrayPattern(self.alloc(pat)); + let kind = AstType::ArrayPattern; self.enter_node(kind); for pat in pat.elements.iter_mut().flatten() { self.visit_binding_pattern(pat); @@ -1212,14 +1161,14 @@ pub trait VisitMut<'a>: Sized { } fn visit_rest_element(&mut self, pat: &mut BindingRestElement<'a>) { - let kind = AstKind::BindingRestElement(self.alloc(pat)); + let kind = AstType::BindingRestElement; 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)); + let kind = AstType::AssignmentPattern; self.enter_node(kind); self.visit_binding_pattern(&mut pat.left); self.visit_expression(&mut pat.right); @@ -1228,64 +1177,64 @@ pub trait VisitMut<'a>: Sized { /* ---------- Identifier ---------- */ - fn visit_identifier_reference(&mut self, ident: &mut IdentifierReference<'a>) { - let kind = AstKind::IdentifierReference(self.alloc(ident)); + fn visit_identifier_reference(&mut self, _ident: &mut IdentifierReference<'a>) { + let kind = AstType::IdentifierReference; self.enter_node(kind); self.leave_node(kind); } - fn visit_private_identifier(&mut self, ident: &mut PrivateIdentifier<'a>) { - let kind = AstKind::PrivateIdentifier(self.alloc(ident)); + fn visit_private_identifier(&mut self, _ident: &mut PrivateIdentifier<'a>) { + let kind = AstType::PrivateIdentifier; self.enter_node(kind); self.leave_node(kind); } - fn visit_label_identifier(&mut self, ident: &mut LabelIdentifier<'a>) { - let kind = AstKind::LabelIdentifier(self.alloc(ident)); + fn visit_label_identifier(&mut self, _ident: &mut LabelIdentifier<'a>) { + let kind = AstType::LabelIdentifier; self.enter_node(kind); self.leave_node(kind); } - fn visit_identifier_name(&mut self, ident: &mut IdentifierName<'a>) { - let kind = AstKind::IdentifierName(self.alloc(ident)); + fn visit_identifier_name(&mut self, _ident: &mut IdentifierName<'a>) { + let kind = AstType::IdentifierName; self.enter_node(kind); self.leave_node(kind); } /* ---------- Literal ---------- */ - fn visit_number_literal(&mut self, lit: &mut NumericLiteral<'a>) { - let kind = AstKind::NumericLiteral(self.alloc(lit)); + fn visit_number_literal(&mut self, _lit: &mut NumericLiteral<'a>) { + let kind = AstType::NumericLiteral; self.enter_node(kind); self.leave_node(kind); } - fn visit_boolean_literal(&mut self, lit: &mut BooleanLiteral) { - let kind = AstKind::BooleanLiteral(self.alloc(lit)); + fn visit_boolean_literal(&mut self, _lit: &mut BooleanLiteral) { + let kind = AstType::BooleanLiteral; self.enter_node(kind); self.leave_node(kind); } - fn visit_null_literal(&mut self, lit: &mut NullLiteral) { - let kind = AstKind::NullLiteral(self.alloc(lit)); + fn visit_null_literal(&mut self, _lit: &mut NullLiteral) { + let kind = AstType::NullLiteral; self.enter_node(kind); self.leave_node(kind); } - fn visit_bigint_literal(&mut self, lit: &mut BigIntLiteral<'a>) { - let kind = AstKind::BigintLiteral(self.alloc(lit)); + fn visit_bigint_literal(&mut self, _lit: &mut BigIntLiteral<'a>) { + let kind = AstType::BigintLiteral; self.enter_node(kind); self.leave_node(kind); } - fn visit_string_literal(&mut self, lit: &mut StringLiteral<'a>) { - let kind = AstKind::StringLiteral(self.alloc(lit)); + fn visit_string_literal(&mut self, _lit: &mut StringLiteral<'a>) { + let kind = AstType::StringLiteral; 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)); + let kind = AstType::TemplateLiteral; self.enter_node(kind); for elem in lit.quasis.iter_mut() { self.visit_template_element(elem); @@ -1296,8 +1245,8 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_reg_expr_literal(&mut self, lit: &mut RegExpLiteral<'a>) { - let kind = AstKind::RegExpLiteral(self.alloc(lit)); + fn visit_reg_expr_literal(&mut self, _lit: &mut RegExpLiteral<'a>) { + let kind = AstType::RegExpLiteral; self.enter_node(kind); self.leave_node(kind); } @@ -1307,7 +1256,7 @@ pub trait VisitMut<'a>: Sized { /* ---------- Module ---------- */ fn visit_module_declaration(&mut self, decl: &mut ModuleDeclaration<'a>) { - let kind = AstKind::ModuleDeclaration(self.alloc(decl)); + let kind = AstType::ModuleDeclaration; self.enter_node(kind); match decl { ModuleDeclaration::ImportDeclaration(decl) => { @@ -1331,7 +1280,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_import_declaration(&mut self, decl: &mut ImportDeclaration<'a>) { - let kind = AstKind::ImportDeclaration(self.alloc(decl)); + let kind = AstType::ImportDeclaration; self.enter_node(kind); if let Some(specifiers) = &mut decl.specifiers { for specifier in specifiers.iter_mut() { @@ -1381,7 +1330,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_import_specifier(&mut self, specifier: &mut ImportSpecifier<'a>) { - let kind = AstKind::ImportSpecifier(self.alloc(specifier)); + let kind = AstType::ImportSpecifier; self.enter_node(kind); // TODO: imported self.visit_binding_identifier(&mut specifier.local); @@ -1389,28 +1338,28 @@ pub trait VisitMut<'a>: Sized { } fn visit_import_default_specifier(&mut self, specifier: &mut ImportDefaultSpecifier<'a>) { - let kind = AstKind::ImportDefaultSpecifier(self.alloc(specifier)); + let kind = AstType::ImportDefaultSpecifier; self.enter_node(kind); self.visit_binding_identifier(&mut specifier.local); self.leave_node(kind); } fn visit_import_name_specifier(&mut self, specifier: &mut ImportNamespaceSpecifier<'a>) { - let kind = AstKind::ImportNamespaceSpecifier(self.alloc(specifier)); + let kind = AstType::ImportNamespaceSpecifier; self.enter_node(kind); self.visit_binding_identifier(&mut specifier.local); self.leave_node(kind); } fn visit_export_all_declaration(&mut self, decl: &mut ExportAllDeclaration<'a>) { - let kind = AstKind::ExportAllDeclaration(self.alloc(decl)); + let kind = AstType::ExportAllDeclaration; self.enter_node(kind); self.visit_string_literal(&mut decl.source); self.leave_node(kind); } fn visit_export_default_declaration(&mut self, decl: &mut ExportDefaultDeclaration<'a>) { - let kind = AstKind::ExportDefaultDeclaration(self.alloc(decl)); + let kind = AstType::ExportDefaultDeclaration; self.enter_node(kind); match &mut decl.declaration { ExportDefaultDeclarationKind::Expression(expr) => self.visit_expression(expr), @@ -1424,7 +1373,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_export_named_declaration(&mut self, decl: &mut ExportNamedDeclaration<'a>) { - let kind = AstKind::ExportNamedDeclaration(self.alloc(decl)); + let kind = AstType::ExportNamedDeclaration; self.enter_node(kind); if let Some(decl) = &mut decl.declaration { self.visit_declaration(decl); @@ -1436,7 +1385,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_enum_member(&mut self, member: &mut TSEnumMember<'a>) { - let kind = AstKind::TSEnumMember(self.alloc(member)); + let kind = AstType::TSEnumMember; self.enter_node(kind); if let Some(initializer) = &mut member.initializer { self.visit_expression(initializer); @@ -1445,7 +1394,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_enum(&mut self, decl: &mut TSEnumDeclaration<'a>) { - let kind = AstKind::TSEnumDeclaration(self.alloc(decl)); + let kind = AstType::TSEnumDeclaration; self.enter_node(kind); self.visit_binding_identifier(&mut decl.id); self.enter_scope(ScopeFlags::empty()); @@ -1483,7 +1432,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_import_equals_declaration(&mut self, decl: &mut TSImportEqualsDeclaration<'a>) { - let kind = AstKind::TSImportEqualsDeclaration(self.alloc(decl)); + let kind = AstType::TSImportEqualsDeclaration; self.enter_node(kind); self.visit_binding_identifier(&mut decl.id); self.visit_ts_module_reference(&mut decl.module_reference); @@ -1500,7 +1449,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_name(&mut self, name: &mut TSTypeName<'a>) { - let kind = AstKind::TSTypeName(self.alloc(name)); + let kind = AstType::TSTypeName; self.enter_node(kind); match name { TSTypeName::IdentifierReference(ident) => self.visit_identifier_reference(ident), @@ -1513,14 +1462,14 @@ pub trait VisitMut<'a>: Sized { &mut self, reference: &mut TSExternalModuleReference<'a>, ) { - let kind = AstKind::TSExternalModuleReference(self.alloc(reference)); + let kind = AstType::TSExternalModuleReference; self.enter_node(kind); self.visit_string_literal(&mut reference.expression); self.leave_node(kind); } fn visit_ts_qualified_name(&mut self, name: &mut TSQualifiedName<'a>) { - let kind = AstKind::TSQualifiedName(self.alloc(name)); + let kind = AstType::TSQualifiedName; self.enter_node(kind); self.visit_ts_type_name(&mut name.left); self.visit_identifier_name(&mut name.right); @@ -1528,7 +1477,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_module_declaration(&mut self, decl: &mut TSModuleDeclaration<'a>) { - let kind = AstKind::TSModuleDeclaration(self.alloc(decl)); + let kind = AstType::TSModuleDeclaration; self.enter_node(kind); match &mut decl.id { TSModuleDeclarationName::Identifier(ident) => self.visit_identifier_name(ident), @@ -1544,7 +1493,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_module_block(&mut self, block: &mut TSModuleBlock<'a>) { - let kind = AstKind::TSModuleBlock(self.alloc(block)); + let kind = AstType::TSModuleBlock; self.enter_scope(ScopeFlags::TsModuleBlock); self.enter_node(kind); self.visit_statements(&mut block.body); @@ -1553,7 +1502,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_alias_declaration(&mut self, decl: &mut TSTypeAliasDeclaration<'a>) { - let kind = AstKind::TSTypeAliasDeclaration(self.alloc(decl)); + let kind = AstType::TSTypeAliasDeclaration; self.enter_node(kind); self.visit_binding_identifier(&mut decl.id); if let Some(parameters) = &mut decl.type_parameters { @@ -1564,7 +1513,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_interface_declaration(&mut self, decl: &mut TSInterfaceDeclaration<'a>) { - let kind = AstKind::TSInterfaceDeclaration(self.alloc(decl)); + let kind = AstType::TSInterfaceDeclaration; self.enter_node(kind); self.visit_binding_identifier(&mut decl.id); if let Some(parameters) = &mut decl.type_parameters { @@ -1577,7 +1526,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_as_expression(&mut self, expr: &mut TSAsExpression<'a>) { - let kind = AstKind::TSAsExpression(self.alloc(expr)); + let kind = AstType::TSAsExpression; self.enter_node(kind); self.visit_expression(&mut expr.expression); self.visit_ts_type(&mut expr.type_annotation); @@ -1585,7 +1534,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_satisfies_expression(&mut self, expr: &mut TSSatisfiesExpression<'a>) { - let kind = AstKind::TSSatisfiesExpression(self.alloc(expr)); + let kind = AstType::TSSatisfiesExpression; self.enter_node(kind); self.visit_expression(&mut expr.expression); self.visit_ts_type(&mut expr.type_annotation); @@ -1593,14 +1542,14 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_non_null_expression(&mut self, expr: &mut TSNonNullExpression<'a>) { - let kind = AstKind::TSNonNullExpression(self.alloc(expr)); + let kind = AstType::TSNonNullExpression; 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)); + let kind = AstType::TSTypeAssertion; self.enter_node(kind); self.visit_expression(&mut expr.expression); self.visit_ts_type(&mut expr.type_annotation); @@ -1613,7 +1562,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_annotation(&mut self, annotation: &mut TSTypeAnnotation<'a>) { - let kind = AstKind::TSTypeAnnotation(self.alloc(annotation)); + let kind = AstType::TSTypeAnnotation; self.enter_node(kind); self.visit_ts_type(&mut annotation.type_annotation); self.leave_node(kind); @@ -1644,7 +1593,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_literal(&mut self, ty: &mut TSTypeLiteral<'a>) { - let kind = AstKind::TSTypeLiteral(self.alloc(ty)); + let kind = AstType::TSTypeLiteral; self.enter_node(kind); for signature in ty.members.iter_mut() { self.visit_ts_signature(signature); @@ -1653,7 +1602,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_indexed_access_type(&mut self, ty: &mut TSIndexedAccessType<'a>) { - let kind = AstKind::TSIndexedAccessType(self.alloc(ty)); + let kind = AstType::TSIndexedAccessType; self.enter_node(kind); self.visit_ts_type(&mut ty.object_type); self.visit_ts_type(&mut ty.index_type); @@ -1704,7 +1653,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_parameter(&mut self, ty: &mut TSTypeParameter<'a>) { - let kind = AstKind::TSTypeParameter(self.alloc(ty)); + let kind = AstType::TSTypeParameter; self.enter_scope(ScopeFlags::empty()); self.enter_node(kind); if let Some(constraint) = &mut ty.constraint { @@ -1719,7 +1668,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_parameter_instantiation(&mut self, ty: &mut TSTypeParameterInstantiation<'a>) { - let kind = AstKind::TSTypeParameterInstantiation(self.alloc(ty)); + let kind = AstType::TSTypeParameterInstantiation; self.enter_node(kind); for ts_parameter in ty.params.iter_mut() { self.visit_ts_type(ts_parameter); @@ -1728,7 +1677,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_parameter_declaration(&mut self, ty: &mut TSTypeParameterDeclaration<'a>) { - let kind = AstKind::TSTypeParameterDeclaration(self.alloc(ty)); + let kind = AstType::TSTypeParameterDeclaration; self.enter_node(kind); for ts_parameter in ty.params.iter_mut() { self.visit_ts_type_parameter(ts_parameter); @@ -1755,26 +1704,26 @@ pub trait VisitMut<'a>: Sized { self.visit_ts_type(&mut ty.element_type); } - fn visit_ts_null_keyword(&mut self, ty: &mut TSNullKeyword) { - let kind = AstKind::TSNullKeyword(self.alloc(ty)); + fn visit_ts_null_keyword(&mut self, _ty: &mut TSNullKeyword) { + let kind = AstType::TSNullKeyword; self.enter_node(kind); self.leave_node(kind); } - fn visit_ts_any_keyword(&mut self, ty: &mut TSAnyKeyword) { - let kind = AstKind::TSAnyKeyword(self.alloc(ty)); + fn visit_ts_any_keyword(&mut self, _ty: &mut TSAnyKeyword) { + let kind = AstType::TSAnyKeyword; self.enter_node(kind); self.leave_node(kind); } - fn visit_ts_void_keyword(&mut self, ty: &mut TSVoidKeyword) { - let kind = AstKind::TSVoidKeyword(self.alloc(ty)); + fn visit_ts_void_keyword(&mut self, _ty: &mut TSVoidKeyword) { + let kind = AstType::TSVoidKeyword; 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)); + let kind = AstType::TSIntersectionType; self.enter_node(kind); for ty in ty.types.iter_mut() { self.visit_ts_type(ty); @@ -1783,7 +1732,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_reference(&mut self, ty: &mut TSTypeReference<'a>) { - let kind = AstKind::TSTypeReference(self.alloc(ty)); + let kind = AstType::TSTypeReference; self.enter_node(kind); self.visit_ts_type_name(&mut ty.type_name); if let Some(parameters) = &mut ty.type_parameters { @@ -1793,7 +1742,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_union_type(&mut self, ty: &mut TSUnionType<'a>) { - let kind = AstKind::TSUnionType(self.alloc(ty)); + let kind = AstType::TSUnionType; self.enter_node(kind); for ty in ty.types.iter_mut() { self.visit_ts_type(ty); @@ -1802,7 +1751,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_literal_type(&mut self, ty: &mut TSLiteralType<'a>) { - let kind = AstKind::TSLiteralType(self.alloc(ty)); + let kind = AstType::TSLiteralType; self.enter_node(kind); match &mut ty.literal { TSLiteral::BigintLiteral(lit) => self.visit_bigint_literal(lit), @@ -1845,7 +1794,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_method_signature(&mut self, signature: &mut TSMethodSignature<'a>) { - let kind = AstKind::TSMethodSignature(self.alloc(signature)); + let kind = AstType::TSMethodSignature; self.enter_node(kind); self.visit_formal_parameters(&mut signature.params); if let Some(parameters) = &mut signature.type_parameters { @@ -1870,7 +1819,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_property_signature(&mut self, signature: &mut TSPropertySignature<'a>) { - let kind = AstKind::TSPropertySignature(self.alloc(signature)); + let kind = AstType::TSPropertySignature; self.enter_node(kind); self.visit_property_key(&mut signature.key); if let Some(annotation) = &mut signature.type_annotation { @@ -1894,7 +1843,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_type_query(&mut self, ty: &mut TSTypeQuery<'a>) { - let kind = AstKind::TSTypeQuery(self.alloc(ty)); + let kind = AstType::TSTypeQuery; self.enter_node(kind); match &mut ty.expr_name { TSTypeQueryExprName::TSTypeName(name) => self.visit_ts_type_name(name), @@ -1907,7 +1856,7 @@ pub trait VisitMut<'a>: Sized { } fn visit_ts_import_type(&mut self, ty: &mut TSImportType<'a>) { - let kind = AstKind::TSImportType(self.alloc(ty)); + let kind = AstType::TSImportType; self.enter_node(kind); self.visit_ts_type(&mut ty.argument); if let Some(name) = &mut ty.qualifier { @@ -1940,3 +1889,69 @@ pub trait VisitMut<'a>: Sized { } } } + +pub fn walk_method_definition_mut<'a, V: VisitMut<'a>>( + visitor: &mut V, + def: &mut MethodDefinition<'a>, +) { + let kind = AstType::MethodDefinition; + visitor.enter_node(kind); + for decorator in def.decorators.iter_mut() { + visitor.visit_decorator(decorator); + } + + let flags = match def.kind { + MethodDefinitionKind::Get => ScopeFlags::GetAccessor, + MethodDefinitionKind::Set => ScopeFlags::SetAccessor, + MethodDefinitionKind::Constructor => ScopeFlags::Constructor, + MethodDefinitionKind::Method => ScopeFlags::empty(), + }; + visitor.visit_property_key(&mut def.key); + visitor.visit_function(&mut def.value, Some(flags)); + visitor.leave_node(kind); +} + +pub fn walk_object_property_mut<'a, V: VisitMut<'a>>( + visitor: &mut V, + prop: &mut ObjectProperty<'a>, +) { + let kind = AstType::ObjectProperty; + visitor.enter_node(kind); + visitor.visit_property_key(&mut prop.key); + visitor.visit_expression(&mut prop.value); + if let Some(init) = &mut prop.init { + visitor.visit_expression(init); + } + visitor.leave_node(kind); +} + +pub fn walk_function_mut<'a, V: VisitMut<'a>>( + visitor: &mut V, + func: &mut Function<'a>, + flags: Option, +) { + let kind = AstType::Function; + visitor.enter_scope({ + let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function; + if func.is_strict() { + flags |= ScopeFlags::StrictMode; + } + flags + }); + visitor.enter_node(kind); + if let Some(ident) = &mut func.id { + visitor.visit_binding_identifier(ident); + } + visitor.visit_formal_parameters(&mut func.params); + if let Some(body) = &mut func.body { + visitor.visit_function_body(body); + } + if let Some(parameters) = &mut func.type_parameters { + visitor.visit_ts_type_parameter_declaration(parameters); + } + if let Some(annotation) = &mut func.return_type { + visitor.visit_ts_type_annotation(annotation); + } + visitor.leave_node(kind); + visitor.leave_scope(); +} diff --git a/crates/oxc_transformer/src/es2015/arrow_functions.rs b/crates/oxc_transformer/src/es2015/arrow_functions.rs index e41eb282c..0d5c62227 100644 --- a/crates/oxc_transformer/src/es2015/arrow_functions.rs +++ b/crates/oxc_transformer/src/es2015/arrow_functions.rs @@ -1,7 +1,7 @@ use std::rc::Rc; use oxc_allocator::Vec; -use oxc_ast::{ast::*, AstBuilder, AstKind, VisitMut}; +use oxc_ast::{ast::*, AstBuilder, AstType, VisitMut}; use oxc_span::{Atom, SPAN}; use serde::Deserialize; @@ -16,7 +16,7 @@ use crate::TransformTarget; /// * pub struct ArrowFunctions<'a> { ast: Rc>, - nodes: Vec<'a, AstKind<'a>>, + nodes: Vec<'a, AstType>, uid: usize, has_this: bool, /// Insert a variable declaration at the top of the BlockStatement @@ -33,11 +33,11 @@ pub struct ArrowFunctionsOptions { } impl<'a> VisitMut<'a> for ArrowFunctions<'a> { - fn enter_node(&mut self, kind: AstKind<'a>) { + fn enter_node(&mut self, kind: AstType) { self.nodes.push(kind); } - fn leave_node(&mut self, _kind: AstKind<'a>) { + fn leave_node(&mut self, _kind: AstType) { self.nodes.pop(); } @@ -45,8 +45,8 @@ impl<'a> VisitMut<'a> for ArrowFunctions<'a> { let parent_kind = self.nodes.last().unwrap(); let parent_parent_kind = self.nodes[self.nodes.len() - 2]; if ident.name == "this" - && (matches!(parent_kind, AstKind::JSXElementName(_)) - || matches!(parent_parent_kind, AstKind::JSXMemberExpression(_))) + && (matches!(parent_kind, AstType::JSXElementName) + || matches!(parent_parent_kind, AstType::JSXMemberExpression)) { if !self.has_this { self.has_this = true; diff --git a/crates/oxc_transformer/src/es2015/new_target.rs b/crates/oxc_transformer/src/es2015/new_target.rs index 1d6027cae..a9341826f 100644 --- a/crates/oxc_transformer/src/es2015/new_target.rs +++ b/crates/oxc_transformer/src/es2015/new_target.rs @@ -1,6 +1,6 @@ use crate::{context::TransformerCtx, TransformOptions, TransformTarget}; use oxc_allocator::Vec; -use oxc_ast::{ast::*, AstBuilder, AstKind, VisitMut}; +use oxc_ast::{ast::*, AstBuilder}; use oxc_diagnostics::miette; use oxc_span::{Atom, Span, SPAN}; use oxc_syntax::operator::BinaryOperator; @@ -24,18 +24,54 @@ enum NewTargetKind<'a> { Function(Option>), } -impl<'a> VisitMut<'a> for NewTarget<'a> { - fn enter_node(&mut self, kind: AstKind<'a>) { - if let Some(kind) = self.get_kind(kind) { - self.kinds.push(kind); +impl<'a> NewTarget<'a> { + pub(crate) fn enter_method_definition(&mut self, def: &MethodDefinition<'a>) { + let kind = match def.kind { + MethodDefinitionKind::Get + | MethodDefinitionKind::Set + | MethodDefinitionKind::Method => NewTargetKind::Method, + MethodDefinitionKind::Constructor => NewTargetKind::Constructor, + }; + self.push(kind); + } + + pub(crate) fn leave_method_definition(&mut self, _: &MethodDefinition) { + self.pop(); + } + + pub(crate) fn enter_object_property(&mut self, prop: &ObjectProperty<'a>) { + if prop.method { + self.push(NewTargetKind::Method); } } - fn leave_node(&mut self, kind: AstKind<'a>) { - if self.get_kind(kind).is_some() { - self.kinds.pop(); + pub(crate) fn leave_object_property(&mut self, prop: &ObjectProperty<'a>) { + if prop.method { + self.pop(); } } + + pub(crate) fn enter_function(&mut self, func: &Function<'a>) { + if let Some(kind) = self.function_new_target_kind(func) { + self.push(kind); + } + } + + pub(crate) fn leave_function(&mut self, func: &Function<'a>) { + if self.function_new_target_kind(func).is_some() { + self.pop(); + } + } + + fn function_new_target_kind(&self, func: &Function<'a>) -> Option> { + // oxc visitor `MethodDefinitionKind` will enter `Function` node, here need to exclude it + if let Some(kind) = self.kinds.last() { + if !matches!(kind, NewTargetKind::Function(_)) { + return None; + } + } + func.id.as_ref().map(|id| NewTargetKind::Function(Some(id.name.clone()))) + } } impl<'a> NewTarget<'a> { @@ -52,26 +88,12 @@ impl<'a> NewTarget<'a> { }) } - fn get_kind(&self, kind: AstKind<'a>) -> Option> { - match kind { - AstKind::MethodDefinition(def) => match def.kind { - MethodDefinitionKind::Get - | MethodDefinitionKind::Set - | MethodDefinitionKind::Method => Some(NewTargetKind::Method), - MethodDefinitionKind::Constructor => Some(NewTargetKind::Constructor), - }, - AstKind::ObjectProperty(property) => property.method.then_some(NewTargetKind::Method), - AstKind::Function(function) => { - // oxc visitor `MethodDefinitionKind` will enter `Function` node, here need to exclude it - if let Some(kind) = self.kinds.last() { - if !matches!(kind, NewTargetKind::Function(_)) { - return None; - } - } - function.id.as_ref().map(|id| NewTargetKind::Function(Some(id.name.clone()))) - } - _ => None, - } + fn push(&mut self, kind: NewTargetKind<'a>) { + self.kinds.push(kind); + } + + fn pop(&mut self) { + self.kinds.pop(); } fn create_constructor_expr(&self, span: Span) -> Expression<'a> { diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 5d50d5e09..82e3d204f 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -28,7 +28,7 @@ use std::{cell::RefCell, rc::Rc, sync::Arc}; use es2015::TemplateLiterals; use oxc_allocator::Allocator; -use oxc_ast::{ast::*, AstBuilder, AstKind, VisitMut}; +use oxc_ast::{ast::*, visit_mut::walk_function_mut, AstBuilder, AstType, VisitMut}; use oxc_diagnostics::Error; use oxc_semantic::{ScopeFlags, Semantic}; use oxc_span::SourceType; @@ -152,16 +152,8 @@ impl<'a> Transformer<'a> { } impl<'a> VisitMut<'a> for Transformer<'a> { - fn enter_node(&mut self, kind: oxc_ast::AstKind<'a>) { - self.es2015_new_target.as_mut().map(|t| t.enter_node(kind)); - } - - fn leave_node(&mut self, kind: oxc_ast::AstKind<'a>) { - self.es2015_new_target.as_mut().map(|t| t.leave_node(kind)); - } - fn visit_program(&mut self, program: &mut Program<'a>) { - let kind = AstKind::Program(self.alloc(program)); + let kind = AstType::Program; self.enter_scope({ let mut flags = ScopeFlags::Top; if program.is_strict() { @@ -185,7 +177,7 @@ impl<'a> VisitMut<'a> for Transformer<'a> { } fn visit_assignment_expression(&mut self, expr: &mut AssignmentExpression<'a>) { - let kind = AstKind::AssignmentExpression(self.alloc(expr)); + let kind = AstType::AssignmentExpression; self.enter_node(kind); self.es2015_function_name.as_mut().map(|t| t.transform_assignment_expression(expr)); @@ -238,7 +230,7 @@ impl<'a> VisitMut<'a> for Transformer<'a> { } fn visit_catch_clause(&mut self, clause: &mut CatchClause<'a>) { - let kind = AstKind::CatchClause(self.alloc(clause)); + let kind = AstType::CatchClause; self.enter_scope(ScopeFlags::empty()); self.enter_node(kind); @@ -253,7 +245,7 @@ impl<'a> VisitMut<'a> for Transformer<'a> { } fn visit_object_expression(&mut self, expr: &mut ObjectExpression<'a>) { - let kind = AstKind::ObjectExpression(self.alloc(expr)); + let kind = AstType::ObjectExpression; self.enter_node(kind); self.es2015_function_name.as_mut().map(|t| t.transform_object_expression(expr)); self.es2015_duplicate_keys.as_mut().map(|t| t.transform_object_expression(expr)); @@ -265,8 +257,9 @@ impl<'a> VisitMut<'a> for Transformer<'a> { } fn visit_object_property(&mut self, prop: &mut ObjectProperty<'a>) { - let kind = AstKind::ObjectProperty(self.alloc(prop)); + let kind = AstType::ObjectProperty; self.enter_node(kind); + self.es2015_new_target.as_mut().map(|t| t.enter_object_property(prop)); self.es2015_shorthand_properties.as_mut().map(|t| t.transform_object_property(prop)); self.es3_property_literal.as_mut().map(|t| t.transform_object_property(prop)); @@ -276,6 +269,8 @@ impl<'a> VisitMut<'a> for Transformer<'a> { if let Some(init) = &mut prop.init { self.visit_expression(init); } + + self.es2015_new_target.as_mut().map(|t| t.leave_object_property(prop)); self.leave_node(kind); } @@ -288,7 +283,7 @@ impl<'a> VisitMut<'a> for Transformer<'a> { } fn visit_variable_declarator(&mut self, declarator: &mut VariableDeclarator<'a>) { - let kind = AstKind::VariableDeclarator(self.alloc(declarator)); + let kind = AstType::VariableDeclarator; self.enter_node(kind); self.es2015_function_name.as_mut().map(|t| t.transform_variable_declarator(declarator)); @@ -315,8 +310,9 @@ impl<'a> VisitMut<'a> for Transformer<'a> { } fn visit_method_definition(&mut self, def: &mut MethodDefinition<'a>) { - let kind = AstKind::MethodDefinition(self.alloc(def)); + let kind = AstType::MethodDefinition; self.enter_node(kind); + self.es2015_new_target.as_mut().map(|t| t.enter_method_definition(def)); self.typescript.as_mut().map(|t| t.transform_method_definition(def)); @@ -332,6 +328,13 @@ impl<'a> VisitMut<'a> for Transformer<'a> { }; self.visit_property_key(&mut def.key); self.visit_function(&mut def.value, Some(flags)); + self.es2015_new_target.as_mut().map(|t| t.leave_method_definition(def)); self.leave_node(kind); } + + fn visit_function(&mut self, func: &mut Function<'a>, flags: Option) { + self.es2015_new_target.as_mut().map(|t| t.enter_function(func)); + walk_function_mut(self, func, flags); + self.es2015_new_target.as_mut().map(|t| t.leave_function(func)); + } }