refactor(transformer/typescript): move all entry points to implementation of Traverse trait (#5422)

This commit is contained in:
Dunqing 2024-09-03 18:26:20 +00:00
parent 0617249716
commit c984219e06
6 changed files with 436 additions and 373 deletions

View file

@ -120,13 +120,13 @@ impl<'a> Transformer<'a> {
impl<'a> Traverse<'a> for Transformer<'a> { impl<'a> Traverse<'a> for Transformer<'a> {
fn enter_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_program(program, ctx); self.x0_typescript.enter_program(program, ctx);
self.x1_react.transform_program(program, ctx); self.x1_react.transform_program(program, ctx);
} }
fn exit_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) { fn exit_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
self.x1_react.transform_program_on_exit(program, ctx); self.x1_react.transform_program_on_exit(program, ctx);
self.x0_typescript.transform_program_on_exit(program, ctx); self.x0_typescript.exit_program(program, ctx);
self.x3_es2015.exit_program(program, ctx); self.x3_es2015.exit_program(program, ctx);
} }
@ -135,22 +135,22 @@ impl<'a> Traverse<'a> for Transformer<'a> {
fn enter_arrow_function_expression( fn enter_arrow_function_expression(
&mut self, &mut self,
expr: &mut ArrowFunctionExpression<'a>, expr: &mut ArrowFunctionExpression<'a>,
_ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_arrow_expression(expr); self.x0_typescript.enter_arrow_function_expression(expr, ctx);
} }
fn enter_binding_pattern(&mut self, pat: &mut BindingPattern<'a>, _ctx: &mut TraverseCtx<'a>) { fn enter_binding_pattern(&mut self, pat: &mut BindingPattern<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_binding_pattern(pat); self.x0_typescript.enter_binding_pattern(pat, ctx);
} }
fn enter_call_expression(&mut self, expr: &mut CallExpression<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_call_expression(&mut self, expr: &mut CallExpression<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_call_expression(expr); self.x0_typescript.enter_call_expression(expr, ctx);
self.x1_react.transform_call_expression(expr, ctx); self.x1_react.transform_call_expression(expr, ctx);
} }
fn enter_class(&mut self, class: &mut Class<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_class(&mut self, class: &mut Class<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_class(class); self.x0_typescript.enter_class(class, ctx);
self.x3_es2015.enter_class(class, ctx); self.x3_es2015.enter_class(class, ctx);
} }
@ -158,19 +158,19 @@ impl<'a> Traverse<'a> for Transformer<'a> {
self.x3_es2015.exit_class(class, ctx); self.x3_es2015.exit_class(class, ctx);
} }
fn enter_class_body(&mut self, body: &mut ClassBody<'a>, _ctx: &mut TraverseCtx<'a>) { fn enter_class_body(&mut self, body: &mut ClassBody<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_class_body(body); self.x0_typescript.enter_class_body(body, ctx);
} }
fn enter_ts_module_declaration( fn enter_ts_module_declaration(
&mut self, &mut self,
decl: &mut TSModuleDeclaration<'a>, decl: &mut TSModuleDeclaration<'a>,
_ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_ts_module_declaration(decl); self.x0_typescript.enter_ts_module_declaration(decl, ctx);
} }
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_expression(expr); self.x0_typescript.enter_expression(expr, ctx);
self.x1_react.transform_expression(expr, ctx); self.x1_react.transform_expression(expr, ctx);
self.x2_es2021.enter_expression(expr, ctx); self.x2_es2021.enter_expression(expr, ctx);
self.x2_es2020.enter_expression(expr, ctx); self.x2_es2020.enter_expression(expr, ctx);
@ -187,44 +187,43 @@ impl<'a> Traverse<'a> for Transformer<'a> {
fn enter_simple_assignment_target( fn enter_simple_assignment_target(
&mut self, &mut self,
node: &mut SimpleAssignmentTarget<'a>, node: &mut SimpleAssignmentTarget<'a>,
_ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_simple_assignment_target(node); self.x0_typescript.enter_simple_assignment_target(node, ctx);
} }
fn enter_assignment_target( fn enter_assignment_target(
&mut self, &mut self,
node: &mut AssignmentTarget<'a>, node: &mut AssignmentTarget<'a>,
_ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_assignment_target(node); self.x0_typescript.enter_assignment_target(node, ctx);
} }
fn enter_formal_parameter( fn enter_formal_parameter(
&mut self, &mut self,
param: &mut FormalParameter<'a>, param: &mut FormalParameter<'a>,
_ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_formal_parameter(param); self.x0_typescript.enter_formal_parameter(param, ctx);
} }
fn enter_function(&mut self, func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_function(&mut self, func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_function(func);
self.x3_es2015.enter_function(func, ctx); self.x3_es2015.enter_function(func, ctx);
} }
fn exit_function(&mut self, func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) { fn exit_function(&mut self, func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_function(func); self.x0_typescript.exit_function(func, ctx);
self.x1_react.transform_function_on_exit(func, ctx); self.x1_react.transform_function_on_exit(func, ctx);
self.x3_es2015.exit_function(func, ctx); self.x3_es2015.exit_function(func, ctx);
} }
fn enter_jsx_element(&mut self, node: &mut JSXElement<'a>, _ctx: &mut TraverseCtx<'a>) { fn enter_jsx_element(&mut self, node: &mut JSXElement<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_jsx_element(node); self.x0_typescript.enter_jsx_element(node, ctx);
} }
fn enter_jsx_fragment(&mut self, node: &mut JSXFragment<'a>, _ctx: &mut TraverseCtx<'a>) { fn enter_jsx_fragment(&mut self, node: &mut JSXFragment<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_jsx_fragment(node); self.x0_typescript.enter_jsx_fragment(node, ctx);
} }
fn enter_jsx_opening_element( fn enter_jsx_opening_element(
@ -232,7 +231,7 @@ impl<'a> Traverse<'a> for Transformer<'a> {
elem: &mut JSXOpeningElement<'a>, elem: &mut JSXOpeningElement<'a>,
ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_jsx_opening_element(elem); self.x0_typescript.enter_jsx_opening_element(elem, ctx);
self.x1_react.transform_jsx_opening_element(elem, ctx); self.x1_react.transform_jsx_opening_element(elem, ctx);
} }
@ -251,9 +250,9 @@ impl<'a> Traverse<'a> for Transformer<'a> {
fn enter_method_definition( fn enter_method_definition(
&mut self, &mut self,
def: &mut MethodDefinition<'a>, def: &mut MethodDefinition<'a>,
_ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_method_definition(def); self.x0_typescript.enter_method_definition(def, ctx);
} }
fn exit_method_definition( fn exit_method_definition(
@ -261,31 +260,31 @@ impl<'a> Traverse<'a> for Transformer<'a> {
def: &mut MethodDefinition<'a>, def: &mut MethodDefinition<'a>,
ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_method_definition_on_exit(def, ctx); self.x0_typescript.exit_method_definition(def, ctx);
} }
fn enter_new_expression(&mut self, expr: &mut NewExpression<'a>, _ctx: &mut TraverseCtx<'a>) { fn enter_new_expression(&mut self, expr: &mut NewExpression<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_new_expression(expr); self.x0_typescript.enter_new_expression(expr, ctx);
} }
fn enter_property_definition( fn enter_property_definition(
&mut self, &mut self,
def: &mut PropertyDefinition<'a>, def: &mut PropertyDefinition<'a>,
_ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_property_definition(def); self.x0_typescript.enter_property_definition(def, ctx);
} }
fn enter_accessor_property( fn enter_accessor_property(
&mut self, &mut self,
node: &mut AccessorProperty<'a>, node: &mut AccessorProperty<'a>,
_ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_accessor_property(node); self.x0_typescript.enter_accessor_property(node, ctx);
} }
fn enter_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { fn enter_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_statements(stmts); self.x0_typescript.enter_statements(stmts, ctx);
self.x1_react.transform_statements(stmts, ctx); self.x1_react.transform_statements(stmts, ctx);
self.x2_es2021.enter_statements(stmts, ctx); self.x2_es2021.enter_statements(stmts, ctx);
self.x2_es2020.enter_statements(stmts, ctx); self.x2_es2020.enter_statements(stmts, ctx);
@ -315,7 +314,7 @@ impl<'a> Traverse<'a> for Transformer<'a> {
} }
fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) { fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_statements_on_exit(stmts, ctx); self.x0_typescript.exit_statements(stmts, ctx);
self.x1_react.transform_statements_on_exit(stmts, ctx); self.x1_react.transform_statements_on_exit(stmts, ctx);
self.x2_es2021.exit_statements(stmts, ctx); self.x2_es2021.exit_statements(stmts, ctx);
self.x2_es2020.exit_statements(stmts, ctx); self.x2_es2020.exit_statements(stmts, ctx);
@ -325,17 +324,17 @@ impl<'a> Traverse<'a> for Transformer<'a> {
fn enter_tagged_template_expression( fn enter_tagged_template_expression(
&mut self, &mut self,
expr: &mut TaggedTemplateExpression<'a>, expr: &mut TaggedTemplateExpression<'a>,
_ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_tagged_template_expression(expr); self.x0_typescript.enter_tagged_template_expression(expr, ctx);
} }
fn enter_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_statement(stmt, ctx); self.x0_typescript.enter_statement(stmt, ctx);
} }
fn enter_declaration(&mut self, decl: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_declaration(&mut self, decl: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_declaration(decl, ctx); self.x0_typescript.enter_declaration(decl, ctx);
self.x3_es2015.enter_declaration(decl, ctx); self.x3_es2015.enter_declaration(decl, ctx);
} }
@ -344,11 +343,11 @@ impl<'a> Traverse<'a> for Transformer<'a> {
} }
fn enter_if_statement(&mut self, stmt: &mut IfStatement<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_if_statement(&mut self, stmt: &mut IfStatement<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_if_statement(stmt, ctx); self.x0_typescript.enter_if_statement(stmt, ctx);
} }
fn enter_while_statement(&mut self, stmt: &mut WhileStatement<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_while_statement(&mut self, stmt: &mut WhileStatement<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_while_statement(stmt, ctx); self.x0_typescript.enter_while_statement(stmt, ctx);
} }
fn enter_do_while_statement( fn enter_do_while_statement(
@ -356,19 +355,19 @@ impl<'a> Traverse<'a> for Transformer<'a> {
stmt: &mut DoWhileStatement<'a>, stmt: &mut DoWhileStatement<'a>,
ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_do_while_statement(stmt, ctx); self.x0_typescript.enter_do_while_statement(stmt, ctx);
} }
fn enter_for_statement(&mut self, stmt: &mut ForStatement<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_for_statement(&mut self, stmt: &mut ForStatement<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_for_statement(stmt, ctx); self.x0_typescript.enter_for_statement(stmt, ctx);
} }
fn enter_for_of_statement(&mut self, stmt: &mut ForOfStatement<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_for_of_statement(&mut self, stmt: &mut ForOfStatement<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_for_of_statement(stmt, ctx); self.x0_typescript.enter_for_of_statement(stmt, ctx);
} }
fn enter_for_in_statement(&mut self, stmt: &mut ForInStatement<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_for_in_statement(&mut self, stmt: &mut ForInStatement<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_for_in_statement(stmt, ctx); self.x0_typescript.enter_for_in_statement(stmt, ctx);
} }
fn enter_catch_clause(&mut self, clause: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_catch_clause(&mut self, clause: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) {
@ -410,8 +409,8 @@ impl<'a> Traverse<'a> for Transformer<'a> {
fn enter_ts_export_assignment( fn enter_ts_export_assignment(
&mut self, &mut self,
export_assignment: &mut TSExportAssignment<'a>, export_assignment: &mut TSExportAssignment<'a>,
_ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.x0_typescript.transform_ts_export_assignment(export_assignment); self.x0_typescript.enter_ts_export_assignment(export_assignment, ctx);
} }
} }

