Skip to content

Commit 3cf8a9c

Browse files
committed
feat(codegen): prefer backquotes over double / single quotes
1 parent 84b62c7 commit 3cf8a9c

File tree

7 files changed

+146
-65
lines changed

7 files changed

+146
-65
lines changed

crates/oxc_codegen/src/gen.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,7 @@ impl Gen for ImportDeclaration<'_> {
952952
p.print_str("from");
953953
}
954954
p.print_soft_space();
955-
self.source.print(p, ctx);
955+
p.print_quoted_utf16(&self.source.value, false);
956956
if let Some(with_clause) = &self.with_clause {
957957
p.print_soft_space();
958958
with_clause.print(p, ctx);
@@ -980,16 +980,18 @@ impl Gen for WithClause<'_> {
980980
}
981981

982982
impl Gen for ImportAttribute<'_> {
983-
fn gen(&self, p: &mut Codegen, ctx: Context) {
983+
fn gen(&self, p: &mut Codegen, _ctx: Context) {
984984
match &self.key {
985985
ImportAttributeKey::Identifier(identifier) => {
986986
p.print_str(identifier.name.as_str());
987987
}
988-
ImportAttributeKey::StringLiteral(literal) => literal.print(p, ctx),
988+
ImportAttributeKey::StringLiteral(literal) => {
989+
p.print_quoted_utf16(&literal.value, false);
990+
}
989991
};
990992
p.print_colon();
991993
p.print_soft_space();
992-
self.value.print(p, ctx);
994+
p.print_quoted_utf16(&self.value.value, false);
993995
}
994996
}
995997

@@ -1055,7 +1057,7 @@ impl Gen for ExportNamedDeclaration<'_> {
10551057
p.print_soft_space();
10561058
p.print_str("from");
10571059
p.print_soft_space();
1058-
source.print(p, ctx);
1060+
p.print_quoted_utf16(&source.value, false);
10591061
}
10601062
p.print_semicolon_after_statement();
10611063
}
@@ -1111,7 +1113,7 @@ impl Gen for ModuleExportName<'_> {
11111113
match self {
11121114
Self::IdentifierName(ident) => ident.print(p, ctx),
11131115
Self::IdentifierReference(ident) => ident.print(p, ctx),
1114-
Self::StringLiteral(literal) => literal.print(p, ctx),
1116+
Self::StringLiteral(literal) => p.print_quoted_utf16(&literal.value, false),
11151117
};
11161118
}
11171119
}
@@ -1139,7 +1141,7 @@ impl Gen for ExportAllDeclaration<'_> {
11391141

