Skip to content

Commit 4040416

Browse files
committed
feat(coverage): improve codegen
1 parent 41b3c24 commit 4040416

File tree

14 files changed

+1911
-1939
lines changed

14 files changed

+1911
-1939
lines changed

crates/oxc_codegen/src/gen.rs

+75-89
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,7 @@ fn print_directives_and_statements<const MINIFY: bool>(
5959
statements: &[Statement<'_>],
6060
ctx: Context,
6161
) {
62-
p.print_directives_and_statements_with_semicolon_order(
63-
Some(directives),
64-
statements,
65-
ctx,
66-
false,
67-
);
62+
p.print_directives_and_statements(Some(directives), statements, ctx);
6863
}
6964

7065
impl<'a, const MINIFY: bool> Gen<MINIFY> for Hashbang<'a> {
@@ -77,13 +72,14 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Hashbang<'a> {
7772
impl<'a, const MINIFY: bool> Gen<MINIFY> for Directive<'a> {
7873
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
7974
p.add_source_mapping(self.span.start);
75+
p.print_indent();
8076
// A Use Strict Directive may not contain an EscapeSequence or LineContinuation.
8177
// So here should print original `directive` value, the `expression` value is escaped str.
8278
// See https://github.com/babel/babel/blob/main/packages/babel-generator/src/generators/base.ts#L64
8379
p.wrap_quote(self.directive.as_str(), |p, _| {
8480
p.print_str(self.directive.as_bytes());
8581
});
86-
p.print_semicolon();
82+
p.print_semicolon_after_statement();
8783
}
8884
}
8985

@@ -108,10 +104,41 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Statement<'a> {
108104
Self::TryStatement(stmt) => stmt.gen(p, ctx),
109105
Self::WhileStatement(stmt) => stmt.gen(p, ctx),
110106
Self::WithStatement(stmt) => stmt.gen(p, ctx),
111-
match_module_declaration!(Self) => self.to_module_declaration().gen(p, ctx),
112-
match_declaration!(Self) => {
107+
108+
Self::ImportDeclaration(decl) => decl.gen(p, ctx),
109+
Self::ExportAllDeclaration(decl) => decl.gen(p, ctx),
110+
Self::ExportDefaultDeclaration(decl) => decl.gen(p, ctx),
111+
Self::ExportNamedDeclaration(decl) => decl.gen(p, ctx),
112+
Self::TSExportAssignment(decl) => decl.gen(p, ctx),
113+
Self::TSNamespaceExportDeclaration(decl) => decl.gen(p, ctx),
114+
115+
Self::VariableDeclaration(decl) => {
116+
p.print_indent();
117+
decl.gen(p, ctx);
118+
p.print_semicolon_after_statement();
119+
}
120+
Self::FunctionDeclaration(decl) => {
113121
p.print_indent();
114-
self.to_declaration().gen(p, ctx);
122+
decl.gen(p, ctx);
123+
p.print_soft_newline();
124+
}
125+
Self::ClassDeclaration(decl) => decl.gen(p, ctx),
126+
Self::UsingDeclaration(declaration) => declaration.gen(p, ctx),
127+
Self::TSModuleDeclaration(decl) => {
128+
decl.gen(p, ctx);
129+
p.print_soft_newline();
130+
}
131+
Self::TSTypeAliasDeclaration(decl) => {
132+
p.print_indent();
133+
decl.gen(p, ctx);
134+
p.print_semicolon_after_statement();
135+
}
136+
Self::TSInterfaceDeclaration(decl) => decl.gen(p, ctx),
137+
Self::TSEnumDeclaration(decl) => decl.gen(p, ctx),
138+
Self::TSImportEqualsDeclaration(decl) => {
139+
p.print_indent();
140+
decl.gen(p, ctx);
141+
p.print_semicolon_after_statement();
115142
}
116143
}
117144
}
@@ -529,68 +556,6 @@ impl<const MINIFY: bool> Gen<MINIFY> for DebuggerStatement {
529556
}
530557
}
531558