View file

@ -13,7 +13,7 @@ use oxc_syntax::{
scope::{ScopeFlags, ScopeId}, scope::{ScopeFlags, ScopeId},
symbol::SymbolId, symbol::SymbolId,
}; };
use oxc_traverse::TraverseCtx; use oxc_traverse::{Traverse, TraverseCtx};
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use crate::{context::Ctx, TypeScriptOptions}; use crate::{context::Ctx, TypeScriptOptions};
@ -59,20 +59,9 @@ impl<'a> TypeScriptAnnotations<'a> {
type_identifier_names: FxHashSet::default(), type_identifier_names: FxHashSet::default(),
} }
} }
/// Check if the given name is a JSX pragma or fragment pragma import
/// and if the file contains JSX elements or fragments
fn is_jsx_imports(&self, name: &str) -> bool {
self.has_jsx_element && name == self.jsx_element_import_name
|| self.has_jsx_fragment && name == self.jsx_fragment_import_name
} }
impl<'a> Traverse<'a> for TypeScriptAnnotations<'a> {
// Remove type only imports/exports fn exit_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
pub fn transform_program_on_exit(
&mut self,
program: &mut Program<'a>,
ctx: &mut TraverseCtx<'a>,
) {
let mut no_modules_remaining = true; let mut no_modules_remaining = true;
let mut some_modules_deleted = false; let mut some_modules_deleted = false;
@ -166,13 +155,16 @@ impl<'a> TypeScriptAnnotations<'a> {
program.body.push(self.ctx.ast.statement_module_declaration(export_decl)); program.body.push(self.ctx.ast.statement_module_declaration(export_decl));
} }
} }
fn enter_arrow_function_expression(
pub fn transform_arrow_expression(&mut self, expr: &mut ArrowFunctionExpression<'a>) { &mut self,
expr: &mut ArrowFunctionExpression<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
expr.type_parameters = None; expr.type_parameters = None;
expr.return_type = None; expr.return_type = None;
} }
pub fn transform_binding_pattern(&mut self, pat: &mut BindingPattern<'a>) { fn enter_binding_pattern(&mut self, pat: &mut BindingPattern<'a>, _ctx: &mut TraverseCtx<'a>) {
pat.type_annotation = None; pat.type_annotation = None;
if pat.kind.is_binding_identifier() { if pat.kind.is_binding_identifier() {
@ -180,18 +172,18 @@ impl<'a> TypeScriptAnnotations<'a> {
} }
} }
pub fn transform_call_expression(&mut self, expr: &mut CallExpression<'a>) { fn enter_call_expression(&mut self, expr: &mut CallExpression<'a>, _ctx: &mut TraverseCtx<'a>) {
expr.type_parameters = None; expr.type_parameters = None;
} }
pub fn transform_class(&mut self, class: &mut Class<'a>) { fn enter_class(&mut self, class: &mut Class<'a>, _ctx: &mut TraverseCtx<'a>) {
class.type_parameters = None; class.type_parameters = None;
class.super_type_parameters = None; class.super_type_parameters = None;
class.implements = None; class.implements = None;
class.r#abstract = false; class.r#abstract = false;
} }
pub fn transform_class_body(&mut self, body: &mut ClassBody<'a>) { fn enter_class_body(&mut self, body: &mut ClassBody<'a>, _ctx: &mut TraverseCtx<'a>) {
// Remove type only members // Remove type only members
body.body.retain(|elem| match elem { body.body.retain(|elem| match elem {
ClassElement::MethodDefinition(method) => { ClassElement::MethodDefinition(method) => {
@ -213,14 +205,18 @@ impl<'a> TypeScriptAnnotations<'a> {
}); });
} }
pub fn transform_expression(&mut self, expr: &mut Expression<'a>) { fn enter_expression(&mut self, expr: &mut Expression<'a>, _ctx: &mut TraverseCtx<'a>) {
if expr.is_typescript_syntax() { if expr.is_typescript_syntax() {
let inner_expr = expr.get_inner_expression_mut(); let inner_expr = expr.get_inner_expression_mut();
*expr = self.ctx.ast.move_expression(inner_expr); *expr = self.ctx.ast.move_expression(inner_expr);
} }
} }
pub fn transform_simple_assignment_target(&mut self, target: &mut SimpleAssignmentTarget<'a>) { fn enter_simple_assignment_target(
&mut self,
target: &mut SimpleAssignmentTarget<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
if let Some(expr) = target.get_expression_mut() { if let Some(expr) = target.get_expression_mut() {
match expr.get_inner_expression_mut() { match expr.get_inner_expression_mut() {
// `foo!++` to `foo++` // `foo!++` to `foo++`
@ -245,7 +241,11 @@ impl<'a> TypeScriptAnnotations<'a> {
} }
} }
pub fn transform_assignment_target(&mut self, target: &mut AssignmentTarget<'a>) { fn enter_assignment_target(
&mut self,
target: &mut AssignmentTarget<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
if let Some(expr) = target.get_expression_mut() { if let Some(expr) = target.get_expression_mut() {
let inner_expr = expr.get_inner_expression_mut(); let inner_expr = expr.get_inner_expression_mut();
if inner_expr.is_member_expression() { if inner_expr.is_member_expression() {
@ -256,21 +256,33 @@ impl<'a> TypeScriptAnnotations<'a> {
} }
} }
pub fn transform_formal_parameter(&mut self, param: &mut FormalParameter<'a>) { fn enter_formal_parameter(
&mut self,
param: &mut FormalParameter<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
param.accessibility = None; param.accessibility = None;
} }
pub fn transform_function(&mut self, func: &mut Function<'a>) { fn exit_function(&mut self, func: &mut Function<'a>, _ctx: &mut TraverseCtx<'a>) {
func.this_param = None; func.this_param = None;
func.type_parameters = None; func.type_parameters = None;
func.return_type = None; func.return_type = None;
} }
pub fn transform_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) { fn enter_jsx_opening_element(
&mut self,
elem: &mut JSXOpeningElement<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
elem.type_parameters = None; elem.type_parameters = None;
} }
pub fn transform_method_definition(&mut self, def: &mut MethodDefinition<'a>) { fn enter_method_definition(
&mut self,
def: &mut MethodDefinition<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
// Collects parameter properties so that we can add an assignment // Collects parameter properties so that we can add an assignment
// for each of them in the constructor body. // for each of them in the constructor body.
if def.kind == MethodDefinitionKind::Constructor { if def.kind == MethodDefinitionKind::Constructor {
@ -296,7 +308,7 @@ impl<'a> TypeScriptAnnotations<'a> {
def.r#override = false; def.r#override = false;
} }
pub fn transform_method_definition_on_exit( fn exit_method_definition(
&mut self, &mut self,
def: &mut MethodDefinition<'a>, def: &mut MethodDefinition<'a>,
ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
@ -327,11 +339,15 @@ impl<'a> TypeScriptAnnotations<'a> {
} }
} }
pub fn transform_new_expression(&mut self, expr: &mut NewExpression<'a>) { fn enter_new_expression(&mut self, expr: &mut NewExpression<'a>, _ctx: &mut TraverseCtx<'a>) {
expr.type_parameters = None; expr.type_parameters = None;
} }
pub fn transform_property_definition(&mut self, def: &mut PropertyDefinition<'a>) { fn enter_property_definition(
&mut self,
def: &mut PropertyDefinition<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
assert!( assert!(
!(def.declare && def.value.is_some()), !(def.declare && def.value.is_some()),
"Fields with the 'declare' modifier cannot be initialized here, but only in the constructor" "Fields with the 'declare' modifier cannot be initialized here, but only in the constructor"
@ -351,13 +367,21 @@ impl<'a> TypeScriptAnnotations<'a> {
def.type_annotation = None; def.type_annotation = None;
} }
pub fn transform_accessor_property(&mut self, def: &mut AccessorProperty<'a>) { fn enter_accessor_property(
&mut self,
def: &mut AccessorProperty<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
def.accessibility = None; def.accessibility = None;
def.definite = false; def.definite = false;
def.type_annotation = None; def.type_annotation = None;
} }
pub fn transform_statements(&mut self, stmts: &mut ArenaVec<'a, Statement<'a>>) { fn enter_statements(
&mut self,
stmts: &mut ArenaVec<'a, Statement<'a>>,
_ctx: &mut TraverseCtx<'a>,
) {
// Remove declare declaration // Remove declare declaration
stmts.retain( stmts.retain(
|stmt| { |stmt| {
@ -370,7 +394,7 @@ impl<'a> TypeScriptAnnotations<'a> {
); );
} }
pub fn transform_statements_on_exit( fn exit_statements(
&mut self, &mut self,
stmts: &mut ArenaVec<'a, Statement<'a>>, stmts: &mut ArenaVec<'a, Statement<'a>>,
ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
@ -415,11 +439,7 @@ impl<'a> TypeScriptAnnotations<'a> {
/// // to /// // to
/// if (true) { super() } else { super() } /// if (true) { super() } else { super() }
/// ``` /// ```
pub fn transform_if_statement( fn enter_if_statement(&mut self, stmt: &mut IfStatement<'a>, ctx: &mut TraverseCtx<'a>) {
&mut self,
stmt: &mut IfStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
if !self.assignments.is_empty() { if !self.assignments.is_empty() {
let consequent_span = match &stmt.consequent { let consequent_span = match &stmt.consequent {
Statement::ExpressionStatement(expr) Statement::ExpressionStatement(expr)
@ -455,6 +475,78 @@ impl<'a> TypeScriptAnnotations<'a> {
} }
} }
fn enter_for_statement(&mut self, stmt: &mut ForStatement<'a>, ctx: &mut TraverseCtx<'a>) {
Self::replace_for_statement_body_with_empty_block_if_ts(
&mut stmt.body,
&stmt.scope_id,
ctx,
);
}
fn enter_for_in_statement(&mut self, stmt: &mut ForInStatement<'a>, ctx: &mut TraverseCtx<'a>) {
Self::replace_for_statement_body_with_empty_block_if_ts(
&mut stmt.body,
&stmt.scope_id,
ctx,
);
}
fn enter_for_of_statement(&mut self, stmt: &mut ForOfStatement<'a>, ctx: &mut TraverseCtx<'a>) {
Self::replace_for_statement_body_with_empty_block_if_ts(
&mut stmt.body,
&stmt.scope_id,
ctx,
);
}
fn enter_while_statement(&mut self, stmt: &mut WhileStatement<'a>, ctx: &mut TraverseCtx<'a>) {
Self::replace_with_empty_block_if_ts(&mut stmt.body, ctx.current_scope_id(), ctx);
}
fn enter_do_while_statement(
&mut self,
stmt: &mut DoWhileStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
Self::replace_with_empty_block_if_ts(&mut stmt.body, ctx.current_scope_id(), ctx);
}
fn enter_tagged_template_expression(
&mut self,
expr: &mut TaggedTemplateExpression<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
expr.type_parameters = None;
}
fn enter_jsx_element(&mut self, _elem: &mut JSXElement<'a>, _ctx: &mut TraverseCtx<'a>) {
self.has_jsx_element = true;
}
fn enter_jsx_fragment(&mut self, _elem: &mut JSXFragment<'a>, _ctx: &mut TraverseCtx<'a>) {
self.has_jsx_fragment = true;
}
fn enter_ts_module_declaration(
&mut self,
decl: &mut TSModuleDeclaration<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
// NB: Namespace transform happens in `enter_program` visitor, and replaces retained
// namespaces with functions. This visitor is called after, by which time any remaining
// namespaces need to be deleted.
self.type_identifier_names.insert(decl.id.name().clone());
}
}
impl<'a> TypeScriptAnnotations<'a> {
/// Check if the given name is a JSX pragma or fragment pragma import
/// and if the file contains JSX elements or fragments
fn is_jsx_imports(&self, name: &str) -> bool {
self.has_jsx_element && name == self.jsx_element_import_name
|| self.has_jsx_fragment && name == self.jsx_fragment_import_name
}
fn create_block_with_statement( fn create_block_with_statement(
stmt: Statement<'a>, stmt: Statement<'a>,
span: Span, span: Span,
@ -466,58 +558,6 @@ impl<'a> TypeScriptAnnotations<'a> {
Statement::BlockStatement(ctx.ast.alloc(block)) Statement::BlockStatement(ctx.ast.alloc(block))
} }
pub fn transform_for_statement(
&mut self,
stmt: &mut ForStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
Self::replace_for_statement_body_with_empty_block_if_ts(
&mut stmt.body,
&stmt.scope_id,
ctx,
);
}
pub fn transform_for_in_statement(
&mut self,
stmt: &mut ForInStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
Self::replace_for_statement_body_with_empty_block_if_ts(
&mut stmt.body,
&stmt.scope_id,
ctx,
);
}
pub fn transform_for_of_statement(
&mut self,
stmt: &mut ForOfStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
Self::replace_for_statement_body_with_empty_block_if_ts(
&mut stmt.body,
&stmt.scope_id,
ctx,
);
}
pub fn transform_while_statement(
&mut self,
stmt: &mut WhileStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
Self::replace_with_empty_block_if_ts(&mut stmt.body, ctx.current_scope_id(), ctx);
}
pub fn transform_do_while_statement(
&mut self,
stmt: &mut DoWhileStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
Self::replace_with_empty_block_if_ts(&mut stmt.body, ctx.current_scope_id(), ctx);
}
fn replace_for_statement_body_with_empty_block_if_ts( fn replace_for_statement_body_with_empty_block_if_ts(
body: &mut Statement<'a>, body: &mut Statement<'a>,
scope_id: &Cell<Option<ScopeId>>, scope_id: &Cell<Option<ScopeId>>,
@ -543,28 +583,6 @@ impl<'a> TypeScriptAnnotations<'a> {
} }
} }
pub fn transform_tagged_template_expression(
&mut self,
expr: &mut TaggedTemplateExpression<'a>,
) {
expr.type_parameters = None;
}
pub fn transform_jsx_element(&mut self, _elem: &mut JSXElement<'a>) {
self.has_jsx_element = true;
}
pub fn transform_jsx_fragment(&mut self, _elem: &mut JSXFragment<'a>) {
self.has_jsx_fragment = true;
}
pub fn transform_ts_module_declaration(&mut self, decl: &mut TSModuleDeclaration<'a>) {
// NB: Namespace transform happens in `enter_program` visitor, and replaces retained
// namespaces with functions. This visitor is called after, by which time any remaining
// namespaces need to be deleted.
self.type_identifier_names.insert(decl.id.name().clone());
}
pub fn has_value_reference(&self, name: &str, ctx: &TraverseCtx<'a>) -> bool { pub fn has_value_reference(&self, name: &str, ctx: &TraverseCtx<'a>) -> bool {
if let Some(symbol_id) = ctx.scopes().get_root_binding(name) { if let Some(symbol_id) = ctx.scopes().get_root_binding(name) {
// `import T from 'mod'; const T = 1;` The T has a value redeclaration // `import T from 'mod'; const T = 1;` The T has a value redeclaration

View file

@ -10,7 +10,7 @@ use oxc_syntax::{
reference::ReferenceFlags, reference::ReferenceFlags,
symbol::SymbolFlags, symbol::SymbolFlags,
}; };
use oxc_traverse::TraverseCtx; use oxc_traverse::{Traverse, TraverseCtx};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use crate::context::Ctx; use crate::context::Ctx;
@ -24,8 +24,10 @@ impl<'a> TypeScriptEnum<'a> {
pub fn new(ctx: Ctx<'a>) -> Self { pub fn new(ctx: Ctx<'a>) -> Self {
Self { ctx, enums: FxHashMap::default() } Self { ctx, enums: FxHashMap::default() }
} }
}
pub fn transform_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) { impl<'a> Traverse<'a> for TypeScriptEnum<'a> {
fn enter_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
let new_stmt = match stmt { let new_stmt = match stmt {
Statement::TSEnumDeclaration(ts_enum_decl) => { Statement::TSEnumDeclaration(ts_enum_decl) => {
self.transform_ts_enum(ts_enum_decl, None, ctx) self.transform_ts_enum(ts_enum_decl, None, ctx)
@ -45,7 +47,9 @@ impl<'a> TypeScriptEnum<'a> {
*stmt = new_stmt; *stmt = new_stmt;
} }
} }
}
impl<'a> TypeScriptEnum<'a> {
/// ```TypeScript /// ```TypeScript
/// enum Foo { /// enum Foo {
/// X = 1, /// X = 1,

View file

@ -8,6 +8,8 @@ mod rewrite_extensions;
use std::rc::Rc; use std::rc::Rc;
use module::TypeScriptModule;
use namespace::TypeScriptNamespace;
use oxc_allocator::Vec; use oxc_allocator::Vec;
use oxc_ast::ast::*; use oxc_ast::ast::*;
use oxc_traverse::{Traverse, TraverseCtx}; use oxc_traverse::{Traverse, TraverseCtx};
@ -45,6 +47,8 @@ pub struct TypeScript<'a> {
annotations: TypeScriptAnnotations<'a>, annotations: TypeScriptAnnotations<'a>,
r#enum: TypeScriptEnum<'a>, r#enum: TypeScriptEnum<'a>,
namespace: TypeScriptNamespace<'a>,
module: TypeScriptModule<'a>,
rewrite_extensions: TypeScriptRewriteExtensions, rewrite_extensions: TypeScriptRewriteExtensions,
} }
@ -58,6 +62,8 @@ impl<'a> TypeScript<'a> {
rewrite_extensions: TypeScriptRewriteExtensions::new( rewrite_extensions: TypeScriptRewriteExtensions::new(
options.rewrite_import_extensions.clone().unwrap_or_default(), options.rewrite_import_extensions.clone().unwrap_or_default(),
), ),
namespace: TypeScriptNamespace::new(Rc::clone(&options), Rc::clone(&ctx)),
module: TypeScriptModule::new(Rc::clone(&ctx)),
options, options,
ctx, ctx,
} }
@ -65,6 +71,189 @@ impl<'a> TypeScript<'a> {
} }
impl<'a> Traverse<'a> for TypeScript<'a> { impl<'a> Traverse<'a> for TypeScript<'a> {
fn enter_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
if self.ctx.source_type.is_typescript_definition() {
// Output empty file for TS definitions
program.directives.clear();
program.hashbang = None;
program.body.clear();
} else {
self.namespace.enter_program(program, ctx);
}
}
fn exit_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.exit_program(program, ctx);
}
fn enter_arrow_function_expression(
&mut self,
expr: &mut ArrowFunctionExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.enter_arrow_function_expression(expr, ctx);
}
fn enter_binding_pattern(&mut self, pat: &mut BindingPattern<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_binding_pattern(pat, ctx);
}
fn enter_call_expression(&mut self, expr: &mut CallExpression<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_call_expression(expr, ctx);
}
fn enter_class(&mut self, class: &mut Class<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_class(class, ctx);
}
fn enter_class_body(&mut self, body: &mut ClassBody<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_class_body(body, ctx);
}
fn enter_ts_module_declaration(
&mut self,
decl: &mut TSModuleDeclaration<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.enter_ts_module_declaration(decl, ctx);
}
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_expression(expr, ctx);
}
fn enter_simple_assignment_target(
&mut self,
target: &mut SimpleAssignmentTarget<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.enter_simple_assignment_target(target, ctx);
}
fn enter_assignment_target(
&mut self,
target: &mut AssignmentTarget<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.enter_assignment_target(target, ctx);
}
fn enter_formal_parameter(
&mut self,
param: &mut FormalParameter<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.enter_formal_parameter(param, ctx);
}
fn exit_function(&mut self, func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.exit_function(func, ctx);
}
fn enter_jsx_opening_element(
&mut self,
elem: &mut JSXOpeningElement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.enter_jsx_opening_element(elem, ctx);
}
fn enter_method_definition(
&mut self,
def: &mut MethodDefinition<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.enter_method_definition(def, ctx);
}
fn exit_method_definition(
&mut self,
def: &mut MethodDefinition<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.exit_method_definition(def, ctx);
}
fn enter_new_expression(&mut self, expr: &mut NewExpression<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_new_expression(expr, ctx);
}
fn enter_property_definition(
&mut self,
def: &mut PropertyDefinition<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.enter_property_definition(def, ctx);
}
fn enter_accessor_property(
&mut self,
def: &mut AccessorProperty<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.enter_accessor_property(def, ctx);
}
fn enter_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_statements(stmts, ctx);
}
fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) {
self.annotations.exit_statements(stmts, ctx);
}
fn enter_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
self.r#enum.enter_statement(stmt, ctx);
}
fn enter_if_statement(&mut self, stmt: &mut IfStatement<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_if_statement(stmt, ctx);
}
fn enter_while_statement(&mut self, stmt: &mut WhileStatement<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_while_statement(stmt, ctx);
}
fn enter_do_while_statement(
&mut self,
stmt: &mut DoWhileStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.enter_do_while_statement(stmt, ctx);
}
fn enter_for_statement(&mut self, stmt: &mut ForStatement<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_for_statement(stmt, ctx);
}
fn enter_for_in_statement(&mut self, stmt: &mut ForInStatement<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_for_in_statement(stmt, ctx);
}
fn enter_for_of_statement(&mut self, stmt: &mut ForOfStatement<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_for_of_statement(stmt, ctx);
}
fn enter_tagged_template_expression(
&mut self,
expr: &mut TaggedTemplateExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.enter_tagged_template_expression(expr, ctx);
}
fn enter_jsx_element(&mut self, elem: &mut JSXElement<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_jsx_element(elem, ctx);
}
fn enter_jsx_fragment(&mut self, elem: &mut JSXFragment<'a>, ctx: &mut TraverseCtx<'a>) {
self.annotations.enter_jsx_fragment(elem, ctx);
}
fn enter_declaration(&mut self, node: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) {
self.module.enter_declaration(node, ctx);
}
fn enter_import_declaration( fn enter_import_declaration(
&mut self, &mut self,
node: &mut ImportDeclaration<'a>, node: &mut ImportDeclaration<'a>,
@ -94,177 +283,12 @@ impl<'a> Traverse<'a> for TypeScript<'a> {
self.rewrite_extensions.enter_export_named_declaration(node, ctx); self.rewrite_extensions.enter_export_named_declaration(node, ctx);
} }
} }
}
// Transforms fn enter_ts_export_assignment(
impl<'a> TypeScript<'a> {
pub fn transform_program(&self, program: &mut Program<'a>, ctx: &mut TraverseCtx) {
if self.ctx.source_type.is_typescript_definition() {
// Output empty file for TS definitions
program.directives.clear();
program.hashbang = None;
program.body.clear();
} else {
self.transform_program_for_namespace(program, ctx);
}
}
pub fn transform_program_on_exit(
&mut self, &mut self,
program: &mut Program<'a>, node: &mut TSExportAssignment<'a>,
ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
self.annotations.transform_program_on_exit(program, ctx); self.module.enter_ts_export_assignment(node, ctx);
}
pub fn transform_arrow_expression(&mut self, expr: &mut ArrowFunctionExpression<'a>) {
self.annotations.transform_arrow_expression(expr);
}
pub fn transform_binding_pattern(&mut self, pat: &mut BindingPattern<'a>) {
self.annotations.transform_binding_pattern(pat);
}
pub fn transform_call_expression(&mut self, expr: &mut CallExpression<'a>) {
self.annotations.transform_call_expression(expr);
}
pub fn transform_class(&mut self, class: &mut Class<'a>) {
self.annotations.transform_class(class);
}
pub fn transform_class_body(&mut self, body: &mut ClassBody<'a>) {
self.annotations.transform_class_body(body);
}
pub fn transform_ts_module_declaration(&mut self, decl: &mut TSModuleDeclaration<'a>) {
self.annotations.transform_ts_module_declaration(decl);
}
pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
self.annotations.transform_expression(expr);
}
pub fn transform_simple_assignment_target(&mut self, target: &mut SimpleAssignmentTarget<'a>) {
self.annotations.transform_simple_assignment_target(target);
}
pub fn transform_assignment_target(&mut self, target: &mut AssignmentTarget<'a>) {
self.annotations.transform_assignment_target(target);
}
pub fn transform_formal_parameter(&mut self, param: &mut FormalParameter<'a>) {
self.annotations.transform_formal_parameter(param);
}
pub fn transform_function(&mut self, func: &mut Function<'a>) {
self.annotations.transform_function(func);
}
pub fn transform_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) {
self.annotations.transform_jsx_opening_element(elem);
}
pub fn transform_method_definition(&mut self, def: &mut MethodDefinition<'a>) {
self.annotations.transform_method_definition(def);
}
pub fn transform_method_definition_on_exit(
&mut self,
def: &mut MethodDefinition<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.transform_method_definition_on_exit(def, ctx);
}
pub fn transform_new_expression(&mut self, expr: &mut NewExpression<'a>) {
self.annotations.transform_new_expression(expr);
}
pub fn transform_property_definition(&mut self, def: &mut PropertyDefinition<'a>) {
self.annotations.transform_property_definition(def);
}
pub fn transform_accessor_property(&mut self, def: &mut AccessorProperty<'a>) {
self.annotations.transform_accessor_property(def);
}
pub fn transform_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
self.annotations.transform_statements(stmts);
}
pub fn transform_statements_on_exit(
&mut self,
stmts: &mut Vec<'a, Statement<'a>>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.transform_statements_on_exit(stmts, ctx);
}
pub fn transform_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
self.r#enum.transform_statement(stmt, ctx);
}
pub fn transform_if_statement(
&mut self,
stmt: &mut IfStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.transform_if_statement(stmt, ctx);
}
pub fn transform_while_statement(
&mut self,
stmt: &mut WhileStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.transform_while_statement(stmt, ctx);
}
pub fn transform_do_while_statement(
&mut self,
stmt: &mut DoWhileStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.transform_do_while_statement(stmt, ctx);
}
pub fn transform_for_statement(
&mut self,
stmt: &mut ForStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.transform_for_statement(stmt, ctx);
}
pub fn transform_for_in_statement(
&mut self,
stmt: &mut ForInStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.transform_for_in_statement(stmt, ctx);
}
pub fn transform_for_of_statement(
&mut self,
stmt: &mut ForOfStatement<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.annotations.transform_for_of_statement(stmt, ctx);
}
pub fn transform_tagged_template_expression(
&mut self,
expr: &mut TaggedTemplateExpression<'a>,
) {
self.annotations.transform_tagged_template_expression(expr);
}
pub fn transform_jsx_element(&mut self, elem: &mut JSXElement<'a>) {
self.annotations.transform_jsx_element(elem);
}
pub fn transform_jsx_fragment(&mut self, elem: &mut JSXFragment<'a>) {
self.annotations.transform_jsx_fragment(elem);
} }
} }