11401142
p.print_str("from");
11411143
p.print_soft_space();
1142-
self.source.print(p, ctx);
1144+
p.print_quoted_utf16(&self.source.value, false);
11431145
if let Some(with_clause) = &self.with_clause {
11441146
p.print_hard_space();
11451147
with_clause.print(p, ctx);
@@ -3451,6 +3453,9 @@ impl Gen for TSSignature<'_> {
34513453
PropertyKey::PrivateIdentifier(key) => {
34523454
p.print_str(key.name.as_str());
34533455
}
3456+
PropertyKey::StringLiteral(key) => {
3457+
p.print_quoted_utf16(&key.value, false);
3458+
}
34543459
key => {
34553460
key.to_expression().print_expr(p, Precedence::Comma, ctx);
34563461
}
@@ -3499,6 +3504,9 @@ impl Gen for TSPropertySignature<'_> {
34993504
PropertyKey::PrivateIdentifier(key) => {
35003505
p.print_str(key.name.as_str());
35013506
}
3507+
PropertyKey::StringLiteral(key) => {
3508+
p.print_quoted_utf16(&key.value, false);
3509+
}
35023510
key => {
35033511
key.to_expression().print_expr(p, Precedence::Comma, ctx);
35043512
}
@@ -3585,7 +3593,9 @@ impl Gen for TSImportAttributeName<'_> {
35853593
fn gen(&self, p: &mut Codegen, ctx: Context) {
35863594
match self {
35873595
TSImportAttributeName::Identifier(ident) => ident.print(p, ctx),
3588-
TSImportAttributeName::StringLiteral(literal) => literal.print(p, ctx),
3596+
TSImportAttributeName::StringLiteral(literal) => {
3597+
p.print_quoted_utf16(&literal.value, false);
3598+
}
35893599
}
35903600
}
35913601
}
@@ -3689,7 +3699,7 @@ impl Gen for TSModuleDeclarationName<'_> {
36893699
fn gen(&self, p: &mut Codegen, ctx: Context) {
36903700
match self {
36913701
Self::Identifier(ident) => ident.print(p, ctx),
3692-
Self::StringLiteral(s) => s.print(p, ctx),
3702+
Self::StringLiteral(s) => p.print_quoted_utf16(&s.value, false),
36933703
}
36943704
}
36953705
}
@@ -3793,7 +3803,7 @@ impl Gen for TSEnumMember<'_> {
37933803
fn gen(&self, p: &mut Codegen, ctx: Context) {
37943804
match &self.id {
37953805
TSEnumMemberName::Identifier(decl) => decl.print(p, ctx),
3796-
TSEnumMemberName::String(decl) => decl.print(p, ctx),
3806+
TSEnumMemberName::String(decl) => p.print_quoted_utf16(&decl.value, false),
37973807
}
37983808
if let Some(init) = &self.initializer {
37993809
p.print_soft_space();
@@ -3837,7 +3847,7 @@ impl Gen for TSModuleReference<'_> {
38373847
match self {
38383848
Self::ExternalModuleReference(decl) => {
38393849
p.print_str("require(");
3840-
decl.expression.print(p, ctx);
3850+
p.print_quoted_utf16(&decl.expression.value, false);
38413851
p.print_str(")");
38423852
}
38433853
match_ts_type_name!(Self) => self.to_ts_type_name().print(p, ctx),

crates/oxc_codegen/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -612,13 +612,13 @@ impl<'a> Codegen<'a> {
612612
}
613613
}
614614
let mut quote = b'"';
615-
if double_cost > single_cost {
616-
quote = b'\'';
617-
if single_cost > backtick_cost && allow_backtick {
618-
quote = b'`';
619-
}
620-
} else if double_cost > backtick_cost && allow_backtick {
615+
if allow_backtick && double_cost >= backtick_cost {
621616
quote = b'`';
617+
if backtick_cost > single_cost {
618+
quote = b'\'';
619+
}
620+
} else if double_cost > single_cost {
621+
quote = b'\'';
622622
}
623623
quote
624624
} else {

crates/oxc_codegen/tests/integration/snapshots/minify.snap

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,51 +10,51 @@ function foo<T extends string>(x: T, y: string, ...restOfParams: Omit<T, 'x'>):
1010
return x;
1111
}
1212
----------
13-
function foo<T extends string>(x:T,y:string,...restOfParams:Omit<T,"x">): T{return x}
13+
function foo<T extends string>(x:T,y:string,...restOfParams:Omit<T,`x`>): T{return x}
1414
########## 2
1515
let x: string[] = ['abc', 'def', 'ghi'];
1616
----------
17-
let x:string[]=["abc","def","ghi"];
17+
let x:string[]=[`abc`,`def`,`ghi`];
1818
########## 3
1919
let x: Array<string> = ['abc', 'def', 'ghi',];
2020
----------
21-
let x:Array<string>=["abc","def","ghi"];
21+
let x:Array<string>=[`abc`,`def`,`ghi`];
2222
########## 4
2323
let x: [string, number] = ['abc', 123];
2424
----------
25-
let x:[string,number]=["abc",123];
25+
let x:[string,number]=[`abc`,123];
2626
########## 5
2727
let x: string | number = 'abc';
2828
----------
29-
let x:string|number="abc";
29+
let x:string|number=`abc`;
3030
########## 6
3131
let x: string & number = 'abc';
3232
----------
33-
let x:string&number="abc";
33+
let x:string&number=`abc`;
3434
########## 7
3535
let x: typeof String = 'string';
3636
----------
37-
let x:typeof String="string";
37+
let x:typeof String=`string`;
3838
########## 8
3939
let x: keyof string = 'length';
4040
----------
41-
let x:keyof string="length";
41+
let x:keyof string=`length`;
4242
########## 9
4343
let x: keyof typeof String = 'length';
4444
----------
45-
let x:keyof typeof String="length";
45+
let x:keyof typeof String=`length`;
4646
########## 10
4747
let x: string['length'] = 123;
4848
----------
49-
let x:string["length"]=123;
49+
let x:string[`length`]=123;
5050
########## 11
5151
function isString(value: unknown): asserts value is string {
5252
if (typeof value !== 'string') {
5353
throw new Error('Not a string');
5454
}
5555
}
5656
----------
57-
function isString(value:unknown): asserts value is string{if(typeof value!=="string"){throw new Error("Not a string")}}
57+
function isString(value:unknown): asserts value is string{if(typeof value!==`string`){throw new Error(`Not a string`)}}
5858
########## 12
5959
import type { Foo } from 'foo';
6060
----------
@@ -74,7 +74,7 @@ type A<T>={[K in keyof T as K extends string ? B<K> : K]:T[K]};
7474
########## 16
7575
class A {readonly type = 'frame'}
7676
----------
77-
class A{readonly type="frame"}
77+
class A{readonly type=`frame`}
7878
########## 17
7979
let foo: { <T>(t: T): void }
8080
----------
@@ -104,34 +104,50 @@ abstract class A {private abstract static readonly prop: string}
104104
----------
105105
abstract class A{private abstract static readonly prop:string}
106106
########## 24
107+
interface A { a: string, 'b': number, 'c'(): void }
108+
----------
109+
interface A{a:string;"b":number;"c"():void;}
110+
########## 25
111+
enum A { a, 'b' }
112+
----------
113+
enum A {a,"b",}
114+
########## 26
115+
module 'a'
116+
----------
117+
module "a"
118+
########## 27
119+
declare module 'a'
120+
----------
121+
declare module "a"
122+
########## 28
107123
a = x!;
108124
----------
109125
a=x! ;
110-
########## 25
126+
########## 29
111127
b = (x as y);
112128
----------
113129
b=x as y;
114-
########## 26
130+
########## 30
115131
c = foo<string>;
116132
----------
117133
c=foo<string> ;
118-
########## 27
134+
########## 31
119135
d = x satisfies y;
120136
----------
121137
d=((x) satisfies y);
122-
########## 28
138+
########## 32
123139
export @x declare abstract class C {}
124140
----------
125141
export @x declare abstract class C{}
126-
########## 29
142+
########## 33
127143
div<T>``
128144
----------
129145
div<T>``;
130-
########## 30
146+
########## 34
131147
export type Component<Props = any> = Foo;
132148
----------
133149
export type Component<Props = any>=Foo;
134-
########## 31
150+
########## 35
135151

136152
export type Component<
137153
Props = any,
@@ -147,19 +163,19 @@ export type Component<
147163

148164
----------
149165
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>;
150-
########## 32
166+
########## 36
151167
(a || b) as any
152168
----------
153169
(a||b) as any;
154-
########## 33
170+
########## 37
155171
(a ** b) as any
156172
----------
157173
(a**b) as any;
158-
########## 34
174+
########## 38
159175
(function g() {}) as any
160176
----------
161177
(function g(){}) as any;
162-
########## 35
178+
########## 39
163179

164180
import defaultExport from "module-name";
165181
import * as name from "module-name";
@@ -196,3 +212,10 @@ export { default as name16 } from "module-name";
196212

197213
----------
198214
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";
215+
########## 40
216+
217+
import a = require("a");
218+
export import b = require("b");
219+
220+
----------
221+
import a = require("a");export import b = require("b");

0 commit comments

Comments
 (0)