532-
impl<'a, const MINIFY: bool> Gen<MINIFY> for ModuleDeclaration<'a> {
533-
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
534-
match self {
535-
Self::ImportDeclaration(decl) => decl.gen(p, ctx),
536-
Self::ExportAllDeclaration(decl) => decl.gen(p, ctx),
537-
Self::ExportDefaultDeclaration(decl) => decl.gen(p, ctx),
538-
Self::ExportNamedDeclaration(decl) => decl.gen(p, ctx),
539-
Self::TSExportAssignment(decl) => decl.gen(p, ctx),
540-
Self::TSNamespaceExportDeclaration(decl) => decl.gen(p, ctx),
541-
}
542-
}
543-
}
544-
545-
impl<'a, const MINIFY: bool> Gen<MINIFY> for Declaration<'a> {
546-
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
547-
match self {
548-
Self::VariableDeclaration(decl) => {
549-
decl.gen(p, ctx);
550-
p.print_semicolon_after_statement();
551-
}
552-
Self::FunctionDeclaration(decl) => {
553-
p.print_space_before_identifier();
554-
decl.gen(p, ctx);
555-
p.print_soft_newline();
556-
}
557-
Self::ClassDeclaration(decl) => {
558-
p.print_space_before_identifier();
559-
decl.gen(p, ctx);
560-
p.print_soft_newline();
561-
}
562-
Self::UsingDeclaration(declaration) => {
563-
p.print_space_before_identifier();
564-
declaration.gen(p, ctx);
565-
p.print_soft_newline();
566-
}
567-
Self::TSModuleDeclaration(decl) => decl.gen(p, ctx),
568-
Self::TSTypeAliasDeclaration(decl) => {
569-
if decl.modifiers.contains(ModifierKind::Export) {
570-
p.print_str(b"export ");
571-
}
572-
if decl.modifiers.contains(ModifierKind::Declare) {
573-
p.print_str(b"declare ");
574-
}
575-
p.print_str(b"type");
576-
p.print_space_before_identifier();
577-
decl.id.gen(p, ctx);
578-
if let Some(type_parameters) = &decl.type_parameters {
579-
type_parameters.gen(p, ctx);
580-
}
581-
p.print_soft_space();
582-
p.print_str(b"=");
583-
p.print_soft_space();
584-
decl.type_annotation.gen(p, ctx);
585-
p.print_semicolon_after_statement();
586-
}
587-
Declaration::TSInterfaceDeclaration(decl) => decl.gen(p, ctx),
588-
Declaration::TSEnumDeclaration(decl) => decl.gen(p, ctx),
589-
Declaration::TSImportEqualsDeclaration(decl) => decl.gen(p, ctx),
590-
}
591-
}
592-
}
593-
594559
impl<'a, const MINIFY: bool> Gen<MINIFY> for UsingDeclaration<'a> {
595560
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
596561
if self.is_await {
@@ -635,6 +600,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for VariableDeclaration<'a> {
635600
p.print_list(&self.declarations, ctx);
636601
}
637602
}
603+
638604
impl<'a, const MINIFY: bool> Gen<MINIFY> for VariableDeclarator<'a> {
639605
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
640606
self.id.gen(p, ctx);
@@ -692,12 +658,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Function<'a> {
692658
impl<'a, const MINIFY: bool> Gen<MINIFY> for FunctionBody<'a> {
693659
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
694660
p.print_curly_braces(self.span, self.is_empty(), |p| {
695-
p.print_directives_and_statements_with_semicolon_order(
696-
Some(&self.directives),
697-
&self.statements,
698-
ctx,
699-
true,
700-
);
661+
p.print_directives_and_statements(Some(&self.directives), &self.statements, ctx);
701662
});
702663
p.needs_semicolon = false;
703664
}
@@ -883,7 +844,28 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportNamedDeclaration<'a> {
883844
}
884845
match &self.declaration {
885846
Some(decl) => {
886-
decl.gen(p, ctx);
847+
match decl {
848+
Declaration::VariableDeclaration(decl) => decl.gen(p, ctx),
849+
Declaration::FunctionDeclaration(decl) => decl.gen(p, ctx),
850+
Declaration::ClassDeclaration(decl) => decl.gen(p, ctx),
851+
Declaration::UsingDeclaration(declaration) => declaration.gen(p, ctx),
852+
Declaration::TSModuleDeclaration(decl) => decl.gen(p, ctx),
853+
Declaration::TSTypeAliasDeclaration(decl) => decl.gen(p, ctx),
854+
Declaration::TSInterfaceDeclaration(decl) => decl.gen(p, ctx),
855+
Declaration::TSEnumDeclaration(decl) => decl.gen(p, ctx),
856+
Declaration::TSImportEqualsDeclaration(decl) => decl.gen(p, ctx),
857+
}
858+
if matches!(
859+
decl,
860+
Declaration::VariableDeclaration(_)
861+
| Declaration::TSTypeAliasDeclaration(_)
862+
| Declaration::TSImportEqualsDeclaration(_)
863+
) {
864+
p.print_semicolon_after_statement();
865+
} else {
866+
p.print_soft_newline();
867+
p.needs_semicolon = false;
868+
}
887869
}
888870
None => {
889871
p.print(b'{');
@@ -968,7 +950,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportAllDeclaration<'a> {
968950
p.print_hard_space();
969951
}
970952
self.with_clause.gen(p, ctx);
971-
972953
p.print_semicolon_after_statement();
973954
}
974955
}
@@ -2786,7 +2767,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSMappedType<'a> {
27862767
p.print_soft_space();
27872768
type_annotation.gen(p, ctx);
27882769
}
2789-
p.print_semicolon_if_needed();
27902770
p.print_str(b"}");
27912771
}
27922772
}
@@ -2961,7 +2941,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSFunctionType<'a> {
29612941

