feat(transformer): start on TypeScript annotation removal (#2951)

This commit is contained in:
Miles Johnson 2024-04-13 03:49:54 -07:00 committed by GitHub
parent 93ce5a919a
commit e67355045e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 564 additions and 26 deletions

View file

@ -113,6 +113,17 @@ pub enum Expression<'a> {
} }
impl<'a> Expression<'a> { impl<'a> Expression<'a> {
pub fn is_typescript_syntax(&self) -> bool {
matches!(
self,
Self::TSAsExpression(_)
| Self::TSSatisfiesExpression(_)
| Self::TSTypeAssertion(_)
| Self::TSNonNullExpression(_)
| Self::TSInstantiationExpression(_)
)
}
pub fn is_primary_expression(&self) -> bool { pub fn is_primary_expression(&self) -> bool {
self.is_literal() self.is_literal()
|| matches!( || matches!(
@ -1289,6 +1300,7 @@ impl<'a> Declaration<'a> {
_ => true, _ => true,
} }
} }
pub fn modifiers(&self) -> Option<&Modifiers<'a>> { pub fn modifiers(&self) -> Option<&Modifiers<'a>> {
match self { match self {
Declaration::VariableDeclaration(decl) => Some(&decl.modifiers), Declaration::VariableDeclaration(decl) => Some(&decl.modifiers),
@ -1659,6 +1671,10 @@ impl<'a> BindingPattern<'a> {
pub fn new_with_kind(kind: BindingPatternKind<'a>) -> Self { pub fn new_with_kind(kind: BindingPatternKind<'a>) -> Self {
Self { kind, type_annotation: None, optional: false } Self { kind, type_annotation: None, optional: false }
} }
pub fn get_identifier(&self) -> Option<&Atom<'a>> {
self.kind.get_identifier()
}
} }
#[derive(Debug, Hash)] #[derive(Debug, Hash)]
@ -1679,6 +1695,14 @@ pub enum BindingPatternKind<'a> {
} }
impl<'a> BindingPatternKind<'a> { impl<'a> BindingPatternKind<'a> {
pub fn get_identifier(&self) -> Option<&Atom<'a>> {
match self {
Self::BindingIdentifier(ident) => Some(&ident.name),
Self::AssignmentPattern(assign) => assign.left.get_identifier(),
_ => None,
}
}
pub fn is_destructuring_pattern(&self) -> bool { pub fn is_destructuring_pattern(&self) -> bool {
matches!(self, Self::ObjectPattern(_) | Self::ArrayPattern(_)) matches!(self, Self::ObjectPattern(_) | Self::ArrayPattern(_))
} }
@ -1809,8 +1833,10 @@ pub struct Function<'a> {
impl<'a> Function<'a> { impl<'a> Function<'a> {
pub fn is_typescript_syntax(&self) -> bool { pub fn is_typescript_syntax(&self) -> bool {
self.r#type == FunctionType::TSDeclareFunction matches!(
|| self.body.is_none() self.r#type,
FunctionType::TSDeclareFunction | FunctionType::TSEmptyBodyFunctionExpression
) || self.body.is_none()
|| self.modifiers.contains(ModifierKind::Declare) || self.modifiers.contains(ModifierKind::Declare)
} }

View file

@ -1007,6 +1007,12 @@ pub enum ModifierKind {
Override, Override,
} }
impl ModifierKind {
pub fn is_typescript_syntax(&self) -> bool {
!matches!(self, Self::Async | Self::Default | Self::Export | Self::Static)
}
}
#[derive(Debug, Hash)] #[derive(Debug, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))] #[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
@ -1043,6 +1049,12 @@ impl<'a> Modifiers<'a> {
pub fn is_contains_declare(&self) -> bool { pub fn is_contains_declare(&self) -> bool {
self.contains(ModifierKind::Declare) self.contains(ModifierKind::Declare)
} }
pub fn remove_type_modifiers(&mut self) {
if let Some(list) = &mut self.0 {
list.retain(|m| !m.kind.is_typescript_syntax());
}
}
} }
/// Export Assignment in non-module files /// Export Assignment in non-module files

View file

@ -51,6 +51,11 @@ impl<'a> AstBuilder<'a> {
vec vec
} }
#[inline]
pub fn new_vec_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> Vec<'a, T> {
Vec::from_iter_in(iter, self.allocator)
}
#[inline] #[inline]
pub fn new_str(&self, value: &str) -> &'a str { pub fn new_str(&self, value: &str) -> &'a str {
String::from_str_in(value, self.allocator).into_bump_str() String::from_str_in(value, self.allocator).into_bump_str()
@ -210,6 +215,14 @@ impl<'a> AstBuilder<'a> {
Expression::TemplateLiteral(self.alloc(literal)) Expression::TemplateLiteral(self.alloc(literal))
} }
pub fn identifier_name(&self, span: Span, name: &str) -> IdentifierName<'a> {
IdentifierName::new(span, self.new_atom(name))
}
pub fn identifier_reference(&self, span: Span, name: &str) -> IdentifierReference<'a> {
IdentifierReference::new(span, self.new_atom(name))
}
pub fn identifier_reference_expression( pub fn identifier_reference_expression(
&self, &self,
ident: IdentifierReference<'a>, ident: IdentifierReference<'a>,
@ -1195,6 +1208,22 @@ impl<'a> AstBuilder<'a> {
}) })
} }
pub fn plain_export_named_declaration(
&self,
span: Span,
specifiers: Vec<'a, ExportSpecifier<'a>>,
source: Option<StringLiteral<'a>>,
) -> Box<'a, ExportNamedDeclaration<'a>> {
self.export_named_declaration(
span,
None,
specifiers,
source,
ImportOrExportKind::Value,
None,
)
}
/* ---------- JSX ----------------- */ /* ---------- JSX ----------------- */
pub fn jsx_element( pub fn jsx_element(
&self, &self,

View file

@ -77,38 +77,135 @@ impl<'a> Transformer<'a> {
} }
impl<'a> VisitMut<'a> for Transformer<'a> { impl<'a> VisitMut<'a> for Transformer<'a> {
fn visit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) { fn visit_program(&mut self, program: &mut Program<'a>) {
self.x0_typescript.transform_statements(stmts); walk_mut::walk_program_mut(self, program);
walk_mut::walk_statements_mut(self, stmts);
self.x0_typescript.transform_program_on_exit(program);
} }
fn visit_statement(&mut self, stmt: &mut Statement<'a>) { // ALPHASORT
self.x2_decorators.transform_statement(stmt);
walk_mut::walk_statement_mut(self, stmt); fn visit_arrow_expression(&mut self, expr: &mut ArrowFunctionExpression<'a>) {
self.x0_typescript.transform_arrow_expression(expr);
walk_mut::walk_arrow_expression_mut(self, expr);
} }
fn visit_expression(&mut self, expr: &mut Expression<'a>) { fn visit_binding_pattern(&mut self, pat: &mut BindingPattern<'a>) {
self.x1_react.transform_expression(expr); self.x0_typescript.transform_binding_pattern(pat);
walk_mut::walk_expression_mut(self, expr);
walk_mut::walk_binding_pattern_mut(self, pat);
} }
fn visit_variable_declarator(&mut self, declarator: &mut VariableDeclarator<'a>) { fn visit_call_expression(&mut self, expr: &mut CallExpression<'a>) {
self.x1_react.transform_variable_declarator(declarator); self.x0_typescript.transform_call_expression(expr);
walk_mut::walk_variable_declarator_mut(self, declarator);
walk_mut::walk_call_expression_mut(self, expr);
} }
fn visit_object_property(&mut self, prop: &mut ObjectProperty<'a>) { fn visit_class(&mut self, class: &mut Class<'a>) {
self.x1_react.transform_object_property(prop); self.x0_typescript.transform_class(class);
walk_mut::walk_object_property_mut(self, prop);
walk_mut::walk_class_mut(self, class);
}
fn visit_class_body(&mut self, body: &mut ClassBody<'a>) {
self.x0_typescript.transform_class_body(body);
walk_mut::walk_class_body_mut(self, body);
} }
fn visit_export_default_declaration(&mut self, decl: &mut ExportDefaultDeclaration<'a>) { fn visit_export_default_declaration(&mut self, decl: &mut ExportDefaultDeclaration<'a>) {
self.x1_react.transform_export_default_declaration(decl); self.x1_react.transform_export_default_declaration(decl);
walk_mut::walk_export_default_declaration_mut(self, decl); walk_mut::walk_export_default_declaration_mut(self, decl);
} }
fn visit_export_named_declaration(&mut self, decl: &mut ExportNamedDeclaration<'a>) {
self.x0_typescript.transform_export_named_declaration(decl);
walk_mut::walk_export_named_declaration_mut(self, decl);
}
fn visit_expression(&mut self, expr: &mut Expression<'a>) {
self.x0_typescript.transform_expression(expr);
self.x1_react.transform_expression(expr);
walk_mut::walk_expression_mut(self, expr);
}
fn visit_formal_parameter(&mut self, param: &mut FormalParameter<'a>) {
self.x0_typescript.transform_formal_parameter(param);
walk_mut::walk_formal_parameter_mut(self, param);
}
fn visit_function(&mut self, func: &mut Function<'a>, flags: Option<oxc_semantic::ScopeFlags>) {
self.x0_typescript.transform_function(func, flags);
walk_mut::walk_function_mut(self, func, flags);
}
fn visit_import_declaration(&mut self, decl: &mut ImportDeclaration<'a>) {
self.x0_typescript.transform_import_declaration(decl);
walk_mut::walk_import_declaration_mut(self, decl);
}
fn visit_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) { fn visit_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) {
self.x0_typescript.transform_jsx_opening_element(elem);
self.x1_react.transform_jsx_opening_element(elem); self.x1_react.transform_jsx_opening_element(elem);
walk_mut::walk_jsx_opening_element_mut(self, elem); walk_mut::walk_jsx_opening_element_mut(self, elem);
} }
fn visit_method_definition(&mut self, def: &mut MethodDefinition<'a>) {
self.x0_typescript.transform_method_definition(def);
walk_mut::walk_method_definition_mut(self, def);
}
fn visit_new_expression(&mut self, expr: &mut NewExpression<'a>) {
self.x0_typescript.transform_new_expression(expr);
walk_mut::walk_new_expression_mut(self, expr);
}
fn visit_object_property(&mut self, prop: &mut ObjectProperty<'a>) {
self.x1_react.transform_object_property(prop);
walk_mut::walk_object_property_mut(self, prop);
}
fn visit_property_definition(&mut self, def: &mut PropertyDefinition<'a>) {
self.x0_typescript.transform_property_definition(def);
walk_mut::walk_property_definition_mut(self, def);
}
fn visit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
self.x0_typescript.transform_statements(stmts);
walk_mut::walk_statements_mut(self, stmts);
self.x0_typescript.transform_statements_on_exit(stmts);
}
fn visit_statement(&mut self, stmt: &mut Statement<'a>) {
self.x2_decorators.transform_statement(stmt);
walk_mut::walk_statement_mut(self, stmt);
}
fn visit_tagged_template_expression(&mut self, expr: &mut TaggedTemplateExpression<'a>) {
self.x0_typescript.transform_tagged_template_expression(expr);
walk_mut::walk_tagged_template_expression_mut(self, expr);
}
fn visit_variable_declarator(&mut self, declarator: &mut VariableDeclarator<'a>) {
self.x1_react.transform_variable_declarator(declarator);
walk_mut::walk_variable_declarator_mut(self, declarator);
}
} }

