feat(codegen)!: remove CodegenOptions::enable_typescript (#3674)

The typescript transform pass is now required to strip typescript syntax
for codegen to print things properly.

Codegen will now print whatever is in the AST.
This commit is contained in:
Boshen 2024-06-14 21:56:00 +08:00 committed by GitHub
parent 4f2db46ee5
commit 534242a729
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 144 additions and 271 deletions

View file

@ -28,8 +28,7 @@ fn main() -> std::io::Result<()> {
println!("Original:"); println!("Original:");
println!("{source_text}"); println!("{source_text}");
let options = let options = CodegenOptions { enable_source_map: false, ..Default::default() };
CodegenOptions { enable_source_map: false, enable_typescript: true, ..Default::default() };
let printed = Codegen::<false>::new("", &source_text, ret.trivias, options) let printed = Codegen::<false>::new("", &source_text, ret.trivias, options)
.build(&ret.program) .build(&ret.program)
.source_text; .source_text;

View file

@ -26,8 +26,7 @@ fn main() -> std::io::Result<()> {
return Ok(()); return Ok(());
} }
let codegen_options = let codegen_options = CodegenOptions { enable_source_map: true, ..Default::default() };
CodegenOptions { enable_source_map: true, enable_typescript: true, ..Default::default() };
let CodegenReturn { source_text, source_map } = Codegen::<false>::new( let CodegenReturn { source_text, source_map } = Codegen::<false>::new(
path.to_string_lossy().as_ref(), path.to_string_lossy().as_ref(),

View file

@ -511,14 +511,11 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ModuleDeclaration<'a> {
Self::ExportDefaultDeclaration(decl) => decl.gen(p, ctx), Self::ExportDefaultDeclaration(decl) => decl.gen(p, ctx),
Self::ExportNamedDeclaration(decl) => decl.gen(p, ctx), Self::ExportNamedDeclaration(decl) => decl.gen(p, ctx),
Self::TSExportAssignment(decl) => { Self::TSExportAssignment(decl) => {
if p.options.enable_typescript {
p.print_str(b"export = "); p.print_str(b"export = ");
decl.expression.gen_expr(p, Precedence::lowest(), ctx); decl.expression.gen_expr(p, Precedence::lowest(), ctx);
p.print_semicolon_after_statement(); p.print_semicolon_after_statement();
} }
}
Self::TSNamespaceExportDeclaration(decl) => { Self::TSNamespaceExportDeclaration(decl) => {
if p.options.enable_typescript {
p.print_str(b"export as namespace "); p.print_str(b"export as namespace ");
decl.id.gen(p, ctx); decl.id.gen(p, ctx);
p.print_semicolon_after_statement(); p.print_semicolon_after_statement();
@ -526,49 +523,36 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ModuleDeclaration<'a> {
} }
} }
} }
}
impl<'a, const MINIFY: bool> Gen<MINIFY> for Declaration<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for Declaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
match self { match self {
Self::VariableDeclaration(decl) => { Self::VariableDeclaration(decl) => {
// Codegen is not intended to be used as a code formatting tool, so we need filter out the TypeScript syntax here.
if p.options.enable_typescript || !decl.is_typescript_syntax() {
p.print_indent(); p.print_indent();
decl.gen(p, ctx); decl.gen(p, ctx);
p.print_semicolon_after_statement(); p.print_semicolon_after_statement();
} }
}
Self::FunctionDeclaration(decl) => { Self::FunctionDeclaration(decl) => {
if p.options.enable_typescript || !decl.is_typescript_syntax() {
p.print_indent(); p.print_indent();
p.print_space_before_identifier(); p.print_space_before_identifier();
decl.gen(p, ctx); decl.gen(p, ctx);
p.print_soft_newline(); p.print_soft_newline();
} }
}
Self::ClassDeclaration(decl) => { Self::ClassDeclaration(decl) => {
if p.options.enable_typescript || !decl.is_typescript_syntax() {
p.print_indent(); p.print_indent();
p.print_space_before_identifier(); p.print_space_before_identifier();
decl.gen(p, ctx); decl.gen(p, ctx);
p.print_soft_newline(); p.print_soft_newline();
} }
}
Self::UsingDeclaration(declaration) => { Self::UsingDeclaration(declaration) => {
p.print_space_before_identifier(); p.print_space_before_identifier();
declaration.gen(p, ctx); declaration.gen(p, ctx);
p.print_soft_newline(); p.print_soft_newline();
} }
Self::TSModuleDeclaration(decl) => { Self::TSModuleDeclaration(decl) => {
if p.options.enable_typescript {
decl.gen(p, ctx); decl.gen(p, ctx);
} }
}
Self::TSTypeAliasDeclaration(decl) => { Self::TSTypeAliasDeclaration(decl) => {
if !p.options.enable_typescript {
return;
}
if decl.modifiers.contains(ModifierKind::Export) { if decl.modifiers.contains(ModifierKind::Export) {
p.print_str(b"export "); p.print_str(b"export ");
} }
@ -590,13 +574,11 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Declaration<'a> {
Declaration::TSInterfaceDeclaration(decl) => decl.gen(p, ctx), Declaration::TSInterfaceDeclaration(decl) => decl.gen(p, ctx),
Declaration::TSEnumDeclaration(decl) => decl.gen(p, ctx), Declaration::TSEnumDeclaration(decl) => decl.gen(p, ctx),
Declaration::TSImportEqualsDeclaration(decl) => { Declaration::TSImportEqualsDeclaration(decl) => {
if p.options.enable_typescript {
decl.gen(p, ctx); decl.gen(p, ctx);
} }
} }
} }
} }
}
impl<'a, const MINIFY: bool> Gen<MINIFY> for UsingDeclaration<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for UsingDeclaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
@ -614,7 +596,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for UsingDeclaration<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for VariableDeclaration<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for VariableDeclaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.add_source_mapping(self.span.start); p.add_source_mapping(self.span.start);
if p.options.enable_typescript && self.modifiers.contains(ModifierKind::Declare) { if self.modifiers.contains(ModifierKind::Declare) {
p.print_str(b"declare "); p.print_str(b"declare ");
} }
@ -658,13 +640,10 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Function<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.add_source_mapping(self.span.start); p.add_source_mapping(self.span.start);
self.gen_comment(p, ctx); self.gen_comment(p, ctx);
if !p.options.enable_typescript && self.is_typescript_syntax() {
return;
}
let n = p.code_len(); let n = p.code_len();
let wrap = self.is_expression() && (p.start_of_stmt == n || p.start_of_default_export == n); let wrap = self.is_expression() && (p.start_of_stmt == n || p.start_of_default_export == n);
p.wrap(wrap, |p| { p.wrap(wrap, |p| {
if p.options.enable_typescript && self.modifiers.contains(ModifierKind::Declare) { if self.modifiers.contains(ModifierKind::Declare) {
p.print_str(b"declare "); p.print_str(b"declare ");
} }
if self.r#async { if self.r#async {
@ -679,24 +658,20 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Function<'a> {
p.print_space_before_identifier(); p.print_space_before_identifier();
id.gen(p, ctx); id.gen(p, ctx);
} }
if p.options.enable_typescript {
if let Some(type_parameters) = &self.type_parameters { if let Some(type_parameters) = &self.type_parameters {
type_parameters.gen(p, ctx); type_parameters.gen(p, ctx);
} }
}
p.print(b'('); p.print(b'(');
self.params.gen(p, ctx); self.params.gen(p, ctx);
p.print(b')'); p.print(b')');
if p.options.enable_typescript {
if let Some(return_type) = &self.return_type { if let Some(return_type) = &self.return_type {
p.print_str(b": "); p.print_str(b": ");
return_type.gen(p, ctx); return_type.gen(p, ctx);
} }
}
p.print_soft_space(); p.print_soft_space();
if let Some(body) = &self.body { if let Some(body) = &self.body {
body.gen(p, ctx); body.gen(p, ctx);
} else if p.options.enable_typescript { } else {
p.print_semicolon_after_statement(); p.print_semicolon_after_statement();
} }
}); });
@ -720,14 +695,12 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for FunctionBody<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for FormalParameter<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for FormalParameter<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
self.decorators.gen(p, ctx); self.decorators.gen(p, ctx);
if p.options.enable_typescript {
if self.readonly { if self.readonly {
p.print_str(b"readonly "); p.print_str(b"readonly ");
} }
if let Some(accessibility) = self.accessibility { if let Some(accessibility) = self.accessibility {
accessibility.gen(p, ctx); accessibility.gen(p, ctx);
} }
}
self.pattern.gen(p, ctx); self.pattern.gen(p, ctx);
} }
} }
@ -749,7 +722,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ImportDeclaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.add_source_mapping(self.span.start); p.add_source_mapping(self.span.start);
p.print_str(b"import "); p.print_str(b"import ");
if p.options.enable_typescript && self.import_kind.is_type() { if self.import_kind.is_type() {
p.print_str(b"type "); p.print_str(b"type ");
} }
if let Some(specifiers) = &self.specifiers { if let Some(specifiers) = &self.specifiers {
@ -798,7 +771,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ImportDeclaration<'a> {
p.print(b'{'); p.print(b'{');
} }
if p.options.enable_typescript && spec.import_kind.is_type() { if spec.import_kind.is_type() {
p.print_str(b"type "); p.print_str(b"type ");
} }
@ -870,9 +843,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ImportAttribute<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportNamedDeclaration<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportNamedDeclaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.add_source_mapping(self.span.start); p.add_source_mapping(self.span.start);
if !p.options.enable_typescript && self.is_typescript_syntax() {
return;
}
if p.options.preserve_annotate_comments { if p.options.preserve_annotate_comments {
match &self.declaration { match &self.declaration {
Some(Declaration::FunctionDeclaration(_)) => { Some(Declaration::FunctionDeclaration(_)) => {
@ -895,7 +865,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportNamedDeclaration<'a> {
}; };
} }
p.print_str(b"export "); p.print_str(b"export ");
if p.options.enable_typescript && self.export_kind.is_type() { if self.export_kind.is_type() {
p.print_str(b"type "); p.print_str(b"type ");
} }
match &self.declaration { match &self.declaration {
@ -922,7 +892,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportNamedDeclaration<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportSpecifier<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportSpecifier<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
if p.options.enable_typescript && self.export_kind.is_type() { if self.export_kind.is_type() {
p.print_str(b"type "); p.print_str(b"type ");
} }
self.local.gen(p, ctx); self.local.gen(p, ctx);
@ -947,11 +917,8 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ModuleExportName<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportAllDeclaration<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportAllDeclaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.add_source_mapping(self.span.start); p.add_source_mapping(self.span.start);
if !p.options.enable_typescript && self.is_typescript_syntax() {
return;
}
p.print_str(b"export "); p.print_str(b"export ");
if p.options.enable_typescript && self.export_kind.is_type() { if self.export_kind.is_type() {
p.print_str(b"type "); p.print_str(b"type ");
} }
p.print(b'*'); p.print(b'*');
@ -975,9 +942,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportAllDeclaration<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportDefaultDeclaration<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportDefaultDeclaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.add_source_mapping(self.span.start); p.add_source_mapping(self.span.start);
if !p.options.enable_typescript && self.is_typescript_syntax() {
return;
}
p.print_str(b"export default "); p.print_str(b"export default ");
self.declaration.gen(p, ctx); self.declaration.gen(p, ctx);
} }
@ -1043,11 +1007,9 @@ impl<'a, const MINIFY: bool> GenExpr<MINIFY> for Expression<'a> {
Self::TSAsExpression(e) => e.gen_expr(p, precedence, ctx), Self::TSAsExpression(e) => e.gen_expr(p, precedence, ctx),
Self::TSSatisfiesExpression(e) => { Self::TSSatisfiesExpression(e) => {
e.expression.gen_expr(p, precedence, ctx); e.expression.gen_expr(p, precedence, ctx);
if p.options.enable_typescript {
p.print_str(b" satisfies "); p.print_str(b" satisfies ");
e.type_annotation.gen(p, ctx); e.type_annotation.gen(p, ctx);
} }
}
Self::TSTypeAssertion(e) => e.gen_expr(p, precedence, ctx), Self::TSTypeAssertion(e) => e.gen_expr(p, precedence, ctx),
Self::TSNonNullExpression(e) => e.expression.gen_expr(p, precedence, ctx), Self::TSNonNullExpression(e) => e.expression.gen_expr(p, precedence, ctx),
Self::TSInstantiationExpression(e) => e.expression.gen_expr(p, precedence, ctx), Self::TSInstantiationExpression(e) => e.expression.gen_expr(p, precedence, ctx),
@ -1069,17 +1031,13 @@ impl<const MINIFY: bool> GenComment<MINIFY> for Function<'_> {
impl<'a, const MINIFY: bool> GenExpr<MINIFY> for TSAsExpression<'a> { impl<'a, const MINIFY: bool> GenExpr<MINIFY> for TSAsExpression<'a> {
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) { fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) {
if p.options.enable_typescript {
p.print_str(b"("); p.print_str(b"(");
}
self.expression.gen_expr(p, precedence, ctx); self.expression.gen_expr(p, precedence, ctx);
if p.options.enable_typescript {
p.print_str(b" as "); p.print_str(b" as ");
self.type_annotation.gen(p, ctx); self.type_annotation.gen(p, ctx);
p.print_str(b")"); p.print_str(b")");
} }
} }
}
impl<'a, const MINIFY: bool> Gen<MINIFY> for IdentifierReference<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for IdentifierReference<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
// if let Some(mangler) = &p.mangler { // if let Some(mangler) = &p.mangler {
@ -1427,11 +1385,9 @@ impl<'a, const MINIFY: bool> GenExpr<MINIFY> for CallExpression<'a> {
if self.optional { if self.optional {
p.print_str(b"?."); p.print_str(b"?.");
} }
if p.options.enable_typescript {
if let Some(type_parameters) = &self.type_parameters { if let Some(type_parameters) = &self.type_parameters {
type_parameters.gen(p, ctx); type_parameters.gen(p, ctx);
} }
}
p.print(b'('); p.print(b'(');
p.print_list(&self.arguments, ctx); p.print_list(&self.arguments, ctx);
p.print(b')'); p.print(b')');
@ -1553,11 +1509,9 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ObjectProperty<'a> {
if self.computed { if self.computed {
p.print(b']'); p.print(b']');
} }
if p.options.enable_typescript {
if let Some(type_parameters) = &func.type_parameters { if let Some(type_parameters) = &func.type_parameters {
type_parameters.gen(p, ctx); type_parameters.gen(p, ctx);
} }
}
p.print(b'('); p.print(b'(');
func.params.gen(p, ctx); func.params.gen(p, ctx);
p.print(b')'); p.print(b')');
@ -1604,33 +1558,22 @@ impl<'a, const MINIFY: bool> GenExpr<MINIFY> for ArrowFunctionExpression<'a> {
p.print_str(b"async"); p.print_str(b"async");
} }
// No wrap for `a => {}` if self.r#async {
let nowrap = self.params.rest.is_none()
&& self.params.items.len() == 1
&& self.params.items[0].pattern.kind.is_binding_identifier()
&& !p.options.enable_typescript;
if nowrap && self.r#async {
p.print_hard_space(); p.print_hard_space();
} }
if p.options.enable_typescript {
if let Some(type_parameters) = &self.type_parameters { if let Some(type_parameters) = &self.type_parameters {
type_parameters.gen(p, ctx); type_parameters.gen(p, ctx);
} }
}
if !nowrap {
p.add_source_mapping(self.span.start); p.add_source_mapping(self.span.start);
} p.print(b'(');
p.wrap(!nowrap, |p| {
self.params.gen(p, ctx); self.params.gen(p, ctx);
}); p.print(b')');
if p.options.enable_typescript {
if let Some(return_type) = &self.return_type { if let Some(return_type) = &self.return_type {
p.print_str(b":"); p.print_str(b":");
p.print_soft_space(); p.print_soft_space();
return_type.gen(p, ctx); return_type.gen(p, ctx);
} }
}
p.print_soft_space(); p.print_soft_space();
p.print_str(b"=>"); p.print_str(b"=>");
p.print_soft_space(); p.print_soft_space();
@ -2082,17 +2025,12 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for MetaProperty<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for Class<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for Class<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.add_source_mapping(self.span.start); p.add_source_mapping(self.span.start);
if !p.options.enable_typescript && self.is_declare() {
return;
}
if p.options.enable_typescript {
if self.modifiers.is_contains_declare() { if self.modifiers.is_contains_declare() {
p.print_str(b"declare "); p.print_str(b"declare ");
} }
if self.modifiers.is_contains_abstract() { if self.modifiers.is_contains_abstract() {
p.print_str(b"abstract "); p.print_str(b"abstract ");
} }
}
let n = p.code_len(); let n = p.code_len();
let wrap = self.is_expression() && (p.start_of_stmt == n || p.start_of_default_export == n); let wrap = self.is_expression() && (p.start_of_stmt == n || p.start_of_default_export == n);
p.wrap(wrap, |p| { p.wrap(wrap, |p| {
@ -2109,9 +2047,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Class<'a> {
p.print_soft_space(); p.print_soft_space();
p.print_block_start(self.body.span.start); p.print_block_start(self.body.span.start);
for item in &self.body.body { for item in &self.body.body {
if !p.options.enable_typescript && item.is_typescript_syntax() {
continue;
}
p.print_indent(); p.print_indent();
p.print_semicolon_if_needed(); p.print_semicolon_if_needed();
item.gen(p, ctx); item.gen(p, ctx);
@ -2361,15 +2296,10 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for StaticBlock<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for MethodDefinition<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for MethodDefinition<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
if !p.options.enable_typescript && self.value.is_typescript_syntax() {
return;
}
p.add_source_mapping(self.span.start); p.add_source_mapping(self.span.start);
self.decorators.gen(p, ctx); self.decorators.gen(p, ctx);
if p.options.enable_typescript if self.r#type == MethodDefinitionType::TSAbstractMethodDefinition {
&& self.r#type == MethodDefinitionType::TSAbstractMethodDefinition
{
p.print_str(b"abstract "); p.print_str(b"abstract ");
} }
@ -2405,16 +2335,14 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for MethodDefinition<'a> {
p.print(b'('); p.print(b'(');
self.value.params.gen(p, ctx); self.value.params.gen(p, ctx);
p.print(b')'); p.print(b')');
if p.options.enable_typescript {
if let Some(return_type) = &self.value.return_type { if let Some(return_type) = &self.value.return_type {
p.print_colon(); p.print_colon();
p.print_soft_space(); p.print_soft_space();
return_type.gen(p, ctx); return_type.gen(p, ctx);
} }
}
if let Some(body) = &self.value.body { if let Some(body) = &self.value.body {
body.gen(p, ctx); body.gen(p, ctx);
} else if p.options.enable_typescript { } else {
p.print_semicolon_after_statement(); p.print_semicolon_after_statement();
} }
} }
@ -2424,7 +2352,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for PropertyDefinition<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.add_source_mapping(self.span.start); p.add_source_mapping(self.span.start);
self.decorators.gen(p, ctx); self.decorators.gen(p, ctx);
if p.options.enable_typescript {
if self.r#type == PropertyDefinitionType::TSAbstractPropertyDefinition { if self.r#type == PropertyDefinitionType::TSAbstractPropertyDefinition {
p.print_str(b"abstract "); p.print_str(b"abstract ");
} }
@ -2441,7 +2368,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for PropertyDefinition<'a> {
} }
} }
} }
}
if self.r#static { if self.r#static {
p.print_str(b"static "); p.print_str(b"static ");
} }
@ -2455,13 +2381,11 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for PropertyDefinition<'a> {
if self.optional { if self.optional {
p.print_str(b"?"); p.print_str(b"?");
} }
if p.options.enable_typescript {
if let Some(type_annotation) = &self.type_annotation { if let Some(type_annotation) = &self.type_annotation {
p.print_colon(); p.print_colon();
p.print_soft_space(); p.print_soft_space();
type_annotation.gen(p, ctx); type_annotation.gen(p, ctx);
} }
}
if let Some(value) = &self.value { if let Some(value) = &self.value {
p.print_equal(); p.print_equal();
value.gen_expr(p, Precedence::Assign, Context::default()); value.gen_expr(p, Precedence::Assign, Context::default());
@ -2472,7 +2396,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for PropertyDefinition<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for AccessorProperty<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for AccessorProperty<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.add_source_mapping(self.span.start); p.add_source_mapping(self.span.start);
if p.options.enable_typescript && self.r#type.is_abstract() { if self.r#type.is_abstract() {
p.print_str(b"abstract "); p.print_str(b"abstract ");
} }
if self.r#static { if self.r#static {
@ -2509,7 +2433,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for BindingPattern<'a> {
BindingPatternKind::ArrayPattern(pattern) => pattern.gen(p, ctx), BindingPatternKind::ArrayPattern(pattern) => pattern.gen(p, ctx),
BindingPatternKind::AssignmentPattern(pattern) => pattern.gen(p, ctx), BindingPatternKind::AssignmentPattern(pattern) => pattern.gen(p, ctx),
} }
if p.options.enable_typescript {
if self.optional { if self.optional {
p.print_str(b"?"); p.print_str(b"?");
} }
@ -2520,7 +2443,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for BindingPattern<'a> {
} }
} }
} }
}
impl<'a, const MINIFY: bool> Gen<MINIFY> for ObjectPattern<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for ObjectPattern<'a> {
fn gen(&self, p: &mut Codegen<MINIFY>, ctx: Context) { fn gen(&self, p: &mut Codegen<MINIFY>, ctx: Context) {

View file

@ -478,9 +478,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSTypeParameterInstantiation<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSIndexSignature<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for TSIndexSignature<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
if !p.options.enable_typescript {
return;
}
p.print_str(b"["); p.print_str(b"[");
for (index, parameter) in self.parameters.iter().enumerate() { for (index, parameter) in self.parameters.iter().enumerate() {
if index != 0 { if index != 0 {
@ -563,9 +560,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSModuleDeclaration<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSTypeAliasDeclaration<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for TSTypeAliasDeclaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
if !p.options.enable_typescript {
return;
}
p.print_str(b"type "); p.print_str(b"type ");
self.id.gen(p, ctx); self.id.gen(p, ctx);
if let Some(type_parameters) = &self.type_parameters { if let Some(type_parameters) = &self.type_parameters {
@ -579,10 +573,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSTypeAliasDeclaration<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSInterfaceDeclaration<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for TSInterfaceDeclaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
if !p.options.enable_typescript {
return;
}
p.print_str(b"interface"); p.print_str(b"interface");
p.print_hard_space(); p.print_hard_space();
self.id.gen(p, ctx); self.id.gen(p, ctx);
@ -623,15 +613,11 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSInterfaceHeritage<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSEnumDeclaration<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for TSEnumDeclaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
if !p.options.enable_typescript {
return;
}
p.print_indent(); p.print_indent();
if self.modifiers.contains(ModifierKind::Export) { if self.modifiers.contains(ModifierKind::Export) {
p.print_str(b"export "); p.print_str(b"export ");
} }
if p.options.enable_typescript && self.modifiers.contains(ModifierKind::Declare) { if self.modifiers.contains(ModifierKind::Declare) {
p.print_str(b"declare "); p.print_str(b"declare ");
} }
if self.modifiers.contains(ModifierKind::Const) { if self.modifiers.contains(ModifierKind::Const) {
@ -684,9 +670,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSConstructorType<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSImportEqualsDeclaration<'a> { impl<'a, const MINIFY: bool> Gen<MINIFY> for TSImportEqualsDeclaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
if !p.options.enable_typescript {
return;
}
p.print_str(b"import "); p.print_str(b"import ");
self.id.gen(p, ctx); self.id.gen(p, ctx);
p.print_str(b" = "); p.print_str(b" = ");
@ -709,11 +692,9 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSModuleReference<'a> {
impl<'a, const MINIFY: bool> GenExpr<MINIFY> for TSTypeAssertion<'a> { impl<'a, const MINIFY: bool> GenExpr<MINIFY> for TSTypeAssertion<'a> {
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) { fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) {
if p.options.enable_typescript {
p.print_str(b"<"); p.print_str(b"<");
self.type_annotation.gen(p, ctx); self.type_annotation.gen(p, ctx);
p.print_str(b">"); p.print_str(b">");
}
self.expression.gen_expr(p, precedence, ctx); self.expression.gen_expr(p, precedence, ctx);
} }
} }

View file

@ -44,24 +44,10 @@ pub struct CodegenOptions {
/// Pass in the filename to enable source map support. /// Pass in the filename to enable source map support.
pub enable_source_map: bool, pub enable_source_map: bool,
/// Enable TypeScript code generation.
pub enable_typescript: bool,
/// Enable preserve annotate comments, like `/* #__PURE__ */` and `/* #__NO_SIDE_EFFECTS__ */`. /// Enable preserve annotate comments, like `/* #__PURE__ */` and `/* #__NO_SIDE_EFFECTS__ */`.
pub preserve_annotate_comments: bool, pub preserve_annotate_comments: bool,
} }
impl CodegenOptions {
#[must_use]
pub fn with_typescript(mut self, yes: bool) -> Self {
if yes {
self.enable_typescript = true;
}
self
}
}
pub struct CodegenReturn { pub struct CodegenReturn {
pub source_text: String, pub source_text: String,
pub source_map: Option<oxc_sourcemap::SourceMap>, pub source_map: Option<oxc_sourcemap::SourceMap>,
@ -471,9 +457,7 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
} }
for stmt in statements { for stmt in statements {
if let Some(decl) = stmt.as_declaration() { if let Some(decl) = stmt.as_declaration() {
if decl.is_typescript_syntax() if decl.is_typescript_syntax() && !matches!(decl, Declaration::TSEnumDeclaration(_))
&& !self.options.enable_typescript
&& !matches!(decl, Declaration::TSEnumDeclaration(_))
{ {
continue; continue;
} }

View file

@ -7,10 +7,10 @@ fn test(source_text: &str, expected: &str, options: Option<CodegenOptions>) {
let allocator = Allocator::default(); let allocator = Allocator::default();
let source_type = SourceType::default().with_module(true); let source_type = SourceType::default().with_module(true);
let ret = Parser::new(&allocator, source_text, source_type).parse(); let ret = Parser::new(&allocator, source_text, source_type).parse();
let program = allocator.alloc(ret.program);
let options = options.unwrap_or_default(); let options = options.unwrap_or_default();
let result = let result = Codegen::<false>::new("", source_text, ret.trivias, options)
Codegen::<false>::new("", source_text, ret.trivias, options).build(program).source_text; .build(&ret.program)
.source_text;
assert_eq!(expected, result, "for source {source_text}, expect {expected}, got {result}"); assert_eq!(expected, result, "for source {source_text}, expect {expected}, got {result}");
} }
@ -21,10 +21,9 @@ fn test_ts(source_text: &str, expected: &str, is_typescript_definition: bool) {
.with_typescript_definition(is_typescript_definition) .with_typescript_definition(is_typescript_definition)
.with_module(true); .with_module(true);
let ret = Parser::new(&allocator, source_text, source_type).parse(); let ret = Parser::new(&allocator, source_text, source_type).parse();
let program = allocator.alloc(ret.program); let codegen_options = CodegenOptions::default();
let codegen_options = CodegenOptions { enable_typescript: true, ..CodegenOptions::default() };
let result = Codegen::<false>::new("", source_text, ret.trivias, codegen_options) let result = Codegen::<false>::new("", source_text, ret.trivias, codegen_options)
.build(program) .build(&ret.program)
.source_text; .source_text;
assert_eq!(expected, result, "for source {source_text}, expect {expected}, got {result}"); assert_eq!(expected, result, "for source {source_text}, expect {expected}, got {result}");
} }
@ -186,11 +185,7 @@ fn test_comment_helper(source_text: &str, expected: &str) {
test( test(
source_text, source_text,
expected, expected,
Some(CodegenOptions { Some(CodegenOptions { enable_source_map: true, preserve_annotate_comments: true }),
enable_source_map: true,
enable_typescript: false,
preserve_annotate_comments: true,
}),
); );
} }
#[test] #[test]
@ -230,9 +225,9 @@ fn annotate_comment() {
/* #__NO_SIDE_EFFECTS__ */ async () => {}, /* #__NO_SIDE_EFFECTS__ */ async () => {},
/* #__NO_SIDE_EFFECTS__ */ async (y) => (y), /* #__NO_SIDE_EFFECTS__ */ async (y) => (y),
])", ])",
r"x([/* #__NO_SIDE_EFFECTS__ */ y => y, /* #__NO_SIDE_EFFECTS__ */ () => { r"x([/* #__NO_SIDE_EFFECTS__ */ (y) => y, /* #__NO_SIDE_EFFECTS__ */ () => {
}, /* #__NO_SIDE_EFFECTS__ */ y => y, /* #__NO_SIDE_EFFECTS__ */ async y => y, /* #__NO_SIDE_EFFECTS__ */ async() => { }, /* #__NO_SIDE_EFFECTS__ */ (y) => y, /* #__NO_SIDE_EFFECTS__ */ async (y) => y, /* #__NO_SIDE_EFFECTS__ */ async () => {
}, /* #__NO_SIDE_EFFECTS__ */ async y => y,]); }, /* #__NO_SIDE_EFFECTS__ */ async (y) => y,]);
", ",
); );
test_comment_helper( test_comment_helper(
@ -245,9 +240,9 @@ fn annotate_comment() {
/* #__NO_SIDE_EFFECTS__ */ async () => {}, /* #__NO_SIDE_EFFECTS__ */ async () => {},
/* #__NO_SIDE_EFFECTS__ */ async (y) => (y), /* #__NO_SIDE_EFFECTS__ */ async (y) => (y),
])", ])",
r"x([/* #__NO_SIDE_EFFECTS__ */ y => y, /* #__NO_SIDE_EFFECTS__ */ () => { r"x([/* #__NO_SIDE_EFFECTS__ */ (y) => y, /* #__NO_SIDE_EFFECTS__ */ () => {
}, /* #__NO_SIDE_EFFECTS__ */ y => y, /* #__NO_SIDE_EFFECTS__ */ async y => y, /* #__NO_SIDE_EFFECTS__ */ async() => { }, /* #__NO_SIDE_EFFECTS__ */ (y) => y, /* #__NO_SIDE_EFFECTS__ */ async (y) => y, /* #__NO_SIDE_EFFECTS__ */ async () => {
}, /* #__NO_SIDE_EFFECTS__ */ async y => y,]); }, /* #__NO_SIDE_EFFECTS__ */ async (y) => y,]);
", ",
); );
// //

