Skip to content

Commit

Permalink
fix(transformer): TS transform generate do not copy statements
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Jun 22, 2024
1 parent ff1da27 commit 433b11e
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 60 deletions.
12 changes: 6 additions & 6 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,17 +208,17 @@ impl<'a> Traverse<'a> for Transformer<'a> {
fn enter_method_definition(
&mut self,
def: &mut MethodDefinition<'a>,
ctx: &mut TraverseCtx<'a>,
_ctx: &mut TraverseCtx<'a>,
) {
self.x0_typescript.transform_method_definition(def, ctx);
self.x0_typescript.transform_method_definition(def);
}

fn exit_method_definition(
&mut self,
def: &mut MethodDefinition<'a>,
_ctx: &mut TraverseCtx<'a>,
ctx: &mut TraverseCtx<'a>,
) {
self.x0_typescript.transform_method_definition_on_exit(def);
self.x0_typescript.transform_method_definition_on_exit(def, ctx);
}

fn enter_new_expression(&mut self, expr: &mut NewExpression<'a>, _ctx: &mut TraverseCtx<'a>) {
Expand All @@ -238,8 +238,8 @@ impl<'a> Traverse<'a> for Transformer<'a> {
self.x3_es2015.enter_statements(stmts);
}

fn exit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>, _ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_statements_on_exit(stmts);
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.x3_es2015.exit_statements(stmts);
}

Expand Down
111 changes: 65 additions & 46 deletions crates/oxc_transformer/src/typescript/annotations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

use std::rc::Rc;

use oxc_allocator::Vec;
use oxc_allocator::Vec as ArenaVec;
use oxc_ast::ast::*;
use oxc_span::{Atom, GetSpan, SPAN};
use oxc_syntax::{operator::AssignmentOperator, reference::ReferenceFlag};
use oxc_span::{Atom, GetSpan, Span, SPAN};
use oxc_syntax::{operator::AssignmentOperator, reference::ReferenceFlag, symbol::SymbolId};
use oxc_traverse::TraverseCtx;
use rustc_hash::FxHashSet;

Expand All @@ -16,7 +16,7 @@ pub struct TypeScriptAnnotations<'a> {
options: Rc<TypeScriptOptions>,
ctx: Ctx<'a>,
/// Assignments to be added to the constructor body
assignments: Vec<'a, Statement<'a>>,
assignments: Vec<Assignment<'a>>,
has_super_call: bool,