View file

@ -2,11 +2,21 @@ use oxc_allocator::Box;
use oxc_ast::ast::*; use oxc_ast::ast::*;
use oxc_span::SPAN; use oxc_span::SPAN;
use oxc_syntax::reference::ReferenceFlags; use oxc_syntax::reference::ReferenceFlags;
use oxc_traverse::TraverseCtx; use oxc_traverse::{Traverse, TraverseCtx};
use super::TypeScript; use crate::context::Ctx;
impl<'a> TypeScript<'a> { pub struct TypeScriptModule<'a> {
ctx: Ctx<'a>,
}
impl<'a> TypeScriptModule<'a> {
pub fn new(ctx: Ctx<'a>) -> Self {
Self { ctx }
}
}
impl<'a> Traverse<'a> for TypeScriptModule<'a> {
/// ```TypeScript /// ```TypeScript
/// import b = babel; /// import b = babel;
/// import AliasModule = LongNameModule; /// import AliasModule = LongNameModule;
@ -15,7 +25,7 @@ impl<'a> TypeScript<'a> {
/// var b = babel; /// var b = babel;
/// var AliasModule = LongNameModule; /// var AliasModule = LongNameModule;
/// ``` /// ```
pub fn transform_declaration(&mut self, decl: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) { fn enter_declaration(&mut self, decl: &mut Declaration<'a>, ctx: &mut TraverseCtx<'a>) {
match decl { match decl {
Declaration::TSImportEqualsDeclaration(ts_import_equals) Declaration::TSImportEqualsDeclaration(ts_import_equals)
if ts_import_equals.import_kind.is_value() => if ts_import_equals.import_kind.is_value() =>
@ -26,6 +36,19 @@ impl<'a> TypeScript<'a> {
} }
} }
fn enter_ts_export_assignment(
&mut self,
export_assignment: &mut TSExportAssignment<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
if self.ctx.source_type.is_module() {
self.ctx
.error(super::diagnostics::export_assignment_unsupported(export_assignment.span));
}
}
}
impl<'a> TypeScriptModule<'a> {
fn transform_ts_import_equals( fn transform_ts_import_equals(
&self, &self,
decl: &mut Box<'a, TSImportEqualsDeclaration<'a>>, decl: &mut Box<'a, TSImportEqualsDeclaration<'a>>,
@ -34,8 +57,8 @@ impl<'a> TypeScript<'a> {
let kind = VariableDeclarationKind::Var; let kind = VariableDeclarationKind::Var;
let decls = { let decls = {
let binding_pattern_kind = let binding_pattern_kind =
self.ctx.ast.binding_pattern_kind_binding_identifier(SPAN, &decl.id.name); ctx.ast.binding_pattern_kind_binding_identifier(SPAN, &decl.id.name);
let binding = self.ctx.ast.binding_pattern( let binding = ctx.ast.binding_pattern(
binding_pattern_kind, binding_pattern_kind,
Option::<TSTypeAnnotation>::None, Option::<TSTypeAnnotation>::None,
false, false,
@ -53,11 +76,11 @@ impl<'a> TypeScript<'a> {
)); ));
} }
let callee = self.ctx.ast.expression_identifier_reference(SPAN, "require"); let callee = ctx.ast.expression_identifier_reference(SPAN, "require");
let arguments = self.ctx.ast.vec1(Argument::from( let arguments = ctx.ast.vec1(Argument::from(
self.ctx.ast.expression_from_string_literal(reference.expression.clone()), ctx.ast.expression_from_string_literal(reference.expression.clone()),
)); ));
self.ctx.ast.expression_call( ctx.ast.expression_call(
SPAN, SPAN,
callee, callee,
Option::<TSTypeParameterInstantiation>::None, Option::<TSTypeParameterInstantiation>::None,
@ -66,18 +89,13 @@ impl<'a> TypeScript<'a> {
) )
} }
}; };
self.ctx.ast.vec1(self.ctx.ast.variable_declarator( ctx.ast.vec1(ctx.ast.variable_declarator(SPAN, kind, binding, Some(init), false))
SPAN,
kind,
binding,
Some(init),
false,
))
}; };
self.ctx.ast.declaration_variable(SPAN, kind, decls, false) ctx.ast.declaration_variable(SPAN, kind, decls, false)
} }
#[allow(clippy::only_used_in_recursion)]
fn transform_ts_type_name( fn transform_ts_type_name(
&self, &self,
type_name: &mut TSTypeName<'a>, type_name: &mut TSTypeName<'a>,
@ -89,10 +107,9 @@ impl<'a> TypeScript<'a> {
let reference_id = ident.reference_id.get().unwrap(); let reference_id = ident.reference_id.get().unwrap();
let reference = ctx.symbols_mut().get_reference_mut(reference_id); let reference = ctx.symbols_mut().get_reference_mut(reference_id);
*reference.flags_mut() = ReferenceFlags::Read; *reference.flags_mut() = ReferenceFlags::Read;
self.ctx.ast.expression_from_identifier_reference(ident) ctx.ast.expression_from_identifier_reference(ident)
} }
TSTypeName::QualifiedName(qualified_name) => self TSTypeName::QualifiedName(qualified_name) => ctx
.ctx
.ast .ast
.member_expression_static( .member_expression_static(
SPAN, SPAN,
@ -103,14 +120,4 @@ impl<'a> TypeScript<'a> {
.into(), .into(),
} }
} }
pub fn transform_ts_export_assignment(
&mut self,
export_assignment: &mut TSExportAssignment<'a>,
) {
if self.ctx.source_type.is_module() {
self.ctx
.error(super::diagnostics::export_assignment_unsupported(export_assignment.span));
}
}
} }

