From ad1dcf079adb5e82b81104342eee5c42ebe9966a Mon Sep 17 00:00:00 2001 From: magic-akari Date: Fri, 12 May 2023 15:02:34 +0800 Subject: [PATCH] fix: strip type only ts module --- .../src/strip_type.rs | 103 +++++++++++++++--- 1 file changed, 85 insertions(+), 18 deletions(-) diff --git a/crates/swc_ecma_transforms_typescript/src/strip_type.rs b/crates/swc_ecma_transforms_typescript/src/strip_type.rs index b492a88cac662..406cc9c6a034d 100644 --- a/crates/swc_ecma_transforms_typescript/src/strip_type.rs +++ b/crates/swc_ecma_transforms_typescript/src/strip_type.rs @@ -173,26 +173,10 @@ impl VisitMut for StripType { fn should_retain_module_item(module_item: &ModuleItem) -> bool { match module_item { - ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl)) => !import_decl.type_only, ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(export_decl)) => { should_retain_decl(&export_decl.decl) } - ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(named_export)) => !named_export.type_only, - ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(export_default_decl)) => { - !export_default_decl.decl.is_ts_interface_decl() - } - ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(..)) => true, - ModuleItem::ModuleDecl(ModuleDecl::ExportAll(export_all)) => !export_all.type_only, - ModuleItem::ModuleDecl(ModuleDecl::TsImportEquals(ts_import_equals)) => { - !ts_import_equals.is_type_only - } - ModuleItem::ModuleDecl(ModuleDecl::TsExportAssignment(..)) => true, - ModuleItem::ModuleDecl(ModuleDecl::TsNamespaceExport(..)) => { - // https://www.typescriptlang.org/docs/handbook/modules.html#umd-modules - // `TsNamespaceExport` is only used in UMD dts - false - } - ModuleItem::Stmt(stmt) => !stmt.is_empty(), + _ => !module_item.is_type_only(), } } @@ -204,6 +188,89 @@ fn should_retain_decl(decl: &Decl) -> bool { Decl::TsInterface(..) => false, Decl::TsTypeAlias(..) => false, Decl::TsEnum(ts_enum) => !ts_enum.declare, - Decl::TsModule(ts_module) => !ts_module.declare, + Decl::TsModule(ts_module) => should_retain_ts_module(ts_module), + } +} + +fn should_retain_ts_module(ts_module: &TsModuleDecl) -> bool { + if ts_module.declare || ts_module.global { + return false; + } + + !ts_module.is_type_only() +} + +trait IsTypeOnly { + fn is_type_only(&self) -> bool; +} + +impl IsTypeOnly for TsModuleDecl { + fn is_type_only(&self) -> bool { + self.body + .as_ref() + .map(|body| body.is_type_only()) + .unwrap_or(true) + } +} + +impl IsTypeOnly for TsNamespaceBody { + fn is_type_only(&self) -> bool { + match self { + Self::TsModuleBlock(ts_module_block) => { + ts_module_block.body.iter().all(|item| item.is_type_only()) + } + Self::TsNamespaceDecl(ts_namespace_decl) => ts_namespace_decl.body.is_type_only(), + } + } +} + +impl IsTypeOnly for ModuleItem { + fn is_type_only(&self) -> bool { + match self { + Self::ModuleDecl(module_decl) => module_decl.is_type_only(), + Self::Stmt(stmt) => stmt.is_type_only(), + } + } +} + +impl IsTypeOnly for ModuleDecl { + fn is_type_only(&self) -> bool { + match self { + Self::Import(import_decl) => import_decl.type_only, + Self::ExportDecl(export_decl) => export_decl.decl.is_type_only(), + Self::ExportNamed(named_export) => named_export.type_only, + Self::ExportDefaultDecl(export_default_decl) => { + !export_default_decl.decl.is_ts_interface_decl() + } + Self::ExportDefaultExpr(..) => false, + Self::ExportAll(export_all) => export_all.type_only, + Self::TsImportEquals(ts_import_equals) => ts_import_equals.is_type_only, + Self::TsExportAssignment(..) => false, + Self::TsNamespaceExport(..) => true, + } + } +} + +impl IsTypeOnly for Decl { + fn is_type_only(&self) -> bool { + match self { + Self::TsInterface(..) => true, + Self::TsTypeAlias(..) => true, + Self::Fn(r#fn) => r#fn.function.body.is_none(), + Self::Class(..) => false, + Self::Var(..) => false, + Self::TsEnum(..) => false, + Self::TsModule(ts_module) => ts_module.is_type_only(), + } + } +} + +impl IsTypeOnly for Stmt { + fn is_type_only(&self) -> bool { + match self { + Stmt::Empty(..) => true, + Stmt::Decl(decl) => decl.is_type_only(), + _ => false, + } } }