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),
};
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)),
regexp_flags: RegexpFlags::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_span::Span;
use oxc_span::{Atom, Span};
use std::rc::Rc;
use crate::context::TransformerCtx;
/// Transform TypeScript
///
/// References:
/// * <https://babeljs.io/docs/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> {
ast: Rc<AstBuilder<'a>>,
ctx: TransformerCtx<'a>,
verbatim_module_syntax: bool,
}
impl<'a> TypeScript<'a> {
pub fn new(ast: Rc<AstBuilder<'a>>) -> Self {
Self { ast }
pub fn new(
ast: Rc<AstBuilder<'a>>,
ctx: TransformerCtx<'a>,
verbatim_module_syntax: bool,
) -> Self {
Self { ast, ctx, verbatim_module_syntax }
}
#[allow(clippy::unused_self)]
@ -37,13 +46,31 @@ impl<'a> TypeScript<'a> {
ModuleDeclaration::ExportNamedDeclaration(decl) => {
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 {
specifiers.retain(|specifier| match specifier {
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() {
return false;
}
if decl.specifiers.as_ref().is_some_and(|specifiers| specifiers.is_empty()) {
// TODO: verbatim_module_syntax
return false;
if self.verbatim_module_syntax {
return true;
}
true
!decl.specifiers.as_ref().is_some_and(|specifiers| specifiers.is_empty())
}
ModuleDeclaration::ExportNamedDeclaration(decl) => {
if decl.export_kind.is_type() {
return false;
}
if self.verbatim_module_syntax {
return true;
}
if decl.declaration.is_none() && decl.specifiers.is_empty() {
return false;
}
true
}
_ => true,
@ -92,4 +126,19 @@ impl<'a> TypeScript<'a> {
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:
* babel-plugin-transform-numeric-separator
@ -705,7 +705,7 @@ Passed: 173/1083
* unicode-regex/negated-set/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-method/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-preact/input.ts
* imports/elide-type-referenced-in-imports-equal-no/input.ts
* imports/elide-typeof/input.ts
* imports/elision/input.ts
* imports/elision-export-type/input.ts
* imports/elision-locations/input.ts
* imports/elision-rename/input.ts
* imports/enum-id/input.ts