Skip to content

Commit

Permalink
strip type
Browse files Browse the repository at this point in the history
  • Loading branch information
magic-akari committed Apr 7, 2023
1 parent 07a688f commit 1bcc8eb
Show file tree
Hide file tree
Showing 4 changed files with 345 additions and 6 deletions.
2 changes: 1 addition & 1 deletion crates/swc_ecma_transforms_typescript/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ pub mod strip;
mod strip_import;
mod strip_type;
mod transform;
mod typescript;
pub mod typescript;
290 changes: 287 additions & 3 deletions crates/swc_ecma_transforms_typescript/src/strip_type.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,291 @@
use swc_ecma_visit::VisitMut;
use swc_common::{collections::AHashSet, util::take::Take};
use swc_ecma_ast::*;
use swc_ecma_visit::{VisitMut, VisitMutWith};

/// This Module will strip all types/generics/interface/declares
/// and type import/export
pub(crate) struct StripType;
#[derive(Default)]
pub(crate) struct StripType {
type_id: AHashSet<Id>,
}

impl VisitMut for StripType {}
impl VisitMut for StripType {
fn visit_mut_accessibility(&mut self, _: &mut Accessibility) {
unreachable!()
}

fn visit_mut_true_plus_minus(&mut self, _: &mut TruePlusMinus) {
unreachable!()
}

fn visit_mut_ts_array_type(&mut self, _: &mut TsArrayType) {
unreachable!()
}

fn visit_mut_ts_call_signature_decl(&mut self, _: &mut TsCallSignatureDecl) {
unreachable!()
}

fn visit_mut_ts_conditional_type(&mut self, _: &mut TsConditionalType) {
unreachable!()
}

fn visit_mut_ts_construct_signature_decl(&mut self, _: &mut TsConstructSignatureDecl) {
unreachable!()
}

fn visit_mut_ts_constructor_type(&mut self, _: &mut TsConstructorType) {
unreachable!()
}

fn visit_mut_ts_entity_name(&mut self, _: &mut TsEntityName) {
unreachable!()
}

fn visit_mut_ts_external_module_ref(&mut self, _: &mut TsExternalModuleRef) {
unreachable!()
}

fn visit_mut_ts_fn_or_constructor_type(&mut self, _: &mut TsFnOrConstructorType) {
unreachable!()
}

fn visit_mut_ts_fn_param(&mut self, _: &mut TsFnParam) {
unreachable!()
}

fn visit_mut_ts_fn_type(&mut self, _: &mut TsFnType) {
unreachable!()
}

fn visit_mut_ts_import_type(&mut self, _: &mut TsImportType) {
unreachable!()
}

fn visit_mut_ts_index_signature(&mut self, _: &mut TsIndexSignature) {
unreachable!()
}

fn visit_mut_ts_indexed_access_type(&mut self, _: &mut TsIndexedAccessType) {
unreachable!()
}

fn visit_mut_ts_infer_type(&mut self, _: &mut TsInferType) {
unreachable!()
}

fn visit_mut_ts_interface_body(&mut self, _: &mut TsInterfaceBody) {
unreachable!()
}

fn visit_mut_ts_interface_decl(&mut self, _: &mut TsInterfaceDecl) {
unreachable!()
}

fn visit_mut_ts_intersection_type(&mut self, _: &mut TsIntersectionType) {
unreachable!()
}

fn visit_mut_ts_keyword_type(&mut self, _: &mut TsKeywordType) {
unreachable!()
}

fn visit_mut_ts_keyword_type_kind(&mut self, _: &mut TsKeywordTypeKind) {
unreachable!()
}

fn visit_mut_ts_mapped_type(&mut self, _: &mut TsMappedType) {
unreachable!()
}

fn visit_mut_ts_method_signature(&mut self, _: &mut TsMethodSignature) {
unreachable!()
}

fn visit_mut_ts_module_ref(&mut self, _: &mut TsModuleRef) {
unreachable!()
}

fn visit_mut_ts_optional_type(&mut self, _: &mut TsOptionalType) {
unreachable!()
}

fn visit_mut_ts_parenthesized_type(&mut self, _: &mut TsParenthesizedType) {
unreachable!()
}

fn visit_mut_ts_property_signature(&mut self, _: &mut TsPropertySignature) {
unreachable!()
}

fn visit_mut_ts_qualified_name(&mut self, _: &mut TsQualifiedName) {
unreachable!()
}

fn visit_mut_ts_rest_type(&mut self, _: &mut TsRestType) {
unreachable!()
}

fn visit_mut_ts_this_type(&mut self, _: &mut TsThisType) {
unreachable!()
}

fn visit_mut_ts_this_type_or_ident(&mut self, _: &mut TsThisTypeOrIdent) {
unreachable!()
}

fn visit_mut_ts_tuple_type(&mut self, _: &mut TsTupleType) {
unreachable!()
}

fn visit_mut_ts_type(&mut self, _: &mut TsType) {
unreachable!()
}

fn visit_mut_ts_type_alias_decl(&mut self, _: &mut TsTypeAliasDecl) {
unreachable!()
}

fn visit_mut_ts_type_ann(&mut self, _: &mut TsTypeAnn) {
unreachable!()
}

fn visit_mut_ts_type_element(&mut self, _: &mut TsTypeElement) {
unreachable!()
}

fn visit_mut_ts_type_lit(&mut self, _: &mut TsTypeLit) {
unreachable!()
}

fn visit_mut_ts_type_operator(&mut self, _: &mut TsTypeOperator) {
unreachable!()
}

fn visit_mut_ts_type_operator_op(&mut self, _: &mut TsTypeOperatorOp) {
unreachable!()
}

fn visit_mut_ts_type_param(&mut self, _: &mut TsTypeParam) {
unreachable!()
}

fn visit_mut_ts_type_param_decl(&mut self, _: &mut TsTypeParamDecl) {
unreachable!()
}

fn visit_mut_ts_type_param_instantiation(&mut self, _: &mut TsTypeParamInstantiation) {
unreachable!()
}

fn visit_mut_ts_type_predicate(&mut self, _: &mut TsTypePredicate) {
unreachable!()
}

fn visit_mut_ts_type_query(&mut self, _: &mut TsTypeQuery) {
unreachable!()
}

fn visit_mut_ts_type_query_expr(&mut self, _: &mut TsTypeQueryExpr) {
unreachable!()
}

fn visit_mut_ts_type_ref(&mut self, _: &mut TsTypeRef) {
unreachable!()
}

fn visit_mut_ts_union_or_intersection_type(&mut self, _: &mut TsUnionOrIntersectionType) {
unreachable!()
}

fn visit_mut_ts_union_type(&mut self, _: &mut TsUnionType) {
unreachable!()
}

fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {
n.retain(|module_item| match module_item {
ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl)) => !import_decl.type_only,
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(export_decl)) => {
match &export_decl.decl {
Decl::Class(class) => !class.declare,
Decl::Fn(r#fn) => !r#fn.declare,
Decl::Var(var) => !var.declare,
Decl::TsInterface(..) => false,
Decl::TsTypeAlias(..) => false,
Decl::TsEnum(ts_enum) => !ts_enum.declare,
Decl::TsModule(ts_module) => !ts_module.declare,
}
}
ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(export_named)) => {
!export_named.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(..) => true,
});

