Skip to content

Commit

Permalink
feat(codegen): prefer backquotes over double / single quotes
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red committed Feb 3, 2025
1 parent a5bdf32 commit df82694
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 66 deletions.
32 changes: 21 additions & 11 deletions crates/oxc_codegen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ impl Gen for ImportDeclaration<'_> {
p.print_str("from");
}
p.print_soft_space();
self.source.print(p, ctx);
p.print_quoted_utf16(&self.source.value, false);
if let Some(with_clause) = &self.with_clause {
p.print_soft_space();
with_clause.print(p, ctx);
Expand Down Expand Up @@ -980,16 +980,18 @@ impl Gen for WithClause<'_> {
}

impl Gen for ImportAttribute<'_> {
fn gen(&self, p: &mut Codegen, ctx: Context) {
fn gen(&self, p: &mut Codegen, _ctx: Context) {
match &self.key {
ImportAttributeKey::Identifier(identifier) => {
p.print_str(identifier.name.as_str());
}
ImportAttributeKey::StringLiteral(literal) => literal.print(p, ctx),
ImportAttributeKey::StringLiteral(literal) => {
p.print_quoted_utf16(&literal.value, false);
}
};
p.print_colon();
p.print_soft_space();
self.value.print(p, ctx);
p.print_quoted_utf16(&self.value.value, false);
}
}

Expand Down Expand Up @@ -1055,7 +1057,7 @@ impl Gen for ExportNamedDeclaration<'_> {
p.print_soft_space();
p.print_str("from");
p.print_soft_space();
source.print(p, ctx);
p.print_quoted_utf16(&source.value, false);
}
p.print_semicolon_after_statement();
}
Expand Down Expand Up @@ -1111,7 +1113,7 @@ impl Gen for ModuleExportName<'_> {
match self {
Self::IdentifierName(ident) => ident.print(p, ctx),
Self::IdentifierReference(ident) => ident.print(p, ctx),
Self::StringLiteral(literal) => literal.print(p, ctx),
Self::StringLiteral(literal) => p.print_quoted_utf16(&literal.value, false),
};
}
}
Expand Down Expand Up @@ -1139,7 +1141,7 @@ impl Gen for ExportAllDeclaration<'_> {

