refactor(transformer): TS transforms only store options they need (#6135)

All TS transforms only need a subset of the options in `TypeScriptOptions` - mostly just a single `bool`. Store these specific options in the transforms, not the whole `TypeScriptOptions` object.

This makes the transformer types smaller, and also checking the option is cheaper as it doesn't involve going through a double-reference.

e.g. Accessing `only_remove_type_imports` option with Rust's deref sugar made explicit:

Before: `*(&*self.options).only_remove_type_imports`
After: `*self.only_remove_type_imports`
This commit is contained in:
overlookmotel 2024-09-28 09:40:09 +00:00
parent 73098a43ff
commit 30424fab58
5 changed files with 30 additions and 28 deletions

View file

@ -19,9 +19,11 @@ use rustc_hash::FxHashSet;
use crate::{TransformCtx, TypeScriptOptions}; use crate::{TransformCtx, TypeScriptOptions};
pub struct TypeScriptAnnotations<'a, 'ctx> { pub struct TypeScriptAnnotations<'a, 'ctx> {
#[allow(dead_code)]
options: &'ctx TypeScriptOptions,
ctx: &'ctx TransformCtx<'a>, ctx: &'ctx TransformCtx<'a>,
// Options
only_remove_type_imports: bool,
/// Assignments to be added to the constructor body /// Assignments to be added to the constructor body
assignments: Vec<Assignment<'a>>, assignments: Vec<Assignment<'a>>,
has_super_call: bool, has_super_call: bool,
@ -34,7 +36,7 @@ pub struct TypeScriptAnnotations<'a, 'ctx> {
} }
impl<'a, 'ctx> TypeScriptAnnotations<'a, 'ctx> { impl<'a, 'ctx> TypeScriptAnnotations<'a, 'ctx> {
pub fn new(options: &'ctx TypeScriptOptions, ctx: &'ctx TransformCtx<'a>) -> Self { pub fn new(options: &TypeScriptOptions, ctx: &'ctx TransformCtx<'a>) -> Self {
let jsx_element_import_name = if options.jsx_pragma.contains('.') { let jsx_element_import_name = if options.jsx_pragma.contains('.') {
options.jsx_pragma.split('.').next().map(String::from).unwrap() options.jsx_pragma.split('.').next().map(String::from).unwrap()
} else { } else {
@ -48,10 +50,10 @@ impl<'a, 'ctx> TypeScriptAnnotations<'a, 'ctx> {
}; };
Self { Self {
ctx,
only_remove_type_imports: options.only_remove_type_imports,
has_super_call: false, has_super_call: false,
assignments: vec![], assignments: vec![],
options,
ctx,
has_jsx_element: false, has_jsx_element: false,
has_jsx_fragment: false, has_jsx_fragment: false,
jsx_element_import_name, jsx_element_import_name,
@ -100,7 +102,7 @@ impl<'a, 'ctx> Traverse<'a> for TypeScriptAnnotations<'a, 'ctx> {
Statement::ImportDeclaration(decl) => { Statement::ImportDeclaration(decl) => {
if decl.import_kind.is_type() { if decl.import_kind.is_type() {
false false
} else if self.options.only_remove_type_imports { } else if self.only_remove_type_imports {
true true
} else if let Some(specifiers) = &mut decl.specifiers { } else if let Some(specifiers) = &mut decl.specifiers {
if specifiers.is_empty() { if specifiers.is_empty() {

View file

@ -39,28 +39,24 @@ use crate::TransformCtx;
/// In: `const x: number = 0;` /// In: `const x: number = 0;`
/// Out: `const x = 0;` /// Out: `const x = 0;`
pub struct TypeScript<'a, 'ctx> { pub struct TypeScript<'a, 'ctx> {
options: &'ctx TypeScriptOptions,
ctx: &'ctx TransformCtx<'a>, ctx: &'ctx TransformCtx<'a>,
annotations: TypeScriptAnnotations<'a, 'ctx>, annotations: TypeScriptAnnotations<'a, 'ctx>,
r#enum: TypeScriptEnum<'a, 'ctx>, r#enum: TypeScriptEnum<'a, 'ctx>,
namespace: TypeScriptNamespace<'a, 'ctx>, namespace: TypeScriptNamespace<'a, 'ctx>,
module: TypeScriptModule<'a, 'ctx>, module: TypeScriptModule<'a, 'ctx>,
rewrite_extensions: TypeScriptRewriteExtensions, rewrite_extensions: Option<TypeScriptRewriteExtensions>,
} }
impl<'a, 'ctx> TypeScript<'a, 'ctx> { impl<'a, 'ctx> TypeScript<'a, 'ctx> {
pub fn new(options: &'ctx TypeScriptOptions, ctx: &'ctx TransformCtx<'a>) -> Self { pub fn new(options: &TypeScriptOptions, ctx: &'ctx TransformCtx<'a>) -> Self {
Self { Self {
ctx,
annotations: TypeScriptAnnotations::new(options, ctx), annotations: TypeScriptAnnotations::new(options, ctx),
r#enum: TypeScriptEnum::new(ctx), r#enum: TypeScriptEnum::new(ctx),
rewrite_extensions: TypeScriptRewriteExtensions::new(
options.rewrite_import_extensions.clone().unwrap_or_default(),
),
namespace: TypeScriptNamespace::new(options, ctx), namespace: TypeScriptNamespace::new(options, ctx),
module: TypeScriptModule::new(ctx), module: TypeScriptModule::new(ctx),
options, rewrite_extensions: TypeScriptRewriteExtensions::new(options),
ctx,
} }
} }
} }
@ -263,8 +259,8 @@ impl<'a, 'ctx> Traverse<'a> for TypeScript<'a, 'ctx> {
node: &mut ImportDeclaration<'a>, node: &mut ImportDeclaration<'a>,
ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
if self.options.rewrite_import_extensions.is_some() { if let Some(rewrite_extensions) = &mut self.rewrite_extensions {
self.rewrite_extensions.enter_import_declaration(node, ctx); rewrite_extensions.enter_import_declaration(node, ctx);
} }
} }
@ -273,8 +269,8 @@ impl<'a, 'ctx> Traverse<'a> for TypeScript<'a, 'ctx> {
node: &mut ExportAllDeclaration<'a>, node: &mut ExportAllDeclaration<'a>,
ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
if self.options.rewrite_import_extensions.is_some() { if let Some(rewrite_extensions) = &mut self.rewrite_extensions {
self.rewrite_extensions.enter_export_all_declaration(node, ctx); rewrite_extensions.enter_export_all_declaration(node, ctx);
} }
} }
@ -283,8 +279,8 @@ impl<'a, 'ctx> Traverse<'a> for TypeScript<'a, 'ctx> {
node: &mut ExportNamedDeclaration<'a>, node: &mut ExportNamedDeclaration<'a>,
ctx: &mut TraverseCtx<'a>, ctx: &mut TraverseCtx<'a>,
) { ) {
if self.options.rewrite_import_extensions.is_some() { if let Some(rewrite_extensions) = &mut self.rewrite_extensions {
self.rewrite_extensions.enter_export_named_declaration(node, ctx); rewrite_extensions.enter_export_named_declaration(node, ctx);
} }
} }

View file

@ -17,12 +17,14 @@ use crate::TransformCtx;
pub struct TypeScriptNamespace<'a, 'ctx> { pub struct TypeScriptNamespace<'a, 'ctx> {
ctx: &'ctx TransformCtx<'a>, ctx: &'ctx TransformCtx<'a>,
options: &'ctx TypeScriptOptions,
// Options
allow_namespaces: bool,
} }
impl<'a, 'ctx> TypeScriptNamespace<'a, 'ctx> { impl<'a, 'ctx> TypeScriptNamespace<'a, 'ctx> {
pub fn new(options: &'ctx TypeScriptOptions, ctx: &'ctx TransformCtx<'a>) -> Self { pub fn new(options: &TypeScriptOptions, ctx: &'ctx TransformCtx<'a>) -> Self {
Self { ctx, options } Self { ctx, allow_namespaces: options.allow_namespaces }
} }
} }
@ -47,7 +49,7 @@ impl<'a, 'ctx> Traverse<'a> for TypeScriptNamespace<'a, 'ctx> {
match stmt { match stmt {
Statement::TSModuleDeclaration(decl) => { Statement::TSModuleDeclaration(decl) => {
if !decl.declare { if !decl.declare {
if !self.options.allow_namespaces { if !self.allow_namespaces {
self.ctx.error(namespace_not_supported(decl.span)); self.ctx.error(namespace_not_supported(decl.span));
} }
@ -75,7 +77,7 @@ impl<'a, 'ctx> Traverse<'a> for TypeScriptNamespace<'a, 'ctx> {
match &export_decl.declaration { match &export_decl.declaration {
Some(Declaration::TSModuleDeclaration(decl)) => { Some(Declaration::TSModuleDeclaration(decl)) => {
if !decl.declare { if !decl.declare {
if !self.options.allow_namespaces { if !self.allow_namespaces {
self.ctx.error(namespace_not_supported(decl.span)); self.ctx.error(namespace_not_supported(decl.span));
} }

View file

@ -109,7 +109,7 @@ impl Default for TypeScriptOptions {
} }
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Copy, Default)]
pub enum RewriteExtensionsMode { pub enum RewriteExtensionsMode {
/// Rewrite `.ts`/`.mts`/`.cts` extensions in import/export declarations to `.js`/`.mjs`/`.cjs`. /// Rewrite `.ts`/`.mts`/`.cts` extensions in import/export declarations to `.js`/`.mjs`/`.cjs`.
#[default] #[default]

View file

@ -10,6 +10,8 @@ use oxc_ast::ast::{
}; };
use oxc_traverse::{Traverse, TraverseCtx}; use oxc_traverse::{Traverse, TraverseCtx};
use crate::TypeScriptOptions;
use super::options::RewriteExtensionsMode; use super::options::RewriteExtensionsMode;
pub struct TypeScriptRewriteExtensions { pub struct TypeScriptRewriteExtensions {
@ -17,8 +19,8 @@ pub struct TypeScriptRewriteExtensions {
} }
impl TypeScriptRewriteExtensions { impl TypeScriptRewriteExtensions {
pub fn new(mode: RewriteExtensionsMode) -> Self { pub fn new(options: &TypeScriptOptions) -> Option<Self> {
Self { mode } options.rewrite_import_extensions.map(|mode| Self { mode })
} }
pub fn rewrite_extensions<'a>( pub fn rewrite_extensions<'a>(