View file

@ -0,0 +1,287 @@
#![allow(clippy::unused_self)]
use std::rc::Rc;
use crate::context::Ctx;
use crate::TypeScriptOptions;
use oxc_allocator::Vec;
use oxc_ast::ast::*;
use oxc_span::{Atom, SPAN};
use oxc_syntax::operator::AssignmentOperator;
use rustc_hash::FxHashSet;
pub struct TypeScriptAnnotations<'a> {
#[allow(dead_code)]
options: Rc<TypeScriptOptions>,
ctx: Ctx<'a>,
global_types: FxHashSet<String>,
}
impl<'a> TypeScriptAnnotations<'a> {
pub fn new(options: &Rc<TypeScriptOptions>, ctx: &Ctx<'a>) -> Self {
Self {
options: Rc::clone(options),
ctx: Rc::clone(ctx),
global_types: FxHashSet::default(),
}
}
pub fn is_global_type(&self) -> bool {
self.global_types.contains("TODO")
}
// Convert `export = expr` into `module.exports = expr`
fn create_module_exports(&self, exp: &TSExportAssignment<'a>) -> Statement<'a> {
let ast = &self.ctx.ast;
ast.expression_statement(
SPAN,
ast.assignment_expression(
SPAN,
AssignmentOperator::Assign,
ast.simple_assignment_target_member_expression(ast.static_member(
SPAN,
ast.identifier_reference_expression(ast.identifier_reference(SPAN, "module")),
ast.identifier_name(SPAN, "exports"),
false,
)),
ast.copy(&exp.expression),
),
)
}
// Creates `this.name = name`
fn create_this_property_assignment(&self, name: &Atom<'a>) -> Statement<'a> {
let ast = &self.ctx.ast;
ast.expression_statement(
SPAN,
ast.assignment_expression(
SPAN,
AssignmentOperator::Assign,
ast.simple_assignment_target_member_expression(ast.static_member(
SPAN,
ast.this_expression(SPAN),
ast.identifier_name(SPAN, name),
false,
)),
ast.identifier_reference_expression(ast.identifier_reference(SPAN, name)),
),
)
}
// Remove type only imports/exports
pub fn transform_program_on_exit(&self, program: &mut Program<'a>) {
let mut module_count = 0;
let body =
self.ctx.ast.move_statement_vec(&mut program.body).into_iter().filter_map(|stmt| {
// If an import/export declaration, remove all that are type-only
if let Statement::ModuleDeclaration(decl) = &stmt {
let keep = match &**decl {
ModuleDeclaration::ImportDeclaration(inner) => !inner.import_kind.is_type(),
ModuleDeclaration::ExportAllDeclaration(inner) => {
!inner.is_typescript_syntax()
}
ModuleDeclaration::ExportNamedDeclaration(inner) => {
!(inner.is_typescript_syntax()
|| inner.specifiers.is_empty()
|| inner.specifiers.iter().all(|spec| spec.export_kind.is_type())
|| self.is_global_type())
}
ModuleDeclaration::ExportDefaultDeclaration(inner) => {
!inner.is_typescript_syntax()
}
ModuleDeclaration::TSNamespaceExportDeclaration(_) => false,
// Replace with `module.exports = expr`
ModuleDeclaration::TSExportAssignment(exp) => {
return Some(self.create_module_exports(exp));
}
};
if keep {
module_count += 1;
} else {
return None;
}
}
Some(stmt)
});
program.body = self.ctx.ast.new_vec_from_iter(body);
// Determine if we still have import/export statements, otherwise we
// need to inject an empty statement (`export {}`) so that the file is
// still considered a module
if module_count == 0 && self.ctx.semantic.source_type().is_module() {
// FIXME
// program.body.push(self.ctx.ast.module_declaration(
// ModuleDeclaration::ExportNamedDeclaration(
// self.ctx.ast.plain_export_named_declaration(SPAN, self.ctx.ast.new_vec(), None),
// ),
// ));
}
}
pub fn transform_arrow_expression(&mut self, expr: &mut ArrowFunctionExpression<'a>) {
expr.type_parameters = None;
expr.return_type = None;
}
pub fn transform_binding_pattern(&mut self, pat: &mut BindingPattern<'a>) {
pat.type_annotation = None;
if pat.kind.is_binding_identifier() {
pat.optional = false;
}
}
pub fn transform_call_expression(&mut self, expr: &mut CallExpression<'a>) {
expr.type_parameters = None;
}
pub fn transform_class(&mut self, class: &mut Class<'a>) {
class.type_parameters = None;
class.super_type_parameters = None;
class.implements = None;
class.modifiers.remove_type_modifiers();
}
pub fn transform_class_body(&mut self, body: &mut ClassBody<'a>) {
// Remove type only members
body.body.retain(|elem| match elem {
ClassElement::MethodDefinition(method) => {
matches!(method.r#type, MethodDefinitionType::MethodDefinition)
|| !method.value.is_typescript_syntax()
}
ClassElement::PropertyDefinition(prop) => {
if prop.value.as_ref().is_some_and(Expression::is_typescript_syntax)
|| prop.declare && prop.decorators.is_empty()
{
false
} else {
matches!(prop.r#type, PropertyDefinitionType::PropertyDefinition)
}
}
ClassElement::TSIndexSignature(_) => false,
_ => true,
});
}
pub fn transform_export_named_declaration(&mut self, decl: &mut ExportNamedDeclaration<'a>) {
// Remove type only specifiers
decl.specifiers.retain(|spec| !spec.export_kind.is_type());
}
pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
*expr = self.ctx.ast.copy(expr.get_inner_expression());
}
pub fn transform_formal_parameter(&mut self, param: &mut FormalParameter<'a>) {
param.accessibility = None;
}
pub fn transform_function(
&mut self,
func: &mut Function<'a>,
_flags: Option<oxc_semantic::ScopeFlags>,
) {
func.this_param = None;
func.type_parameters = None;
func.return_type = None;
func.modifiers.remove_type_modifiers();
}
pub fn transform_import_declaration(&mut self, decl: &mut ImportDeclaration<'a>) {
// Remove type only specifiers
if let Some(specifiers) = &mut decl.specifiers {
specifiers.retain(|spec| match spec {
ImportDeclarationSpecifier::ImportSpecifier(inner) => !inner.import_kind.is_type(),
_ => true,
});
}
}
pub fn transform_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) {
elem.type_parameters = None;
}
pub fn transform_method_definition(&mut self, def: &mut MethodDefinition<'a>) {
def.accessibility = None;
def.optional = false;
def.r#override = false;
// Collects parameter properties so that we can add an assignment
// for each of them in the constructor body.
if def.kind == MethodDefinitionKind::Constructor {
let mut assigns = self.ctx.ast.new_vec();
for param in &def.value.params.items {
if param.pattern.type_annotation.is_none() {
continue;
}
if let Some(id) = param.pattern.get_identifier() {
assigns.push(self.create_this_property_assignment(id));
}
}
if !assigns.is_empty() {
def.value
.body
.get_or_insert(self.ctx.ast.function_body(
SPAN,
self.ctx.ast.new_vec(),
self.ctx.ast.new_vec(),
))
.statements
.extend(assigns);
}
}
}
pub fn transform_new_expression(&mut self, expr: &mut NewExpression<'a>) {
expr.type_parameters = None;
}
pub fn transform_property_definition(&mut self, def: &mut PropertyDefinition<'a>) {
assert!(
!(def.declare && def.value.is_some()),
"Fields with the 'declare' modifier cannot be initialized here, but only in the constructor"
);
assert!(
!(def.definite && def.value.is_some()),
"Definitely assigned fields cannot be initialized here, but only in the constructor"
);
def.accessibility = None;
def.declare = false;
def.definite = false;
def.r#override = false;
def.optional = false;
def.readonly = false;
def.type_annotation = None;
}
pub fn transform_statements_on_exit(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
// Remove TS specific statements
stmts.retain(|stmt| match stmt {
Statement::ExpressionStatement(s) => !s.expression.is_typescript_syntax(),
Statement::Declaration(s) => !s.is_typescript_syntax(),
// Ignore ModuleDeclaration as it's handled in the program
_ => true,
});
}
pub fn transform_tagged_template_expression(
&mut self,
expr: &mut TaggedTemplateExpression<'a>,
) {
expr.type_parameters = None;
}
}

View file

@ -1,3 +1,4 @@
mod annotations;
mod namespace; mod namespace;
use std::rc::Rc; use std::rc::Rc;
@ -9,6 +10,8 @@ use oxc_ast::ast::*;
use crate::context::Ctx; use crate::context::Ctx;
use self::annotations::TypeScriptAnnotations;
#[derive(Debug, Default, Clone, Deserialize)] #[derive(Debug, Default, Clone, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct TypeScriptOptions; pub struct TypeScriptOptions;
@ -36,19 +39,102 @@ pub struct TypeScriptOptions;
/// Out: `const x = 0;` /// Out: `const x = 0;`
#[allow(unused)] #[allow(unused)]
pub struct TypeScript<'a> { pub struct TypeScript<'a> {
options: TypeScriptOptions, options: Rc<TypeScriptOptions>,
ctx: Ctx<'a>, ctx: Ctx<'a>,
annotations: TypeScriptAnnotations<'a>,
} }
impl<'a> TypeScript<'a> { impl<'a> TypeScript<'a> {
pub fn new(options: TypeScriptOptions, ctx: &Ctx<'a>) -> Self { pub fn new(options: TypeScriptOptions, ctx: &Ctx<'a>) -> Self {
Self { options, ctx: Rc::clone(ctx) } let options = Rc::new(options);
Self {
annotations: TypeScriptAnnotations::new(&options, ctx),
options,
ctx: Rc::clone(ctx),
}
} }
} }
// Transforms // Transforms
impl<'a> TypeScript<'a> { impl<'a> TypeScript<'a> {
pub fn transform_program_on_exit(&self, program: &mut Program<'a>) {
self.annotations.transform_program_on_exit(program);
}
pub fn transform_arrow_expression(&mut self, expr: &mut ArrowFunctionExpression<'a>) {
self.annotations.transform_arrow_expression(expr);
}
pub fn transform_binding_pattern(&mut self, pat: &mut BindingPattern<'a>) {
self.annotations.transform_binding_pattern(pat);
}
pub fn transform_call_expression(&mut self, expr: &mut CallExpression<'a>) {
self.annotations.transform_call_expression(expr);
}
pub fn transform_class(&mut self, class: &mut Class<'a>) {
self.annotations.transform_class(class);
}
pub fn transform_class_body(&mut self, body: &mut ClassBody<'a>) {
self.annotations.transform_class_body(body);
}
pub fn transform_export_named_declaration(&mut self, decl: &mut ExportNamedDeclaration<'a>) {
self.annotations.transform_export_named_declaration(decl);
}
pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
self.annotations.transform_expression(expr);
}
pub fn transform_formal_parameter(&mut self, param: &mut FormalParameter<'a>) {
self.annotations.transform_formal_parameter(param);
}
pub fn transform_function(
&mut self,
func: &mut Function<'a>,
flags: Option<oxc_semantic::ScopeFlags>,
) {
self.annotations.transform_function(func, flags);
}
pub fn transform_import_declaration(&mut self, decl: &mut ImportDeclaration<'a>) {
self.annotations.transform_import_declaration(decl);
}
pub fn transform_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) {
self.annotations.transform_jsx_opening_element(elem);
}
pub fn transform_method_definition(&mut self, def: &mut MethodDefinition<'a>) {
self.annotations.transform_method_definition(def);
}
pub fn transform_new_expression(&mut self, expr: &mut NewExpression<'a>) {
self.annotations.transform_new_expression(expr);
}
pub fn transform_property_definition(&mut self, def: &mut PropertyDefinition<'a>) {
self.annotations.transform_property_definition(def);
}
pub fn transform_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) { pub fn transform_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
self.transform_statements_for_namespace(stmts); self.transform_statements_for_namespace(stmts);
} }
pub fn transform_statements_on_exit(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
self.annotations.transform_statements_on_exit(stmts);
}
pub fn transform_tagged_template_expression(
&mut self,
expr: &mut TaggedTemplateExpression<'a>,
) {
self.annotations.transform_tagged_template_expression(expr);
}
} }

