Skip to content

Commit 7b28fb0

Browse files
committed
refactor(transformer/typescript): remove unnecessary specific handling of TSModuledDeclaration transformation
1 parent efaa721 commit 7b28fb0

File tree

9 files changed

+162
-490
lines changed

9 files changed

+162
-490
lines changed

crates/oxc_syntax/src/symbol.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,11 @@ impl SymbolFlags {
255255
self.contains(Self::Ambient)
256256
}
257257

258+
#[inline]
259+
pub fn is_namespace(&self) -> bool {
260+
self.contains(Self::NameSpaceModule)
261+
}
262+
258263
/// If true, then the symbol can be referenced by a type reference
259264
#[inline]
260265
pub fn can_be_referenced_by_type(&self) -> bool {

crates/oxc_transformer/src/lib.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -307,16 +307,6 @@ impl<'a> Traverse<'a> for TransformerImpl<'a, '_> {
307307
self.x2_es2022.exit_static_block(block, ctx);
308308
}
309309

310-
fn enter_ts_module_declaration(
311-
&mut self,
312-
decl: &mut TSModuleDeclaration<'a>,
313-
ctx: &mut TraverseCtx<'a>,
314-
) {
315-
if let Some(typescript) = self.x0_typescript.as_mut() {
316-
typescript.enter_ts_module_declaration(decl, ctx);
317-
}
318-
}
319-
320310
#[inline]
321311
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
322312
self.common.enter_expression(expr, ctx);

crates/oxc_transformer/src/typescript/annotations.rs

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use rustc_hash::FxHashSet;
2-
31
use oxc_allocator::{TakeIn, Vec as ArenaVec};
42
use oxc_ast::ast::*;
53
use oxc_diagnostics::OxcDiagnostic;
@@ -29,7 +27,6 @@ pub struct TypeScriptAnnotations<'a, 'ctx> {
2927
has_jsx_fragment: bool,
3028
jsx_element_import_name: String,
3129
jsx_fragment_import_name: String,
32-
type_identifier_names: FxHashSet<Atom<'a>>,
3330
}
3431

3532
impl<'a, 'ctx> TypeScriptAnnotations<'a, 'ctx> {
@@ -55,7 +52,6 @@ impl<'a, 'ctx> TypeScriptAnnotations<'a, 'ctx> {
5552
has_jsx_fragment: false,
5653
jsx_element_import_name,
5754
jsx_fragment_import_name,
58-
type_identifier_names: FxHashSet::default(),
5955
}
6056
}
6157
}
@@ -79,7 +75,7 @@ impl<'a> Traverse<'a> for TypeScriptAnnotations<'a, '_> {
7975
true
8076
} else {
8177
decl.specifiers
82-
.retain(|specifier| self.can_retain_export_specifier(specifier, ctx));
78+
.retain(|specifier| Self::can_retain_export_specifier(specifier, ctx));
8379
// Keep the export declaration if there are still specifiers after removing type exports
8480
!decl.specifiers.is_empty()
8581
}
@@ -456,8 +452,6 @@ impl<'a> Traverse<'a> for TypeScriptAnnotations<'a, '_> {
456452
// Remove TS specific statements
457453
stmts.retain(|stmt| match stmt {
458454
Statement::ExpressionStatement(s) => !s.expression.is_typescript_syntax(),
459-
// Any namespaces left after namespace transform are type only, so remove them
460-
Statement::TSModuleDeclaration(_) => false,
461455
match_declaration!(Statement) => !stmt.to_declaration().is_typescript_syntax(),
462456
// Ignore ModuleDeclaration as it's handled in the program
463457
_ => true,
@@ -548,17 +542,6 @@ impl<'a> Traverse<'a> for TypeScriptAnnotations<'a, '_> {
548542
fn enter_jsx_fragment(&mut self, _elem: &mut JSXFragment<'a>, _ctx: &mut TraverseCtx<'a>) {
549543
self.has_jsx_fragment = true;
550544
}
551-
552-
fn enter_ts_module_declaration(
553-
&mut self,
554-
decl: &mut TSModuleDeclaration<'a>,
555-
_ctx: &mut TraverseCtx<'a>,
556-
) {
557-
// NB: Namespace transform happens in `enter_program` visitor, and replaces retained
558-
// namespaces with functions. This visitor is called after, by which time any remaining
559-
// namespaces need to be deleted.
560-
self.type_identifier_names.insert(decl.id.name());
561-
}
562545
}
563546

564547
impl<'a> TypeScriptAnnotations<'a, '_> {
@@ -615,14 +598,8 @@ impl<'a> TypeScriptAnnotations<'a, '_> {
615598
self.is_jsx_imports(&id.name)
616599
}
617600

618-
fn can_retain_export_specifier(
619-
&self,
620-
specifier: &ExportSpecifier<'a>,
621-
ctx: &TraverseCtx<'a>,
622-
) -> bool {
623-
if specifier.export_kind.is_type()
624-
|| self.type_identifier_names.contains(&specifier.exported.name())
625-
{
601+
fn can_retain_export_specifier(specifier: &ExportSpecifier<'a>, ctx: &TraverseCtx<'a>) -> bool {
602+
if specifier.export_kind.is_type() {
626603
return false;
627604
}
628605
!matches!(&specifier.local, ModuleExportName::IdentifierReference(ident) if Self::is_refers_to_type(ident, ctx))

crates/oxc_transformer/src/typescript/mod.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,6 @@ impl<'a> Traverse<'a> for TypeScript<'a, '_> {
118118
self.annotations.enter_class_body(body, ctx);
119119
}
120120

121-
fn enter_ts_module_declaration(
122-
&mut self,
123-
decl: &mut TSModuleDeclaration<'a>,
124-
ctx: &mut TraverseCtx<'a>,
125-
) {
126-
self.annotations.enter_ts_module_declaration(decl, ctx);
127-
}
128-
129121
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
130122
self.annotations.enter_expression(expr, ctx);
131123
}

crates/oxc_transformer/src/typescript/namespace.rs

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use oxc_allocator::{Box as ArenaBox, TakeIn, Vec as ArenaVec};
22
use oxc_ast::{NONE, ast::*};
33
use oxc_ecmascript::BoundNames;
4-
use oxc_semantic::Reference;
54
use oxc_span::SPAN;
65
use oxc_syntax::{
76
operator::{AssignmentOperator, LogicalOperator},
@@ -22,24 +21,18 @@ pub struct TypeScriptNamespace<'a, 'ctx> {
2221

2322
// Options
2423
allow_namespaces: bool,
25-
only_remove_type_imports: bool,
2624
}
2725

2826
impl<'a, 'ctx> TypeScriptNamespace<'a, 'ctx> {
2927
pub fn new(options: &TypeScriptOptions, ctx: &'ctx TransformCtx<'a>) -> Self {
30-
Self {
31-
ctx,
32-
allow_namespaces: options.allow_namespaces,
33-
only_remove_type_imports: options.only_remove_type_imports,
34-
}
28+
Self { ctx, allow_namespaces: options.allow_namespaces }
3529
}
3630
}
3731

3832
impl<'a> Traverse<'a> for TypeScriptNamespace<'a, '_> {
3933
// `namespace Foo { }` -> `let Foo; (function (_Foo) { })(Foo || (Foo = {}));`
4034
fn enter_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
4135
// namespace declaration is only allowed at the top level
42-
4336
if !has_namespace(program.body.as_slice()) {
4437
return;
4538
}
@@ -59,14 +52,12 @@ impl<'a> Traverse<'a> for TypeScriptNamespace<'a, '_> {
5952
self.handle_nested(decl, /* is_export */ false, &mut new_stmts, None, ctx);
6053
continue;
6154
}
62-
Statement::ExportNamedDeclaration(export_decl) => {
63-
if export_decl.declaration.as_ref().is_none_or(|decl| {
64-
decl.declare() || !matches!(decl, Declaration::TSModuleDeclaration(_))
65-
}) {
66-
new_stmts.push(Statement::ExportNamedDeclaration(export_decl));
67-
continue;
68-
}
69-
55+
Statement::ExportNamedDeclaration(export_decl)
56+
if export_decl.declaration.as_ref().is_some_and(|declaration| {
57+
!declaration.declare()
58+
&& matches!(declaration, Declaration::TSModuleDeclaration(_))
59+
}) =>
60+
{
7061
let Some(Declaration::TSModuleDeclaration(decl)) =
7162
export_decl.unbox().declaration
7263
else {
@@ -111,6 +102,11 @@ impl<'a> TypeScriptNamespace<'a, '_> {
111102
return;
112103
};
113104

105+
// Empty namespace or only have type declarations.
106+
if ctx.scoping().symbol_flags(ident.symbol_id()).is_namespace() {
107+
return;
108+
}
109+
114110
let Some(body) = body else {
115111
return;
116112
};
@@ -151,7 +147,6 @@ impl<'a> TypeScriptNamespace<'a, '_> {
151147
match stmt {
152148
Statement::TSModuleDeclaration(decl) => {
153149
self.handle_nested(decl, /* is_export */ false, &mut new_stmts, None, ctx);
154-
continue;
155150
}
156151
Statement::ExportNamedDeclaration(export_decl) => {
157152
// NB: `ExportNamedDeclaration` with no declaration (e.g. `export {x}`) is not
@@ -214,33 +209,9 @@ impl<'a> TypeScriptNamespace<'a, '_> {
214209
_ => {}
215210
}
216211
}
217-
continue;
218212
}
219-
// Retain when `only_remove_type_imports` is true or there are value references
220-
// The behavior is the same as `TypeScriptModule::transform_ts_import_equals`
221-
Statement::TSImportEqualsDeclaration(decl)
222-
if !self.only_remove_type_imports
223-
&& ctx
224-
.scoping()
225-
.get_resolved_references(decl.id.symbol_id())
226-
.all(Reference::is_type) =>
227-
{
228-
continue;
229-
}
230-
Statement::TSTypeAliasDeclaration(_) | Statement::TSInterfaceDeclaration(_) => {
231-
continue;
232-
}
233-
_ => {}
213+
_ => new_stmts.push(stmt),
234214
}
235-
new_stmts.push(stmt);
236-
}
237-
238-
if new_stmts.is_empty() {
239-
// Delete the scope binding that `ctx.generate_uid` created above,
240-
// as no binding is actually being created
241-
ctx.scoping_mut().remove_binding(scope_id, uid_binding.name.as_str());
242-
243-
return;
244215
}
245216

246217
if !Self::is_redeclaration_namespace(&ident, ctx) {

0 commit comments

Comments
 (0)