29622942
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSSignature<'a> {
29632943
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
2964-
p.print_soft_space();
29652944
match self {
29662945
Self::TSIndexSignature(signature) => signature.gen(p, ctx),
29672946
Self::TSPropertySignature(signature) => {
@@ -3225,23 +3204,31 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSModuleBlock<'a> {
32253204
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
32263205
p.print_curly_braces(self.span, self.body.is_empty(), |p| {
32273206
for item in &self.body {
3228-
item.gen(p, ctx);
32293207
p.print_semicolon_if_needed();
3208+
item.gen(p, ctx);
32303209
}
32313210
});
32323211
}
32333212
}
32343213

32353214
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSTypeAliasDeclaration<'a> {
32363215
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
3237-
p.print_str(b"type ");
3216+
if self.modifiers.contains(ModifierKind::Export) {
3217+
p.print_str(b"export ");
3218+
}
3219+
if self.modifiers.contains(ModifierKind::Declare) {
3220+
p.print_str(b"declare ");
3221+
}
3222+
p.print_str(b"type");
3223+
p.print_space_before_identifier();
32383224
self.id.gen(p, ctx);
32393225
if let Some(type_parameters) = &self.type_parameters {
32403226
type_parameters.gen(p, ctx);
32413227
}
3242-
p.print_str(b" = ");
3228+
p.print_soft_space();
3229+
p.print_str(b"=");
3230+
p.print_soft_space();
32433231
self.type_annotation.gen(p, ctx);
3244-
p.print_semicolon_after_statement();
32453232
}
32463233
}
32473234

@@ -3263,9 +3250,9 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSInterfaceDeclaration<'a> {
32633250
p.print_curly_braces(self.body.span, self.body.body.is_empty(), |p| {
32643251
for item in &self.body.body {
32653252
p.print_indent();
3266-
p.print_semicolon_if_needed();
32673253
item.gen(p, ctx);
3268-
p.print_semicolon_after_statement();
3254+
p.print_semicolon();
3255+
p.print_soft_newline();
32693256
}
32703257
});
32713258
if MINIFY {
@@ -3363,7 +3350,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSImportEqualsDeclaration<'a> {
33633350
self.id.gen(p, ctx);
33643351
p.print_str(b" = ");
33653352
self.module_reference.gen(p, ctx);
3366-
p.print_semicolon_after_statement();
33673353
}
33683354
}
33693355