View file

@ -214,7 +214,7 @@ fn r#for() {
test("for (x(a in b);;);", "for(x(a in b);;);"); test("for (x(a in b);;);", "for(x(a in b);;);");
test("for (x[a in b];;);", "for(x[a in b];;);"); test("for (x[a in b];;);", "for(x[a in b];;);");
test("for (x?.[a in b];;);", "for(x?.[a in b];;);"); test("for (x?.[a in b];;);", "for(x?.[a in b];;);");
test("for ((x => a in b);;);", "for(x=>(a in b);;);"); test("for ((x => a in b);;);", "for((x)=>(a in b);;);");
// Make sure for-of loops with commas are wrapped in parentheses // Make sure for-of loops with commas are wrapped in parentheses
test("for (let a in b, c);", "for(let a in b,c);"); test("for (let a in b, c);", "for(let a in b,c);");
@ -303,8 +303,8 @@ fn generator() {
#[test] #[test]
fn arrow() { fn arrow() {
test("() => {}", "()=>{};"); test("() => {}", "()=>{};");
test("x => (x, 0)", "x=>(x,0);"); test("x => (x, 0)", "(x)=>(x,0);");
test("x => {y}", "x=>{y};"); test("x => {y}", "(x)=>{y};");
test("(a = (b, c), ...d) => {}", "(a=(b,c),...d)=>{};"); test("(a = (b, c), ...d) => {}", "(a=(b,c),...d)=>{};");
test("({[1 + 2]: a = 3} = {[1 + 2]: 3}) => {}", "({[3]:a=3}={[3]:3})=>{};"); test("({[1 + 2]: a = 3} = {[1 + 2]: 3}) => {}", "({[3]:a=3}={[3]:3})=>{};");
test( test(
@ -515,7 +515,7 @@ fn minify() {
test("1.2", "1.2;"); test("1.2", "1.2;");
test("() => {}", "()=>{};"); test("() => {}", "()=>{};");
test("(a) => {}", "a=>{};"); test("(a) => {}", "(a)=>{};");
test("(...a) => {}", "(...a)=>{};"); test("(...a) => {}", "(...a)=>{};");
test("(a = 0) => {}", "(a=0)=>{};"); test("(a = 0) => {}", "(a=0)=>{};");
test("(a, b) => {}", "(a,b)=>{};"); test("(a, b) => {}", "(a,b)=>{};");

View file

@ -45,14 +45,14 @@ fn r#yield() {
#[test] #[test]
fn arrow() { fn arrow() {
test("x => a, b", "x=>a,b;"); test("x => a, b", "(x)=>a,b;");
test("x => (a, b)", "x=>(a,b);"); test("x => (a, b)", "(x)=>(a,b);");
test("x => (a => b)", "x=>a=>b;"); test("x => (a => b)", "(x)=>(a)=>b;");
test("x => y => a, b", "x=>y=>a,b;"); test("x => y => a, b", "(x)=>(y)=>a,b;");
test("x => y => (a = b)", "x=>y=>a=b;"); test("x => y => (a = b)", "(x)=>(y)=>a=b;");
test("x => y => z => a = b, c", "x=>y=>z=>a=b,c;"); test("x => y => z => a = b, c", "(x)=>(y)=>(z)=>a=b,c;");
test("x => y => z => a = (b, c)", "x=>y=>z=>a=(b,c);"); test("x => y => z => a = (b, c)", "(x)=>(y)=>(z)=>a=(b,c);");
test("x => ({} + 0)", "x=>({})+0;"); test("x => ({} + 0)", "(x)=>({})+0;");
} }
#[test] #[test]

View file

@ -44,7 +44,7 @@ impl<'a> TransformerDts<'a> {
&source_path.file_name().map(|n| n.to_string_lossy()).unwrap_or_default(), &source_path.file_name().map(|n| n.to_string_lossy()).unwrap_or_default(),
source_text, source_text,
trivias, trivias,
CodegenOptions::default().with_typescript(true), CodegenOptions::default(),
); );
let ctx = Rc::new(TransformDtsCtx::new(allocator)); let ctx = Rc::new(TransformDtsCtx::new(allocator));

View file

@ -155,7 +155,7 @@ impl Oxc {
run_options: &OxcRunOptions, run_options: &OxcRunOptions,
parser_options: &OxcParserOptions, parser_options: &OxcParserOptions,
_linter_options: &OxcLinterOptions, _linter_options: &OxcLinterOptions,
codegen_options: &OxcCodegenOptions, _codegen_options: &OxcCodegenOptions,
minifier_options: &OxcMinifierOptions, minifier_options: &OxcMinifierOptions,
) -> Result<(), serde_wasm_bindgen::Error> { ) -> Result<(), serde_wasm_bindgen::Error> {
self.diagnostics = RefCell::default(); self.diagnostics = RefCell::default();
@ -274,10 +274,7 @@ impl Oxc {
Minifier::new(options).build(&allocator, program); Minifier::new(options).build(&allocator, program);
} }
let codegen_options = CodegenOptions { let codegen_options = CodegenOptions::default();
enable_typescript: codegen_options.enable_typescript,
..CodegenOptions::default()
};
self.codegen_text = if minifier_options.whitespace() { self.codegen_text = if minifier_options.whitespace() {
Codegen::<true>::new("", source_text, ret.trivias, codegen_options) Codegen::<true>::new("", source_text, ret.trivias, codegen_options)
.build(program) .build(program)

View file

@ -374,13 +374,14 @@ Unexpected token
(53:16-54:0) "};" --> (106:0-107:0) "\n};" (53:16-54:0) "};" --> (106:0-107:0) "\n};"
(54:0-54:4) "\nvar" --> (107:0-107:4) "\nvar" (54:0-54:4) "\nvar" --> (107:0-107:4) "\nvar"
(54:4-54:8) " z =" --> (107:4-107:8) " z =" (54:4-54:8) " z =" --> (107:4-107:8) " z ="
(54:8-54:13) " x =>" --> (107:8-107:13) " x =>" (54:8-54:13) " x =>" --> (107:8-107:15) " (x) =>"
(54:13-54:15) " {" --> (107:13-108:0) " {" (54:13-54:15) " {" --> (107:15-108:0) " {"
(54:15-55:0) "};" --> (108:0-109:0) "\n};" (54:15-55:0) "};" --> (108:0-109:0) "\n};"
(55:0-55:4) "\nvar" --> (109:0-109:4) "\nvar" (55:0-55:4) "\nvar" --> (109:0-109:4) "\nvar"
(55:4-55:9) " z = " --> (109:4-109:8) " z =" (55:4-55:8) " z =" --> (109:4-109:8) " z ="
(55:9-55:15) "(x) =>" --> (109:8-109:13) " x =>" (55:8-55:9) " " --> (109:8-109:9) " "
(55:15-55:17) " {" --> (109:13-110:0) " {" (55:9-55:15) "(x) =>" --> (109:9-109:15) "(x) =>"
(55:15-55:17) " {" --> (109:15-110:0) " {"
(55:17-56:0) "};" --> (110:0-111:0) "\n};" (55:17-56:0) "};" --> (110:0-111:0) "\n};"
(56:0-56:4) "\nvar" --> (111:0-111:4) "\nvar" (56:0-56:4) "\nvar" --> (111:0-111:4) "\nvar"
(56:4-56:8) " z =" --> (111:4-111:8) " z =" (56:4-56:8) " z =" --> (111:4-111:8) " z ="

View file

@ -65,7 +65,7 @@ fn get_normal_result(
source_text: &str, source_text: &str,
source_type: SourceType, source_type: SourceType,
) -> bool { ) -> bool {
let options = CodegenOptions::default().with_typescript(source_type.is_typescript()); let options = CodegenOptions::default();
let allocator = Allocator::default(); let allocator = Allocator::default();
let parse_result1 = Parser::new(&allocator, source_text, source_type).parse(); let parse_result1 = Parser::new(&allocator, source_text, source_type).parse();
let source_text1 = Codegen::<false>::new("", source_text, parse_result1.trivias, options) let source_text1 = Codegen::<false>::new("", source_text, parse_result1.trivias, options)
@ -108,7 +108,7 @@ fn get_minify_result(
source_text: &str, source_text: &str,
source_type: SourceType, source_type: SourceType,
) -> bool { ) -> bool {
let options = CodegenOptions::default().with_typescript(source_type.is_typescript()); let options = CodegenOptions::default();
let allocator = Allocator::default(); let allocator = Allocator::default();
let parse_result1 = Parser::new(&allocator, source_text, source_type).parse(); let parse_result1 = Parser::new(&allocator, source_text, source_type).parse();
let source_text1 = let source_text1 =

View file

@ -43,7 +43,7 @@ fn get_result(
&filename, &filename,
source_text, source_text,
parse_result1.trivias.clone(), parse_result1.trivias.clone(),
CodegenOptions::default().with_typescript(true), CodegenOptions::default(),
) )
.build(&program) .build(&program)
.source_text; .source_text;

View file

@ -182,12 +182,7 @@ pub trait TestCase {
.build(&mut program); .build(&mut program);
result.map(|()| { result.map(|()| {
Codegen::<false>::new( Codegen::<false>::new("", &source_text, ret.trivias, CodegenOptions::default())
"",
&source_text,
ret.trivias,
CodegenOptions::default().with_typescript(true),
)
.build(&program) .build(&program)
.source_text .source_text
}) })
@ -256,7 +251,7 @@ impl TestCase for ConformanceTestCase {
println!("output_path: {output_path:?}"); println!("output_path: {output_path:?}");
} }
let codegen_options = CodegenOptions::default().with_typescript(true); let codegen_options = CodegenOptions::default();
let mut transformed_code = String::new(); let mut transformed_code = String::new();
let mut actual_errors = String::new(); let mut actual_errors = String::new();
@ -391,7 +386,7 @@ impl ExecTestCase {
"", "",
&source_text, &source_text,
transformed_ret.trivias, transformed_ret.trivias,
CodegenOptions::default().with_typescript(true), CodegenOptions::default(),
) )
.build(&transformed_ret.program) .build(&transformed_ret.program)
.source_text; .source_text;