has_jsx_element: bool,
Expand All @@ -42,7 +42,7 @@ impl<'a> TypeScriptAnnotations<'a> {

Self {
has_super_call: false,
assignments: ctx.ast.new_vec(),
assignments: vec![],
options,
ctx,
has_jsx_element: false,
Expand All @@ -60,35 +60,6 @@ impl<'a> TypeScriptAnnotations<'a> {
|| self.has_jsx_fragment && name == self.jsx_fragment_import_name
}

// Creates `this.name = name`
fn create_this_property_assignment(
&self,
id: &BindingIdentifier<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Statement<'a> {
let ast = self.ctx.ast;

let symbol_id = id.symbol_id.get().unwrap();
let reference_id =
ctx.create_bound_reference(id.name.to_compact_str(), symbol_id, ReferenceFlag::Read);
let id = IdentifierReference::new_read(id.span, id.name.clone(), Some(reference_id));

ast.expression_statement(
SPAN,
ast.assignment_expression(
SPAN,
AssignmentOperator::Assign,
ast.simple_assignment_target_member_expression(ast.static_member(
SPAN,
ast.this_expression(SPAN),
IdentifierName::new(id.span, id.name.clone()),
false,
)),
ast.identifier_reference_expression(id),
),
)
}

// Remove type only imports/exports
pub fn transform_program_on_exit(
&mut self,
Expand Down Expand Up @@ -306,19 +277,18 @@ impl<'a> TypeScriptAnnotations<'a> {
elem.type_parameters = None;
}

pub fn transform_method_definition(
&mut self,
def: &mut MethodDefinition<'a>,
ctx: &mut TraverseCtx<'a>,
) {
pub fn transform_method_definition(&mut self, def: &mut MethodDefinition<'a>) {
// Collects parameter properties so that we can add an assignment
// for each of them in the constructor body.
if def.kind == MethodDefinitionKind::Constructor {
for param in def.value.params.items.as_mut_slice() {
if param.is_public() {
if let Some(id) = param.pattern.get_binding_identifier() {
let assignment = self.create_this_property_assignment(id, ctx);
self.assignments.push(assignment);
self.assignments.push(Assignment {
span: id.span,
name: id.name.clone(),
symbol_id: id.symbol_id.get().unwrap(),
});
}
}

Expand All @@ -333,7 +303,11 @@ impl<'a> TypeScriptAnnotations<'a> {
def.r#override = false;
}

pub fn transform_method_definition_on_exit(&mut self, def: &mut MethodDefinition<'a>) {
pub fn transform_method_definition_on_exit(
&mut self,
def: &mut MethodDefinition<'a>,
ctx: &mut TraverseCtx<'a>,
) {
if def.kind == MethodDefinitionKind::Constructor && !self.assignments.is_empty() {
// When the constructor doesn't have a super call,
// we simply add assignments to the bottom of the function body
Expand All @@ -350,7 +324,11 @@ impl<'a> TypeScriptAnnotations<'a> {
)
})
.statements
.extend(self.assignments.drain(..));
.extend(
self.assignments
.drain(..)
.map(|assignment| assignment.create_this_property_assignment(ctx)),
);
}
}
}
Expand Down Expand Up @@ -379,7 +357,7 @@ impl<'a> TypeScriptAnnotations<'a> {
def.type_annotation = None;
}

pub fn transform_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
pub fn transform_statements(&mut self, stmts: &mut ArenaVec<'a, Statement<'a>>) {
// Remove declare declaration
stmts.retain(|stmt| match stmt {
match_declaration!(Statement) => {
Expand All @@ -389,7 +367,11 @@ impl<'a> TypeScriptAnnotations<'a> {
});
}

pub fn transform_statements_on_exit(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
pub fn transform_statements_on_exit(
&mut self,
stmts: &mut ArenaVec<'a, Statement<'a>>,
ctx: &mut TraverseCtx<'a>,
) {
// Remove TS specific statements
stmts.retain(|stmt| match stmt {
Statement::ExpressionStatement(s) => !s.expression.is_typescript_syntax(),
Expand All @@ -410,7 +392,11 @@ impl<'a> TypeScriptAnnotations<'a> {
let is_super_call = matches!(stmt, Statement::ExpressionStatement(ref stmt) if stmt.expression.is_super_call_expression());
new_stmts.push(stmt);
if is_super_call {
new_stmts.extend(self.ctx.ast.copy(&self.assignments));
new_stmts.extend(
self.assignments
.iter()
.map(|assignment| assignment.create_this_property_assignment(ctx)),
);
}
}
self.has_super_call = true;
Expand Down Expand Up @@ -528,3 +514,36 @@ impl<'a> TypeScriptAnnotations<'a> {
self.is_jsx_imports(name)
}
}

struct Assignment<'a> {
span: Span,
name: Atom<'a>,
symbol_id: SymbolId,
}

impl<'a> Assignment<'a> {
// Creates `this.name = name`
fn create_this_property_assignment(&self, ctx: &mut TraverseCtx<'a>) -> Statement<'a> {
let reference_id = ctx.create_bound_reference(
self.name.to_compact_str(),
self.symbol_id,
ReferenceFlag::Read,
);
let id = IdentifierReference::new_read(self.span, self.name.clone(), Some(reference_id));

ctx.ast.expression_statement(
SPAN,
ctx.ast.assignment_expression(
SPAN,
AssignmentOperator::Assign,
ctx.ast.simple_assignment_target_member_expression(ctx.ast.static_member(
SPAN,
ctx.ast.this_expression(SPAN),
IdentifierName::new(self.span, self.name.clone()),
false,
)),
ctx.ast.identifier_reference_expression(id),
),
)
}
}
20 changes: 12 additions & 8 deletions crates/oxc_transformer/src/typescript/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,16 @@ impl<'a> TypeScript<'a> {
self.annotations.transform_jsx_opening_element(elem);
}

pub fn transform_method_definition(
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(def, ctx);
}

pub fn transform_method_definition_on_exit(&mut self, def: &mut MethodDefinition<'a>) {
self.annotations.transform_method_definition_on_exit(def);
self.annotations.transform_method_definition_on_exit(def, ctx);
}

pub fn transform_new_expression(&mut self, expr: &mut NewExpression<'a>) {
Expand All @@ -151,8 +151,12 @@ impl<'a> TypeScript<'a> {
self.annotations.transform_statements(stmts);
}

pub fn transform_statements_on_exit(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
self.annotations.transform_statements_on_exit(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: &TraverseCtx<'a>) {
Expand Down

0 comments on commit 433b11e

Please sign in to comment.