n.visit_mut_children_with(self);

n.retain(|module_item| !matches!(module_item, ModuleItem::Stmt(Stmt::Empty(empty)) if empty.span.is_dummy()))
}

fn visit_mut_stmts(&mut self, n: &mut Vec<Stmt>) {
n.visit_mut_children_with(self);

n.retain(|stmt| !matches!(stmt, Stmt::Empty(empty) if empty.span.is_dummy()));
}

fn visit_mut_stmt(&mut self, n: &mut Stmt) {
let retain = match n {
Stmt::Block(..)
| Stmt::Empty(..)
| Stmt::Debugger(..)
| Stmt::With(..)
| Stmt::Return(..)
| Stmt::Labeled(..)
| Stmt::Break(..)
| Stmt::Continue(..)
| Stmt::If(..)
| Stmt::Switch(..)
| Stmt::Throw(..)
| Stmt::Try(..)
| Stmt::While(..)
| Stmt::DoWhile(..)
| Stmt::For(..)
| Stmt::ForIn(..)
| Stmt::ForOf(..)
| Stmt::Expr(..) => true,
Stmt::Decl(decl) => match decl {
Decl::Class(class) => !class.declare,
Decl::Fn(r#fn) => !r#fn.declare,
Decl::Var(var) => !var.declare,
Decl::TsInterface(ts_interface) => {
self.type_id.insert(ts_interface.id.to_id());
false
}
Decl::TsTypeAlias(ts_type_alias) => {
self.type_id.insert(ts_type_alias.id.to_id());
false
}
Decl::TsEnum(ts_enum) => !ts_enum.declare,
Decl::TsModule(ts_module) => !ts_module.declare,
},
};

if !retain {
n.take();
}
}
}
8 changes: 6 additions & 2 deletions crates/swc_ecma_transforms_typescript/src/typescript.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};
use swc_ecma_ast::*;
use swc_ecma_visit::{VisitMut, VisitMutWith, VisitWith};
use swc_ecma_visit::{as_folder, Fold, VisitMut, VisitMutWith, VisitWith};