p.print_str("from");
p.print_soft_space();
self.source.print(p, ctx);
p.print_quoted_utf16(&self.source.value, false);
if let Some(with_clause) = &self.with_clause {
p.print_hard_space();
with_clause.print(p, ctx);
Expand Down Expand Up @@ -3451,6 +3453,9 @@ impl Gen for TSSignature<'_> {
PropertyKey::PrivateIdentifier(key) => {
p.print_str(key.name.as_str());
}
PropertyKey::StringLiteral(key) => {
p.print_quoted_utf16(&key.value, false);
}
key => {
key.to_expression().print_expr(p, Precedence::Comma, ctx);
}
Expand Down Expand Up @@ -3499,6 +3504,9 @@ impl Gen for TSPropertySignature<'_> {
PropertyKey::PrivateIdentifier(key) => {
p.print_str(key.name.as_str());
}
PropertyKey::StringLiteral(key) => {
p.print_quoted_utf16(&key.value, false);
}
key => {
key.to_expression().print_expr(p, Precedence::Comma, ctx);
}
Expand Down Expand Up @@ -3585,7 +3593,9 @@ impl Gen for TSImportAttributeName<'_> {
fn gen(&self, p: &mut Codegen, ctx: Context) {
match self {
TSImportAttributeName::Identifier(ident) => ident.print(p, ctx),
TSImportAttributeName::StringLiteral(literal) => literal.print(p, ctx),
TSImportAttributeName::StringLiteral(literal) => {
p.print_quoted_utf16(&literal.value, false);
}
}
}
}
Expand Down Expand Up @@ -3689,7 +3699,7 @@ impl Gen for TSModuleDeclarationName<'_> {
fn gen(&self, p: &mut Codegen, ctx: Context) {
match self {
Self::Identifier(ident) => ident.print(p, ctx),
Self::StringLiteral(s) => s.print(p, ctx),
Self::StringLiteral(s) => p.print_quoted_utf16(&s.value, false),
}
}
}
Expand Down Expand Up @@ -3793,7 +3803,7 @@ impl Gen for TSEnumMember<'_> {
fn gen(&self, p: &mut Codegen, ctx: Context) {
match &self.id {
TSEnumMemberName::Identifier(decl) => decl.print(p, ctx),
TSEnumMemberName::String(decl) => decl.print(p, ctx),
TSEnumMemberName::String(decl) => p.print_quoted_utf16(&decl.value, false),
}
if let Some(init) = &self.initializer {
p.print_soft_space();
Expand Down Expand Up @@ -3837,7 +3847,7 @@ impl Gen for TSModuleReference<'_> {
match self {
Self::ExternalModuleReference(decl) => {
p.print_str("require(");
decl.expression.print(p, ctx);
p.print_quoted_utf16(&decl.expression.value, false);
p.print_str(")");
}
match_ts_type_name!(Self) => self.to_ts_type_name().print(p, ctx),
Expand Down
12 changes: 6 additions & 6 deletions crates/oxc_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,13 +612,13 @@ impl<'a> Codegen<'a> {
}
}
let mut quote = b'"';
if double_cost > single_cost {
quote = b'\'';
if single_cost > backtick_cost && allow_backtick {
quote = b'`';
}
} else if double_cost > backtick_cost && allow_backtick {
if allow_backtick && double_cost >= backtick_cost {
quote = b'`';
if backtick_cost > single_cost {
quote = b'\'';
}
} else if double_cost > single_cost {
quote = b'\'';
}
quote
} else {
Expand Down
69 changes: 46 additions & 23 deletions crates/oxc_codegen/tests/integration/snapshots/minify.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10,51 +10,51 @@ function foo<T extends string>(x: T, y: string, ...restOfParams: Omit<T, 'x'>):
return x;
}
----------
function foo<T extends string>(x:T,y:string,...restOfParams:Omit<T,"x">): T{return x}
function foo<T extends string>(x:T,y:string,...restOfParams:Omit<T,`x`>): T{return x}
########## 2
let x: string[] = ['abc', 'def', 'ghi'];
----------
let x:string[]=["abc","def","ghi"];
let x:string[]=[`abc`,`def`,`ghi`];
########## 3
let x: Array<string> = ['abc', 'def', 'ghi',];
----------
let x:Array<string>=["abc","def","ghi"];
let x:Array<string>=[`abc`,`def`,`ghi`];
########## 4
let x: [string, number] = ['abc', 123];
----------
let x:[string,number]=["abc",123];
let x:[string,number]=[`abc`,123];
########## 5
let x: string | number = 'abc';
----------
let x:string|number="abc";
let x:string|number=`abc`;
########## 6
let x: string & number = 'abc';
----------
let x:string&number="abc";
let x:string&number=`abc`;
########## 7
let x: typeof String = 'string';
----------
let x:typeof String="string";
let x:typeof String=`string`;
########## 8
let x: keyof string = 'length';
----------
let x:keyof string="length";
let x:keyof string=`length`;
########## 9
let x: keyof typeof String = 'length';
----------
let x:keyof typeof String="length";
let x:keyof typeof String=`length`;
########## 10
let x: string['length'] = 123;
----------
let x:string["length"]=123;
let x:string[`length`]=123;
########## 11
function isString(value: unknown): asserts value is string {
if (typeof value !== 'string') {
throw new Error('Not a string');
}
}
----------
function isString(value:unknown): asserts value is string{if(typeof value!=="string"){throw new Error("Not a string")}}
function isString(value:unknown): asserts value is string{if(typeof value!==`string`){throw new Error(`Not a string`)}}
########## 12
import type { Foo } from 'foo';
----------
Expand All @@ -74,7 +74,7 @@ type A<T>={[K in keyof T as K extends string ? B<K> : K]:T[K]};
########## 16
class A {readonly type = 'frame'}
----------
class A{readonly type="frame"}
class A{readonly type=`frame`}
########## 17
let foo: { <T>(t: T): void }
----------
Expand Down Expand Up @@ -104,34 +104,50 @@ abstract class A {private abstract static readonly prop: string}
----------
abstract class A{private abstract static readonly prop:string}
########## 24
interface A { a: string, 'b': number, 'c'(): void }
----------
interface A{a:string;"b":number;"c"():void;}
########## 25
enum A { a, 'b' }
----------
enum A {a,"b",}
########## 26
module 'a'
----------
module "a"
########## 27
declare module 'a'
----------
declare module "a"
########## 28
a = x!;
----------
a=x! ;
########## 25
########## 29
b = (x as y);
----------
b=x as y;
########## 26
########## 30
c = foo<string>;
----------
c=foo<string> ;
########## 27
########## 31
d = x satisfies y;
----------
d=((x) satisfies y);
########## 28
########## 32
export @x declare abstract class C {}
----------
export @x declare abstract class C{}
########## 29
########## 33
div<T>``
----------
div<T>``;
########## 30
########## 34
export type Component<Props = any> = Foo;
----------
export type Component<Props = any>=Foo;
########## 31
########## 35

export type Component<
Props = any,
Expand All @@ -147,19 +163,19 @@ export type Component<

----------
export type Component<Props = any,RawBindings = any,D = any,C extends ComputedOptions = ComputedOptions,M extends MethodOptions = MethodOptions,E extends EmitsOptions|Record<string,any[]> = {},S extends Record<string,any> = any>=ConcreteComponent<Props,RawBindings,D,C,M,E,S>|ComponentPublicInstanceConstructor<Props>;
########## 32
########## 36
(a || b) as any
----------
(a||b) as any;
########## 33
########## 37
(a ** b) as any
----------
(a**b) as any;
########## 34
########## 38
(function g() {}) as any
----------
(function g(){}) as any;
########## 35
########## 39

import defaultExport from "module-name";
import * as name from "module-name";
Expand Down Expand Up @@ -196,3 +212,10 @@ export { default as name16 } from "module-name";

----------
import defaultExport from"module-name";import*as name from"module-name";import{export1}from"module-name";import{export1 as alias1}from"module-name";import{default as alias}from"module-name";import{export1,export2}from"module-name";import{export1,export2 as alias2}from"module-name";import{"string name" as alias}from"module-name";import defaultExport,{export1}from"module-name";import defaultExport,*as name from"module-name";import"module-name";import{}from"mod";export let name1,name2;export const name3=1,name4=2;export function functionName(){}export class ClassName{}export function*generatorFunctionName(){}export const{name5,name2:bar}=o;export const[name6,name7]=array;export{name8,name81};export{variable1 as name9,variable2 as name10,name82};export{variable1 as "string name"};export{name1 as default1};export*from"module-name";export*as name11 from"module-name";export{name12,nameN}from"module-name";export{import1 as name13,import2 as name14,name15}from"module-name";export{default}from"module-name";export{default as name16}from"module-name";
########## 40

import a = require("a");
export import b = require("b");

----------
import a = require("a");export import b = require("b");
Loading

0 comments on commit df82694

Please sign in to comment.