Skip to content

Commit

Permalink
feat(transformer): start on TypeScript annotation removal (#2951)
Browse files Browse the repository at this point in the history
  • Loading branch information
milesj authored Apr 13, 2024
1 parent 93ce5a9 commit e673550
Show file tree
Hide file tree
Showing 7 changed files with 564 additions and 26 deletions.
30 changes: 28 additions & 2 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down Expand Up @@ -1289,6 +1300,7 @@ impl<'a> Declaration<'a> {
_ => true,
}
}

pub fn modifiers(&self) -> Option<&Modifiers<'a>> {
match self {
Declaration::VariableDeclaration(decl) => Some(&decl.modifiers),
Expand Down Expand Up @@ -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)]
Expand All @@ -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(_))
}
Expand Down Expand Up @@ -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)
}

Expand Down
12 changes: 12 additions & 0 deletions crates/oxc_ast/src/ast/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
Expand Down Expand Up @@ -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
Expand Down
29 changes: 29 additions & 0 deletions crates/oxc_ast/src/ast_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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>,
Expand Down Expand Up @@ -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,
Expand Down
127 changes: 112 additions & 15 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Loading

0 comments on commit e673550

Please sign in to comment.