From f5bf5dece1c78b9407fb9bdc2cb29559a30e19dc Mon Sep 17 00:00:00 2001 From: Dunqing Date: Thu, 18 Jan 2024 23:20:26 +0800 Subject: [PATCH] feat(transformer/typescript): support transform exported TSModuleBlock (#2076) --- crates/oxc_transformer/src/typescript/mod.rs | 54 ++++++++++++++++--- tasks/transform_conformance/babel.snap.md | 6 +-- .../transform_conformance/typescript.snap.md | 8 +++ 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/crates/oxc_transformer/src/typescript/mod.rs b/crates/oxc_transformer/src/typescript/mod.rs index d4a80770f..618a4a005 100644 --- a/crates/oxc_transformer/src/typescript/mod.rs +++ b/crates/oxc_transformer/src/typescript/mod.rs @@ -56,8 +56,21 @@ impl<'a> TypeScript<'a> { pub fn transform_statement(&mut self, stmt: &mut Statement<'a>) { let new_stmt = match stmt { Statement::ModuleDeclaration(module_decl) => { - if let ModuleDeclaration::ExportNamedDeclaration(decl) = &mut **module_decl { - self.transform_export_named_declaration(decl) + if let ModuleDeclaration::ExportNamedDeclaration(export_decl) = &mut **module_decl { + self.transform_export_named_declaration(export_decl).or_else(|| { + export_decl.declaration.as_mut().and_then(|decl| { + if decl.modifiers().is_some_and(Modifiers::is_contains_declare) { + None + } else { + match decl { + Declaration::TSModuleDeclaration(ts_module_decl) => { + Some(self.transform_ts_module_block(ts_module_decl)) + } + _ => None, + } + } + }) + }) } else { None } @@ -579,14 +592,26 @@ impl<'a> TypeScript<'a> { let mut insert_var_decl = vec![]; for (index, stmt) in stmts.iter().enumerate() { - if let Statement::Declaration(Declaration::TSModuleDeclaration(decl)) = stmt { - if !decl.modifiers.is_contains_declare() { - insert_var_decl.push((index, decl.id.name().clone())); + match stmt { + Statement::Declaration(Declaration::TSModuleDeclaration(decl)) => { + if !decl.modifiers.is_contains_declare() { + insert_var_decl.push((index, decl.id.name().clone(), false)); + } } + Statement::ModuleDeclaration(module_decl) => { + if let ModuleDeclaration::ExportNamedDeclaration(decl) = &**module_decl { + if let Some(Declaration::TSModuleDeclaration(decl)) = &decl.declaration { + if !decl.modifiers.is_contains_declare() { + insert_var_decl.push((index, decl.id.name().clone(), true)); + } + } + } + } + _ => {} } } - for (index, name) in insert_var_decl.into_iter().rev() { + for (index, name, is_export) in insert_var_decl.into_iter().rev() { let kind = VariableDeclarationKind::Let; let decls = { let binding_identifier = BindingIdentifier::new(SPAN, name.clone()); @@ -598,8 +623,21 @@ impl<'a> TypeScript<'a> { let variable_declaration = self.ast.variable_declaration(SPAN, kind, decls, Modifiers::empty()); - let stmt = - Statement::Declaration(Declaration::VariableDeclaration(variable_declaration)); + let decl = Declaration::VariableDeclaration(variable_declaration); + + let stmt = if is_export { + self.ast.module_declaration(ModuleDeclaration::ExportNamedDeclaration( + self.ast.export_named_declaration( + SPAN, + Some(decl), + self.ast.new_vec(), + None, + ImportOrExportKind::Value, + ), + )) + } else { + Statement::Declaration(decl) + }; stmts.insert(index, stmt); } } diff --git a/tasks/transform_conformance/babel.snap.md b/tasks/transform_conformance/babel.snap.md index 3edf307df..52e0f1bf9 100644 --- a/tasks/transform_conformance/babel.snap.md +++ b/tasks/transform_conformance/babel.snap.md @@ -1,4 +1,4 @@ -Passed: 316/1179 +Passed: 318/1179 # All Passed: * babel-plugin-transform-numeric-separator @@ -832,7 +832,7 @@ Passed: 316/1179 * general/function-duplicate-name/input.js * general/object/input.js -# babel-plugin-transform-typescript (85/158) +# babel-plugin-transform-typescript (87/158) * class/abstract-class-decorated/input.ts * class/abstract-class-decorated-method/input.ts * class/abstract-class-decorated-parameter/input.ts @@ -874,9 +874,7 @@ Passed: 316/1179 * namespace/clobber-export/input.ts * namespace/clobber-import/input.ts * namespace/contentious-names/input.ts -* namespace/declare/input.ts * namespace/empty-removed/input.ts -* namespace/export/input.ts * namespace/export-type-only/input.ts * namespace/module-nested/input.ts * namespace/module-nested-export/input.ts diff --git a/tasks/transform_conformance/typescript.snap.md b/tasks/transform_conformance/typescript.snap.md index 280fab597..e29c3d1b5 100644 --- a/tasks/transform_conformance/typescript.snap.md +++ b/tasks/transform_conformance/typescript.snap.md @@ -632,6 +632,14 @@ let M6; })(M6 || (M6 = {})); let M6; (function(_M6) { +export let A; + (function(_A) { + var Color = (Color => { + const Yellow = 1; + Color[Color['Yellow'] = Yellow] = 'Yellow'; + return Color; + })(Color || {}); + })(A || (A = {})); var t = A.Color.Yellow; t = A.Color.Red; })(M6 || (M6 = {}));