use crate::{
collect::Collect, strip_import::StripImport, strip_type::StripType, transform::Transform,
Expand Down Expand Up @@ -35,6 +35,10 @@ pub struct Config {
pub import_export_assign_config: TsImportExportAssignConfig,
}

pub fn typescript(config: Config) -> impl Fold + VisitMut {
as_folder(TypeScript { config })
}

pub(crate) struct TypeScript {
pub config: Config,
}
Expand All @@ -44,7 +48,7 @@ impl VisitMut for TypeScript {
// https://tc39.es/proposal-type-annotations
// It's possible to keep type in JavaScript.
// We may skip this step or transform TS type to JS type in the future.
n.visit_mut_with(&mut StripType);
n.visit_mut_with(&mut StripType::default());

if !self.config.verbatim_module_syntax {
n.visit_with(&mut Collect);
Expand Down
51 changes: 51 additions & 0 deletions crates/swc_ecma_transforms_typescript/tests/typescript.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use std::path::PathBuf;

use swc_common::{chain, pass::Optional, Mark};
use swc_ecma_parser::{Syntax, TsConfig};
use swc_ecma_transforms_base::resolver;
use swc_ecma_transforms_proposal::decorators;
use swc_ecma_transforms_testing::test_fixture;
use swc_ecma_transforms_typescript::typescript;
use swc_ecma_visit::Fold;

fn tr() -> impl Fold {
tr_config(None, None)
}

fn tr_config(
config: Option<typescript::Config>,
decorators_config: Option<decorators::Config>,
) -> impl Fold {
let unresolved_mark = Mark::new();
let top_level_mark = Mark::new();
let has_decorators = decorators_config.is_some();
let config = config.unwrap_or_else(|| typescript::Config {
no_empty_export: true,
..Default::default()
});

chain!(
Optional::new(
decorators(decorators_config.unwrap_or_default()),
has_decorators,
),
resolver(unresolved_mark, top_level_mark, true),
typescript::typescript(config),
)
}

#[testing::fixture("tests/fixture/**/input.ts")]
#[testing::fixture("tests/fixture/**/input.tsx")]
fn typescript_fixture_new(input: PathBuf) {
let output = input.with_file_name("output.js");
test_fixture(
Syntax::Typescript(TsConfig {
tsx: input.to_string_lossy().ends_with(".tsx"),
..Default::default()
}),
&|_t| tr(),
&input,
&output,
Default::default(),
);
}

0 comments on commit 1bcc8eb

Please sign in to comment.