View file

@ -1,3 +1,5 @@
use std::rc::Rc;
use oxc_allocator::{Box, Vec}; use oxc_allocator::{Box, Vec};
use oxc_ast::{ast::*, syntax_directed_operations::BoundNames}; use oxc_ast::{ast::*, syntax_directed_operations::BoundNames};
use oxc_span::{Atom, CompactStr, SPAN}; use oxc_span::{Atom, CompactStr, SPAN};
@ -6,23 +8,30 @@ use oxc_syntax::{
scope::{ScopeFlags, ScopeId}, scope::{ScopeFlags, ScopeId},
symbol::SymbolFlags, symbol::SymbolFlags,
}; };
use oxc_traverse::TraverseCtx; use oxc_traverse::{Traverse, TraverseCtx};
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use crate::context::Ctx;
use super::{ use super::{
diagnostics::{ambient_module_nested, namespace_exporting_non_const, namespace_not_supported}, diagnostics::{ambient_module_nested, namespace_exporting_non_const, namespace_not_supported},
TypeScript, TypeScriptOptions,
}; };
// TODO: pub struct TypeScriptNamespace<'a> {
// 1. register scope for the newly created function: <https://github.com/babel/babel/blob/08b0472069cd207f043dd40a4d157addfdd36011/packages/babel-plugin-transform-typescript/src/namespace.ts#L38> ctx: Ctx<'a>,
impl<'a> TypeScript<'a> { options: Rc<TypeScriptOptions>,
}
impl<'a> TypeScriptNamespace<'a> {
pub fn new(options: Rc<TypeScriptOptions>, ctx: Ctx<'a>) -> Self {
Self { ctx, options }
}
}
impl<'a> Traverse<'a> for TypeScriptNamespace<'a> {
// `namespace Foo { }` -> `let Foo; (function (_Foo) { })(Foo || (Foo = {}));` // `namespace Foo { }` -> `let Foo; (function (_Foo) { })(Foo || (Foo = {}));`
pub(super) fn transform_program_for_namespace( fn enter_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
&self,
program: &mut Program<'a>,
ctx: &mut TraverseCtx,
) {
// namespace declaration is only allowed at the top level // namespace declaration is only allowed at the top level
if !has_namespace(program.body.as_slice()) { if !has_namespace(program.body.as_slice()) {
@ -129,7 +138,9 @@ impl<'a> TypeScript<'a> {
program.body = new_stmts; program.body = new_stmts;
} }
}
impl<'a> TypeScriptNamespace<'a> {
fn handle_nested( fn handle_nested(
&self, &self,
decl: TSModuleDeclaration<'a>, decl: TSModuleDeclaration<'a>,