Skip to content

Commit

Permalink
fix(transformer): remove typescript symbols after transformation
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Nov 17, 2024
1 parent 44fd962 commit 8661c0c
Show file tree
Hide file tree
Showing 7 changed files with 2,955 additions and 8,261 deletions.
41 changes: 39 additions & 2 deletions crates/oxc_ecmascript/src/bound_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use oxc_ast::ast::{
ArrayPattern, AssignmentPattern, BindingIdentifier, BindingPattern, BindingPatternKind,
BindingRestElement, Class, Declaration, ExportNamedDeclaration, FormalParameter,
FormalParameters, Function, ImportDeclaration, ImportDeclarationSpecifier, ModuleDeclaration,
ObjectPattern, VariableDeclaration,
ObjectPattern, TSEnumDeclaration, TSImportEqualsDeclaration, TSInterfaceDeclaration,
TSModuleDeclaration, TSModuleDeclarationName, TSTypeAliasDeclaration, VariableDeclaration,
};

/// [`BoundName`](https://tc39.es/ecma262/#sec-static-semantics-boundnames)
Expand Down Expand Up @@ -82,7 +83,11 @@ impl<'a> BoundNames<'a> for Declaration<'a> {
Declaration::VariableDeclaration(decl) => decl.bound_names(f),
Declaration::FunctionDeclaration(func) => func.bound_names(f),
Declaration::ClassDeclaration(decl) => decl.bound_names(f),
_ => {}
Declaration::TSInterfaceDeclaration(decl) => decl.bound_names(f),
Declaration::TSEnumDeclaration(decl) => decl.bound_names(f),
Declaration::TSTypeAliasDeclaration(decl) => decl.bound_names(f),
Declaration::TSImportEqualsDeclaration(decl) => decl.bound_names(f),
Declaration::TSModuleDeclaration(decl) => decl.bound_names(f),
}
}
}
Expand Down Expand Up @@ -166,3 +171,35 @@ impl<'a> BoundNames<'a> for ExportNamedDeclaration<'a> {
}
}
}

impl<'a> BoundNames<'a> for TSInterfaceDeclaration<'a> {
fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
self.id.bound_names(f);
}
}

impl<'a> BoundNames<'a> for TSEnumDeclaration<'a> {
fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
self.id.bound_names(f);
}
}

impl<'a> BoundNames<'a> for TSTypeAliasDeclaration<'a> {
fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
self.id.bound_names(f);
}
}

impl<'a> BoundNames<'a> for TSImportEqualsDeclaration<'a> {
fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
self.id.bound_names(f);
}
}

impl<'a> BoundNames<'a> for TSModuleDeclaration<'a> {
fn bound_names<F: FnMut(&BindingIdentifier<'a>)>(&self, f: &mut F) {
if let TSModuleDeclarationName::Identifier(ident) = &self.id {
ident.bound_names(f);
}
}
}
46 changes: 34 additions & 12 deletions crates/oxc_transformer/src/typescript/annotations.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use oxc_ecmascript::BoundNames;
use rustc_hash::FxHashSet;

use oxc_allocator::Vec as ArenaVec;
Expand Down Expand Up @@ -65,10 +66,18 @@ impl<'a, 'ctx> Traverse<'a> for TypeScriptAnnotations<'a, 'ctx> {
let mut no_modules_remaining = true;
let mut some_modules_deleted = false;

let scope_id = ctx.current_scope_id();
program.body.retain_mut(|stmt| {
let need_retain = match stmt {
Statement::ExportNamedDeclaration(decl) if decl.declaration.is_some() => {
decl.declaration.as_ref().is_some_and(|decl| !decl.is_typescript_syntax())
let keep =
decl.declaration.as_ref().is_some_and(|decl| !decl.is_typescript_syntax());
if !keep {
decl.bound_names(&mut |ident| {
ctx.scopes_mut().remove_binding(scope_id, &ident.name.clone().into());
});
}
keep
}
Statement::ExportNamedDeclaration(decl) => {
if decl.export_kind.is_type() {
Expand Down Expand Up @@ -381,18 +390,21 @@ impl<'a, 'ctx> Traverse<'a> for TypeScriptAnnotations<'a, 'ctx> {
fn enter_statements(
&mut self,
stmts: &mut ArenaVec<'a, Statement<'a>>,
_ctx: &mut TraverseCtx<'a>,
ctx: &mut TraverseCtx<'a>,
) {
let scope_id = ctx.current_scope_id();
// Remove declare declaration
stmts.retain(
|stmt| {
if let Some(decl) = stmt.as_declaration() {
!decl.declare()
} else {
true
stmts.retain(|stmt| {
if let Some(decl) = stmt.as_declaration() {
if decl.declare() {
decl.bound_names(&mut |ident| {
ctx.scopes_mut().remove_binding(scope_id, &ident.name.clone().into());
});
return false;
}
},
);
}
true
});
}

fn exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) {
Expand All @@ -419,14 +431,24 @@ impl<'a, 'ctx> Traverse<'a> for TypeScriptAnnotations<'a, 'ctx> {
fn exit_statements(
&mut self,
stmts: &mut ArenaVec<'a, Statement<'a>>,
_ctx: &mut TraverseCtx<'a>,
ctx: &mut TraverseCtx<'a>,
) {
let scope_id = ctx.current_scope_id();
// Remove TS specific statements
stmts.retain(|stmt| match stmt {
Statement::ExpressionStatement(s) => !s.expression.is_typescript_syntax(),
// Any namespaces left after namespace transform are type only, so remove them
Statement::TSModuleDeclaration(_) => false,
match_declaration!(Statement) => !stmt.to_declaration().is_typescript_syntax(),
match_declaration!(Statement) => {
let decl = stmt.to_declaration();
if decl.is_typescript_syntax() {
decl.bound_names(&mut |ident| {
ctx.scopes_mut().remove_binding(scope_id, &ident.name.clone().into());
});
return false;
}
true
}
// Ignore ModuleDeclaration as it's handled in the program
_ => true,
});
Expand Down
Loading

0 comments on commit 8661c0c

Please sign in to comment.