View file

@ -1,16 +1,15 @@
Passed: 77/178 Passed: 76/178
# All Passed: # All Passed:
* babel-plugin-transform-react-jsx-source * babel-plugin-transform-react-jsx-source
# babel-plugin-transform-typescript (60/158) # babel-plugin-transform-typescript (59/158)
* 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
* class/accessor-allowDeclareFields-false/input.ts * class/accessor-allowDeclareFields-false/input.ts
* class/accessor-allowDeclareFields-true/input.ts * class/accessor-allowDeclareFields-true/input.ts
* class/declare/input.ts
* class/decorated-declare-properties/input.ts * class/decorated-declare-properties/input.ts
* class/parameter-properties/input.ts * class/parameter-properties/input.ts
* class/parameter-properties-late-super/input.ts * class/parameter-properties-late-super/input.ts
@ -23,6 +22,8 @@ Passed: 77/178
* declarations/erased/input.ts * declarations/erased/input.ts
* declarations/export-declare-enum/input.ts * declarations/export-declare-enum/input.ts
* declarations/nested-namespace/input.mjs * declarations/nested-namespace/input.mjs
* exports/declare-namespace/input.ts
* exports/declare-shadowed/input.ts
* exports/declared-types/input.ts * exports/declared-types/input.ts
* exports/export-const-enums/input.ts * exports/export-const-enums/input.ts
* exports/export-type/input.ts * exports/export-type/input.ts
@ -33,9 +34,9 @@ Passed: 77/178
* exports/imported-types/input.ts * exports/imported-types/input.ts
* exports/imported-types-only-remove-type-imports/input.ts * exports/imported-types-only-remove-type-imports/input.ts
* exports/issue-9916-3/input.ts * exports/issue-9916-3/input.ts
* exports/simple/input.ts
* exports/type-only-export-specifier-1/input.ts * exports/type-only-export-specifier-1/input.ts
* exports/type-only-export-specifier-2/input.ts * exports/type-only-export-specifier-2/input.ts
* exports/type-only-export-specifier-3/input.ts
* function/overloads-exports/input.mjs * function/overloads-exports/input.mjs
* imports/elide-injected/input.ts * imports/elide-injected/input.ts
* imports/elide-preact/input.ts * imports/elide-preact/input.ts
@ -56,15 +57,12 @@ Passed: 77/178
* imports/import=-declaration/input.ts * imports/import=-declaration/input.ts
* imports/import=-module/input.ts * imports/import=-module/input.ts
* imports/import=-module-to-cjs/input.ts * imports/import=-module-to-cjs/input.ts
* imports/only-remove-type-imports/input.ts
* imports/parameter-decorators/input.ts * imports/parameter-decorators/input.ts
* imports/property-signature/input.ts * imports/property-signature/input.ts
* imports/type-only-export-specifier-1/input.ts * imports/type-only-export-specifier-1/input.ts
* imports/type-only-export-specifier-2/input.ts * imports/type-only-export-specifier-2/input.ts
* imports/type-only-import-specifier-1/input.ts
* imports/type-only-import-specifier-2/input.ts * imports/type-only-import-specifier-2/input.ts
* imports/type-only-import-specifier-3/input.ts * imports/type-only-import-specifier-3/input.ts
* imports/type-only-import-specifier-4/input.ts
* namespace/alias/input.ts * namespace/alias/input.ts
* namespace/ambient-module-nested/input.ts * namespace/ambient-module-nested/input.ts
* namespace/ambient-module-nested-exported/input.ts * namespace/ambient-module-nested-exported/input.ts
@ -74,7 +72,10 @@ Passed: 77/178
* namespace/clobber-export/input.ts * namespace/clobber-export/input.ts
* namespace/clobber-import/input.ts * namespace/clobber-import/input.ts
* namespace/contentious-names/input.ts * namespace/contentious-names/input.ts
* namespace/declare/input.ts
* namespace/declare-global-nested-namespace/input.ts
* namespace/empty-removed/input.ts * namespace/empty-removed/input.ts
* namespace/export/input.ts
* namespace/export-type-only/input.ts * namespace/export-type-only/input.ts
* namespace/module-nested/input.ts * namespace/module-nested/input.ts
* namespace/module-nested-export/input.ts * namespace/module-nested-export/input.ts