mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
feat(transformer): start on TypeScript annotation removal (#2951)
This commit is contained in:
parent
93ce5a919a
commit
e67355045e
7 changed files with 564 additions and 26 deletions
|
|
@ -113,6 +113,17 @@ pub enum 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 {
|
||||
self.is_literal()
|
||||
|| matches!(
|
||||
|
|
@ -1289,6 +1300,7 @@ impl<'a> Declaration<'a> {
|
|||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modifiers(&self) -> Option<&Modifiers<'a>> {
|
||||
match self {
|
||||
Declaration::VariableDeclaration(decl) => Some(&decl.modifiers),
|
||||
|
|
@ -1659,6 +1671,10 @@ impl<'a> BindingPattern<'a> {
|
|||
pub fn new_with_kind(kind: BindingPatternKind<'a>) -> Self {
|
||||
Self { kind, type_annotation: None, optional: false }
|
||||
}
|
||||
|
||||
pub fn get_identifier(&self) -> Option<&Atom<'a>> {
|
||||
self.kind.get_identifier()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash)]
|
||||
|
|
@ -1679,6 +1695,14 @@ pub enum 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 {
|
||||
matches!(self, Self::ObjectPattern(_) | Self::ArrayPattern(_))
|
||||
}
|
||||
|
|
@ -1809,8 +1833,10 @@ pub struct Function<'a> {
|
|||
|
||||
impl<'a> Function<'a> {
|
||||
pub fn is_typescript_syntax(&self) -> bool {
|
||||
self.r#type == FunctionType::TSDeclareFunction
|
||||
|| self.body.is_none()
|
||||
matches!(
|
||||
self.r#type,
|
||||
FunctionType::TSDeclareFunction | FunctionType::TSEmptyBodyFunctionExpression
|
||||
) || self.body.is_none()
|
||||
|| self.modifiers.contains(ModifierKind::Declare)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1007,6 +1007,12 @@ pub enum ModifierKind {
|
|||
Override,
|
||||
}
|
||||
|
||||
impl ModifierKind {
|
||||
pub fn is_typescript_syntax(&self) -> bool {
|
||||
!matches!(self, Self::Async | Self::Default | Self::Export | Self::Static)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash)]
|
||||
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
||||
#[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 {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@ impl<'a> AstBuilder<'a> {
|
|||
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]
|
||||
pub fn new_str(&self, value: &str) -> &'a str {
|
||||
String::from_str_in(value, self.allocator).into_bump_str()
|
||||
|
|
@ -210,6 +215,14 @@ impl<'a> AstBuilder<'a> {
|
|||
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(
|
||||
&self,
|
||||
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 ----------------- */
|
||||
pub fn jsx_element(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -77,38 +77,135 @@ impl<'a> Transformer<'a> {
|
|||
}
|
||||
|
||||
impl<'a> VisitMut<'a> for Transformer<'a> {
|
||||
fn visit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
|
||||
self.x0_typescript.transform_statements(stmts);
|
||||
walk_mut::walk_statements_mut(self, stmts);
|
||||
fn visit_program(&mut self, program: &mut Program<'a>) {
|
||||
walk_mut::walk_program_mut(self, program);
|
||||
|
||||
self.x0_typescript.transform_program_on_exit(program);
|
||||
}
|
||||
|
||||
fn visit_statement(&mut self, stmt: &mut Statement<'a>) {
|
||||
self.x2_decorators.transform_statement(stmt);
|
||||
walk_mut::walk_statement_mut(self, stmt);
|
||||
// ALPHASORT
|
||||
|
||||
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>) {
|
||||
self.x1_react.transform_expression(expr);
|
||||
walk_mut::walk_expression_mut(self, expr);
|
||||
fn visit_binding_pattern(&mut self, pat: &mut BindingPattern<'a>) {
|
||||
self.x0_typescript.transform_binding_pattern(pat);
|
||||
|
||||
walk_mut::walk_binding_pattern_mut(self, pat);
|
||||
}
|
||||
|
||||
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);
|
||||
fn visit_call_expression(&mut self, expr: &mut CallExpression<'a>) {
|
||||
self.x0_typescript.transform_call_expression(expr);
|
||||
|
||||
walk_mut::walk_call_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_class(&mut self, class: &mut Class<'a>) {
|
||||
self.x0_typescript.transform_class(class);
|
||||
|
||||
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>) {
|
||||
self.x1_react.transform_export_default_declaration(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>) {
|
||||
self.x0_typescript.transform_jsx_opening_element(elem);
|
||||
self.x1_react.transform_jsx_opening_element(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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
287
crates/oxc_transformer/src/typescript/annotations.rs
Normal file
287
crates/oxc_transformer/src/typescript/annotations.rs
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
mod annotations;
|
||||
mod namespace;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
|
@ -9,6 +10,8 @@ use oxc_ast::ast::*;
|
|||
|
||||
use crate::context::Ctx;
|
||||
|
||||
use self::annotations::TypeScriptAnnotations;
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TypeScriptOptions;
|
||||
|
|
@ -36,19 +39,102 @@ pub struct TypeScriptOptions;
|
|||
/// Out: `const x = 0;`
|
||||
#[allow(unused)]
|
||||
pub struct TypeScript<'a> {
|
||||
options: TypeScriptOptions,
|
||||
options: Rc<TypeScriptOptions>,
|
||||
ctx: Ctx<'a>,
|
||||
|
||||
annotations: TypeScriptAnnotations<'a>,
|
||||
}
|
||||
|
||||
impl<'a> TypeScript<'a> {
|
||||
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
|
||||
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>>) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
Passed: 77/178
|
||||
Passed: 76/178
|
||||
|
||||
# All Passed:
|
||||
* 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-method/input.ts
|
||||
* class/abstract-class-decorated-parameter/input.ts
|
||||
* class/accessor-allowDeclareFields-false/input.ts
|
||||
* class/accessor-allowDeclareFields-true/input.ts
|
||||
* class/declare/input.ts
|
||||
* class/decorated-declare-properties/input.ts
|
||||
* class/parameter-properties/input.ts
|
||||
* class/parameter-properties-late-super/input.ts
|
||||
|
|
@ -23,6 +22,8 @@ Passed: 77/178
|
|||
* declarations/erased/input.ts
|
||||
* declarations/export-declare-enum/input.ts
|
||||
* declarations/nested-namespace/input.mjs
|
||||
* exports/declare-namespace/input.ts
|
||||
* exports/declare-shadowed/input.ts
|
||||
* exports/declared-types/input.ts
|
||||
* exports/export-const-enums/input.ts
|
||||
* exports/export-type/input.ts
|
||||
|
|
@ -33,9 +34,9 @@ Passed: 77/178
|
|||
* exports/imported-types/input.ts
|
||||
* exports/imported-types-only-remove-type-imports/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-2/input.ts
|
||||
* exports/type-only-export-specifier-3/input.ts
|
||||
* function/overloads-exports/input.mjs
|
||||
* imports/elide-injected/input.ts
|
||||
* imports/elide-preact/input.ts
|
||||
|
|
@ -56,15 +57,12 @@ Passed: 77/178
|
|||
* imports/import=-declaration/input.ts
|
||||
* imports/import=-module/input.ts
|
||||
* imports/import=-module-to-cjs/input.ts
|
||||
* imports/only-remove-type-imports/input.ts
|
||||
* imports/parameter-decorators/input.ts
|
||||
* imports/property-signature/input.ts
|
||||
* imports/type-only-export-specifier-1/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-3/input.ts
|
||||
* imports/type-only-import-specifier-4/input.ts
|
||||
* namespace/alias/input.ts
|
||||
* namespace/ambient-module-nested/input.ts
|
||||
* namespace/ambient-module-nested-exported/input.ts
|
||||
|
|
@ -74,7 +72,10 @@ Passed: 77/178
|
|||
* namespace/clobber-export/input.ts
|
||||
* namespace/clobber-import/input.ts
|
||||
* namespace/contentious-names/input.ts
|
||||
* namespace/declare/input.ts
|
||||
* namespace/declare-global-nested-namespace/input.ts
|
||||
* namespace/empty-removed/input.ts
|
||||
* namespace/export/input.ts
|
||||
* namespace/export-type-only/input.ts
|
||||
* namespace/module-nested/input.ts
|
||||
* namespace/module-nested-export/input.ts
|
||||
|
|
|
|||
Loading…
Reference in a new issue