feat(transformer): strip implicit type import for typescript (#1058)

This commit is contained in:
magic-akari 2023-10-26 11:07:30 +08:00 committed by GitHub
parent 59660a53b8
commit 1b64e48ee1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 15 deletions

View file

@ -78,7 +78,8 @@ impl<'a> Transformer<'a> {
scopes: Rc::clone(scopes), scopes: Rc::clone(scopes),
}; };
Self { Self {
typescript: source_type.is_typescript().then(|| TypeScript::new(Rc::clone(&ast))), // TODO: pass verbatim_module_syntax from user config
typescript: source_type.is_typescript().then(|| TypeScript::new(Rc::clone(&ast), ctx.clone(), false)),
react_jsx: options.react_jsx.map(|options| ReactJsx::new(Rc::clone(&ast), options)), react_jsx: options.react_jsx.map(|options| ReactJsx::new(Rc::clone(&ast), options)),
regexp_flags: RegexpFlags::new(Rc::clone(&ast), &options), regexp_flags: RegexpFlags::new(Rc::clone(&ast), &options),
es2022_class_static_block: es2022::ClassStaticBlock::new(Rc::clone(&ast), &options), es2022_class_static_block: es2022::ClassStaticBlock::new(Rc::clone(&ast), &options),

View file

@ -1,20 +1,29 @@
use oxc_ast::{ast::*, AstBuilder}; use oxc_ast::{ast::*, AstBuilder};
use oxc_span::Span; use oxc_span::{Atom, Span};
use std::rc::Rc; use std::rc::Rc;
use crate::context::TransformerCtx;
/// Transform TypeScript /// Transform TypeScript
/// ///
/// References: /// References:
/// * <https://babeljs.io/docs/babel-plugin-transform-typescript> /// * <https://babeljs.io/docs/babel-plugin-transform-typescript>
/// * <https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-typescript> /// * <https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-typescript>
/// * <https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax>
pub struct TypeScript<'a> { pub struct TypeScript<'a> {
ast: Rc<AstBuilder<'a>>, ast: Rc<AstBuilder<'a>>,
ctx: TransformerCtx<'a>,
verbatim_module_syntax: bool,
} }
impl<'a> TypeScript<'a> { impl<'a> TypeScript<'a> {
pub fn new(ast: Rc<AstBuilder<'a>>) -> Self { pub fn new(
Self { ast } ast: Rc<AstBuilder<'a>>,
ctx: TransformerCtx<'a>,
verbatim_module_syntax: bool,
) -> Self {
Self { ast, ctx, verbatim_module_syntax }
} }
#[allow(clippy::unused_self)] #[allow(clippy::unused_self)]
@ -37,13 +46,31 @@ impl<'a> TypeScript<'a> {
ModuleDeclaration::ExportNamedDeclaration(decl) => { ModuleDeclaration::ExportNamedDeclaration(decl) => {
decl.specifiers.retain(|specifier| specifier.export_kind.is_value()); decl.specifiers.retain(|specifier| specifier.export_kind.is_value());
} }
ModuleDeclaration::ImportDeclaration(decl) => { ModuleDeclaration::ImportDeclaration(decl) if decl.import_kind.is_value() => {
if let Some(specifiers) = &mut decl.specifiers { if let Some(specifiers) = &mut decl.specifiers {
specifiers.retain(|specifier| match specifier { specifiers.retain(|specifier| match specifier {
ImportDeclarationSpecifier::ImportSpecifier(s) => { ImportDeclarationSpecifier::ImportSpecifier(s) => {
s.import_kind.is_value() if s.import_kind.is_type() {
return false;
}
if self.verbatim_module_syntax {
return true;
}
self.has_value_references(&s.local.name)
} }
_ => false, ImportDeclarationSpecifier::ImportDefaultSpecifier(s)
if !self.verbatim_module_syntax =>
{
self.has_value_references(&s.local.name)
}
ImportDeclarationSpecifier::ImportNamespaceSpecifier(s)
if !self.verbatim_module_syntax =>
{
self.has_value_references(&s.local.name)
}
_ => true,
}); });
} }
} }
@ -58,19 +85,26 @@ impl<'a> TypeScript<'a> {
if decl.import_kind.is_type() { if decl.import_kind.is_type() {
return false; return false;
} }
if decl.specifiers.as_ref().is_some_and(|specifiers| specifiers.is_empty()) {
// TODO: verbatim_module_syntax if self.verbatim_module_syntax {
return false; return true;
} }
true
!decl.specifiers.as_ref().is_some_and(|specifiers| specifiers.is_empty())
} }
ModuleDeclaration::ExportNamedDeclaration(decl) => { ModuleDeclaration::ExportNamedDeclaration(decl) => {
if decl.export_kind.is_type() { if decl.export_kind.is_type() {
return false; return false;
} }
if self.verbatim_module_syntax {
return true;
}
if decl.declaration.is_none() && decl.specifiers.is_empty() { if decl.declaration.is_none() && decl.specifiers.is_empty() {
return false; return false;
} }
true true
} }
_ => true, _ => true,
@ -92,4 +126,19 @@ impl<'a> TypeScript<'a> {
program.body.push(self.ast.module_declaration(export_decl)); program.body.push(self.ast.module_declaration(export_decl));
} }
} }
fn has_value_references(&self, name: &Atom) -> bool {
let root_scope_id = self.ctx.scopes().root_scope_id();
self.ctx
.scopes()
.get_binding(root_scope_id, name)
.map(|symbol_id| {
self.ctx
.symbols()
.get_resolved_references(symbol_id)
.any(|x| x.is_read() || x.is_write())
})
.unwrap_or_default()
}
} }

View file

@ -1,4 +1,4 @@
Passed: 173/1083 Passed: 175/1083
# All Passed: # All Passed:
* babel-plugin-transform-numeric-separator * babel-plugin-transform-numeric-separator
@ -705,7 +705,7 @@ Passed: 173/1083
* unicode-regex/negated-set/input.js * unicode-regex/negated-set/input.js
* unicode-regex/slash/input.js * unicode-regex/slash/input.js
# babel-plugin-transform-typescript (82/181) # babel-plugin-transform-typescript (84/181)
* class/abstract-class-decorated/input.ts * class/abstract-class-decorated/input.ts
* class/abstract-class-decorated-method/input.ts * class/abstract-class-decorated-method/input.ts
* class/abstract-class-decorated-parameter/input.ts * class/abstract-class-decorated-parameter/input.ts
@ -752,9 +752,7 @@ Passed: 173/1083
* imports/elide-no-import-specifiers/input.ts * imports/elide-no-import-specifiers/input.ts
* imports/elide-preact/input.ts * imports/elide-preact/input.ts
* imports/elide-type-referenced-in-imports-equal-no/input.ts * imports/elide-type-referenced-in-imports-equal-no/input.ts
* imports/elide-typeof/input.ts
* imports/elision/input.ts * imports/elision/input.ts
* imports/elision-export-type/input.ts
* imports/elision-locations/input.ts * imports/elision-locations/input.ts
* imports/elision-rename/input.ts * imports/elision-rename/input.ts
* imports/enum-id/input.ts * imports/enum-id/input.ts