crates/oxc_codegen/src/lib.rs

+6-13
Original file line numberDiff line numberDiff line change
@@ -363,9 +363,9 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
363363

364364
fn print_block_statement(&mut self, stmt: &BlockStatement<'_>, ctx: Context) {
365365
self.print_curly_braces(stmt.span, stmt.body.is_empty(), |p| {
366-
p.print_directives_and_statements_with_semicolon_order(None, &stmt.body, ctx, true);
367-
p.needs_semicolon = false;
366+
p.print_directives_and_statements(None, &stmt.body, ctx);
368367
});
368+
self.needs_semicolon = false;
369369
}
370370

371371
fn print_block<T: Gen<MINIFY>>(
@@ -474,12 +474,11 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
474474
self.print(quote as u8);
475475
}
476476

477-
fn print_directives_and_statements_with_semicolon_order(
477+
fn print_directives_and_statements(
478478
&mut self,
479479
directives: Option<&[Directive]>,
480480
statements: &[Statement<'_>],
481481
ctx: Context,
482-
print_semicolon_first: bool,
483482
) {
484483
if let Some(directives) = directives {
485484
if directives.is_empty() {
@@ -491,20 +490,14 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
491490
}
492491
} else {
493492
for directive in directives {
494-
self.print_indent();
495493
directive.gen(self, ctx);
496-
self.print_soft_newline();
494+
self.print_semicolon_if_needed();
497495
}
498496
}
499497
}
500498
for stmt in statements {
501-
if print_semicolon_first {
502-
self.print_semicolon_if_needed();
503-
stmt.gen(self, ctx);
504-
} else {
505-
stmt.gen(self, ctx);
506-
self.print_semicolon_if_needed();
507-
}
499+
self.print_semicolon_if_needed();
500+
stmt.gen(self, ctx);
508501
}
509502
}
510503

crates/oxc_minifier/tests/closure/fold_conditions.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ use crate::test;
22

33
#[test]
44
fn test_fold_not() {
5-
test("while(!(x==y)){a=b;}", "for(;x!=y;)a=b;");
6-
test("while(!(x!=y)){a=b;}", "for(;x==y;)a=b;");
7-
test("while(!(x===y)){a=b;}", "for(;x!==y;)a=b;");
8-
test("while(!(x!==y)){a=b;}", "for(;x===y;)a=b;");
5+
test("while(!(x==y)){a=b;}", "for(;x!=y;)a=b");
6+
test("while(!(x!=y)){a=b;}", "for(;x==y;)a=b");
7+
test("while(!(x===y)){a=b;}", "for(;x!==y;)a=b");
8+
test("while(!(x!==y)){a=b;}", "for(;x===y;)a=b");
99

1010
// Because !(x<NaN) != x>=NaN don't fold < and > cases.
11-
test("while(!(x>y)){a=b;}", "for(;!(x>y);)a=b;");
12-
test("while(!(x>=y)){a=b;}", "for(;!(x>=y);)a=b;");
13-
test("while(!(x<y)){a=b;}", "for(;!(x<y);)a=b;");
14-
test("while(!(x<=y)){a=b;}", "for(;!(x<=y);)a=b;");
15-
test("while(!(x<=NaN)){a=b;}", "for(;!(x<=NaN);)a=b;");
11+
test("while(!(x>y)){a=b;}", "for(;!(x>y);)a=b");
12+
test("while(!(x>=y)){a=b;}", "for(;!(x>=y);)a=b");
13+
test("while(!(x<y)){a=b;}", "for(;!(x<y);)a=b");
14+
test("while(!(x<=y)){a=b;}", "for(;!(x<=y);)a=b");
15+
test("while(!(x<=NaN)){a=b;}", "for(;!(x<=NaN);)a=b");
1616

1717
// NOT forces a boolean context
1818
// test("x = !(y() && true)", "x=!y()");

0 commit comments

Comments
 (0)