1use std::ops::Not;
2
3use cow_utils::CowUtils;
4use oxc_ast::ast::*;
5use oxc_span::GetSpan;
6use oxc_syntax::{
7 operator::UnaryOperator,
8 precedence::{GetPrecedence, Precedence},
9};
10
11use crate::{
12 Codegen, Context, Operator, Quote,
13 binary_expr_visitor::{BinaryExpressionVisitor, Binaryish, BinaryishOperator},
14};
15
16const PURE_COMMENT: &str = "/* @__PURE__ */ ";
17const NO_SIDE_EFFECTS_NEW_LINE_COMMENT: &str = "/* @__NO_SIDE_EFFECTS__ */\n";
18const NO_SIDE_EFFECTS_COMMENT: &str = "/* @__NO_SIDE_EFFECTS__ */ ";
19
20pub trait Gen: GetSpan {
22 fn r#gen(&self, p: &mut Codegen, ctx: Context);
24
25 #[inline]
27 fn print(&self, p: &mut Codegen, ctx: Context) {
28 self.r#gen(p, ctx);
29 }
30}
31
32pub trait GenExpr: GetSpan {
34 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context);
36
37 #[inline]
39 fn print_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
40 self.gen_expr(p, precedence, ctx);
41 }
42}
43
44impl Gen for Program<'_> {
45 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
46 p.is_jsx = self.source_type.is_jsx();
47
48 if let Some(hashbang) = &self.hashbang {
49 hashbang.print(p, ctx);
50 }
51 for directive in &self.directives {
52 directive.print(p, ctx);
53 }
54 for stmt in &self.body {
55 stmt.print(p, ctx);
56 p.print_semicolon_if_needed();
57 }
58 p.print_statement_comments(self.span.end);
60 }
61}
62
63impl Gen for Hashbang<'_> {
64 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
65 p.print_str("#!");
66 p.print_str(self.value.as_str());
67 p.print_hard_newline();
68 }
69}
70
71impl Gen for Directive<'_> {
72 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
73 p.add_source_mapping(self.span);
74 p.print_indent();
75 let directive = self.directive.as_str();
79
80 let mut chars = directive.chars();
81 let mut quote = p.quote;
82 while let Some(c) = chars.next() {
83 match c {
84 '"' => {
85 quote = Quote::Single;
86 break;
87 }
88 '\'' => {
89 quote = Quote::Double;
90 break;
91 }
92 '\\' => {
93 chars.next();
94 }
95 _ => {}
96 }
97 }
98 quote.print(p);
99 p.print_str(directive);
100 quote.print(p);
101 p.print_ascii_byte(b';');
102 p.print_soft_newline();
103 }
104}
105
106impl Gen for Statement<'_> {
107 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
108 match self {
109 Self::BlockStatement(stmt) => {
110 p.print_statement_comments(stmt.span.start);
111 stmt.print(p, ctx);
112 }
113 Self::BreakStatement(stmt) => {
114 p.print_statement_comments(stmt.span.start);
115 stmt.print(p, ctx);
116 }
117 Self::ContinueStatement(stmt) => {
118 p.print_statement_comments(stmt.span.start);
119 stmt.print(p, ctx);
120 }
121 Self::DebuggerStatement(stmt) => {
122 p.print_statement_comments(stmt.span.start);
123 stmt.print(p, ctx);
124 }
125 Self::DoWhileStatement(stmt) => {
126 p.print_statement_comments(stmt.span.start);
127 stmt.print(p, ctx);
128 }
129 Self::EmptyStatement(stmt) => {
130 p.print_statement_comments(stmt.span.start);
131 stmt.print(p, ctx);
132 }
133 Self::ExpressionStatement(stmt) => {
134 p.print_statement_comments(stmt.span.start);
135 stmt.print(p, ctx);
136 }
137 Self::ForInStatement(stmt) => {
138 p.print_statement_comments(stmt.span.start);
139 stmt.print(p, ctx);
140 }
141 Self::ForOfStatement(stmt) => {
142 p.print_statement_comments(stmt.span.start);
143 stmt.print(p, ctx);
144 }
145 Self::ForStatement(stmt) => {
146 p.print_statement_comments(stmt.span.start);
147 stmt.print(p, ctx);
148 }
149 Self::IfStatement(stmt) => {
150 p.print_statement_comments(stmt.span.start);
151 stmt.print(p, ctx);
152 }
153 Self::LabeledStatement(stmt) => {
154 p.print_statement_comments(stmt.span.start);
155 stmt.print(p, ctx);
156 }
157 Self::ReturnStatement(stmt) => {
158 p.print_statement_comments(stmt.span.start);
159 stmt.print(p, ctx);
160 }
161 Self::SwitchStatement(stmt) => {
162 p.print_statement_comments(stmt.span.start);
163 stmt.print(p, ctx);
164 }
165 Self::ThrowStatement(stmt) => {
166 p.print_statement_comments(stmt.span.start);
167 stmt.print(p, ctx);
168 }
169 Self::TryStatement(stmt) => {
170 p.print_statement_comments(stmt.span.start);
171 stmt.print(p, ctx);
172 }
173 Self::WhileStatement(stmt) => {
174 p.print_statement_comments(stmt.span.start);
175 stmt.print(p, ctx);
176 }
177 Self::WithStatement(stmt) => {
178 p.print_statement_comments(stmt.span.start);
179 stmt.print(p, ctx);
180 }
181 Self::ImportDeclaration(decl) => {
182 p.print_statement_comments(decl.span.start);
183 decl.print(p, ctx);
184 }
185 Self::ExportAllDeclaration(decl) => {
186 p.print_statement_comments(decl.span.start);
187 decl.print(p, ctx);
188 }
189 Self::ExportDefaultDeclaration(decl) => {
190 p.print_statement_comments(decl.span.start);
191 if let ExportDefaultDeclarationKind::FunctionDeclaration(func) = &decl.declaration {
192 if func.pure && p.options.print_annotation_comments() {
193 p.print_str(NO_SIDE_EFFECTS_NEW_LINE_COMMENT);
194 }
195 }
196 decl.print(p, ctx);
197 }
198 Self::ExportNamedDeclaration(decl) => {
199 p.print_statement_comments(decl.span.start);
200 if let Some(Declaration::FunctionDeclaration(func)) = &decl.declaration {
201 if func.pure && p.options.print_annotation_comments() {
202 p.print_str(NO_SIDE_EFFECTS_NEW_LINE_COMMENT);
203 }
204 }
205 decl.print(p, ctx);
206 }
207 Self::TSExportAssignment(decl) => {
208 p.print_statement_comments(decl.span.start);
209 decl.print(p, ctx);
210 }
211 Self::TSNamespaceExportDeclaration(decl) => {
212 p.print_statement_comments(decl.span.start);
213 decl.print(p, ctx);
214 }
215 Self::VariableDeclaration(decl) => {
216 p.print_statement_comments(decl.span.start);
217 p.print_indent();
218 decl.print(p, ctx);
219 p.print_semicolon_after_statement();
220 }
221 Self::FunctionDeclaration(decl) => {
222 p.print_statement_comments(decl.span.start);
223 if decl.pure && p.options.print_annotation_comments() {
224 p.print_indent();
225 p.print_str(NO_SIDE_EFFECTS_NEW_LINE_COMMENT);
226 }
227 p.print_indent();
228 decl.print(p, ctx);
229 p.print_soft_newline();
230 }
231 Self::ClassDeclaration(decl) => {
232 p.print_statement_comments(decl.span.start);
233 p.print_indent();
234 decl.print(p, ctx);
235 p.print_soft_newline();
236 }
237 Self::TSModuleDeclaration(decl) => {
238 p.print_statement_comments(decl.span.start);
239 p.print_indent();
240 decl.print(p, ctx);
241 p.print_soft_newline();
242 }
243 Self::TSTypeAliasDeclaration(decl) => {
244 p.print_statement_comments(decl.span.start);
245 p.print_indent();
246 decl.print(p, ctx);
247 p.print_semicolon_after_statement();
248 }
249 Self::TSInterfaceDeclaration(decl) => {
250 p.print_statement_comments(decl.span.start);
251 p.print_indent();
252 decl.print(p, ctx);
253 p.print_soft_newline();
254 }
255 Self::TSEnumDeclaration(decl) => {
256 p.print_statement_comments(decl.span.start);
257 p.print_indent();
258 decl.print(p, ctx);
259 p.print_soft_newline();
260 }
261 Self::TSImportEqualsDeclaration(decl) => {
262 p.print_statement_comments(decl.span.start);
263 p.print_indent();
264 decl.print(p, ctx);
265 p.print_semicolon_after_statement();
266 }
267 }
268 }
269}
270
271impl Gen for ExpressionStatement<'_> {
272 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
273 p.add_source_mapping(self.span);
274 p.print_indent();
275 p.start_of_stmt = p.code_len();
276 p.print_expression(&self.expression);
277 if self.expression.is_specific_id("let") {
278 p.print_semicolon();
279 } else {
280 p.print_semicolon_after_statement();
281 }
282 }
283}
284
285impl Gen for IfStatement<'_> {
286 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
287 p.add_source_mapping(self.span);
288 p.print_indent();
289 print_if(self, p, ctx);
290 }
291}
292
293fn print_if(if_stmt: &IfStatement<'_>, p: &mut Codegen, ctx: Context) {
294 p.print_space_before_identifier();
295 p.print_str("if");
296 p.print_soft_space();
297 p.print_ascii_byte(b'(');
298 p.print_expression(&if_stmt.test);
299 p.print_ascii_byte(b')');
300
301 match &if_stmt.consequent {
302 Statement::BlockStatement(block) => {
303 p.print_soft_space();
304 p.print_block_statement(block, ctx);
305 if if_stmt.alternate.is_some() {
306 p.print_soft_space();
307 } else {
308 p.print_soft_newline();
309 }
310 }
311 stmt if wrap_to_avoid_ambiguous_else(stmt) => {
312 p.print_soft_space();
313 p.print_block_start(stmt.span());
314 stmt.print(p, ctx);
315 p.needs_semicolon = false;
316 p.print_block_end(stmt.span());
317 if if_stmt.alternate.is_some() {
318 p.print_soft_space();
319 } else {
320 p.print_soft_newline();
321 }
322 }
323 stmt => {
324 p.print_body(stmt, false, ctx);
325 if if_stmt.alternate.is_some() {
326 p.print_indent();
327 }
328 }
329 }
330 if let Some(alternate) = if_stmt.alternate.as_ref() {
331 p.print_semicolon_if_needed();
332 p.print_space_before_identifier();
333 p.print_str("else");
334 match alternate {
335 Statement::BlockStatement(block) => {
336 p.print_soft_space();
337 p.print_block_statement(block, ctx);
338 p.print_soft_newline();
339 }
340 Statement::IfStatement(if_stmt) => {
341 p.print_hard_space();
342 print_if(if_stmt, p, ctx);
343 }
344 stmt => p.print_body(stmt, true, ctx),
345 }
346 }
347}
348
349fn wrap_to_avoid_ambiguous_else(stmt: &Statement) -> bool {
351 let mut current = stmt;
352 loop {
353 current = match current {
354 Statement::IfStatement(if_stmt) => {
355 if let Some(stmt) = &if_stmt.alternate {
356 stmt
357 } else {
358 return true;
359 }
360 }
361 Statement::ForStatement(for_stmt) => &for_stmt.body,
362 Statement::ForOfStatement(for_of_stmt) => &for_of_stmt.body,
363 Statement::ForInStatement(for_in_stmt) => &for_in_stmt.body,
364 Statement::WhileStatement(while_stmt) => &while_stmt.body,
365 Statement::WithStatement(with_stmt) => &with_stmt.body,
366 Statement::LabeledStatement(labeled_stmt) => &labeled_stmt.body,
367 _ => return false,
368 }
369 }
370}
371
372impl Gen for BlockStatement<'_> {
373 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
374 p.print_indent();
375 p.print_block_statement(self, ctx);
376 p.print_soft_newline();
377 }
378}
379
380impl Gen for ForStatement<'_> {
381 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
382 p.add_source_mapping(self.span);
383 p.print_indent();
384 p.print_space_before_identifier();
385 p.print_str("for");
386 p.print_soft_space();
387 p.print_ascii_byte(b'(');
388
389 if let Some(init) = &self.init {
390 init.print(p, Context::FORBID_IN);
391 }
392
393 p.print_semicolon();
394
395 if let Some(test) = self.test.as_ref() {
396 p.print_soft_space();
397 p.print_expression(test);
398 }
399
400 p.print_semicolon();
401
402 if let Some(update) = self.update.as_ref() {
403 p.print_soft_space();
404 p.print_expression(update);
405 }
406
407 p.print_ascii_byte(b')');
408 p.print_body(&self.body, false, ctx);
409 }
410}
411
412impl Gen for ForInStatement<'_> {
413 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
414 p.add_source_mapping(self.span);
415 p.print_indent();
416 p.print_space_before_identifier();
417 p.print_str("for");
418 p.print_soft_space();
419 p.print_ascii_byte(b'(');
420 self.left.print(p, Context::FORBID_IN);
421 p.print_soft_space();
422 p.print_space_before_identifier();
423 p.print_str("in");
424 p.print_soft_space();
425 p.print_expression(&self.right);
426 p.print_ascii_byte(b')');
427 p.print_body(&self.body, false, ctx);
428 }
429}
430
431impl Gen for ForOfStatement<'_> {
432 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
433 p.add_source_mapping(self.span);
434 p.print_indent();
435 p.print_space_before_identifier();
436 p.print_str("for");
437 if self.r#await {
438 p.print_str(" await");
439 }
440 p.print_soft_space();
441 p.print_ascii_byte(b'(');
442 self.left.print(p, ctx);
443 p.print_soft_space();
444 p.print_space_before_identifier();
445 p.print_str("of");
446 p.print_soft_space();
447 self.right.print_expr(p, Precedence::Comma, Context::empty());
448 p.print_ascii_byte(b')');
449 p.print_body(&self.body, false, ctx);
450 }
451}
452
453impl Gen for ForStatementInit<'_> {
454 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
455 match self {
456 Self::VariableDeclaration(var) => var.print(p, ctx),
457 _ => self.to_expression().print_expr(p, Precedence::Lowest, ctx),
458 }
459 }
460}
461
462impl Gen for ForStatementLeft<'_> {
463 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
464 match self {
465 ForStatementLeft::VariableDeclaration(var) => var.print(p, ctx),
466 ForStatementLeft::AssignmentTargetIdentifier(identifier) => {
467 let wrap = identifier.name == "async";
468 p.wrap(wrap, |p| self.to_assignment_target().print(p, ctx));
469 }
470 match_assignment_target!(ForStatementLeft) => {
471 p.wrap(false, |p| self.to_assignment_target().print(p, ctx));
472 }
473 }
474 }
475}
476
477impl Gen for WhileStatement<'_> {
478 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
479 p.add_source_mapping(self.span);
480 p.print_indent();
481 p.print_space_before_identifier();
482 p.print_str("while");
483 p.print_soft_space();
484 p.print_ascii_byte(b'(');
485 p.print_expression(&self.test);
486 p.print_ascii_byte(b')');
487 p.print_body(&self.body, false, ctx);
488 }
489}
490
491impl Gen for DoWhileStatement<'_> {
492 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
493 p.add_source_mapping(self.span);
494 p.print_indent();
495 p.print_space_before_identifier();
496 p.print_str("do");
497 match &self.body {
498 Statement::BlockStatement(block) => {
499 p.print_soft_space();
500 p.print_block_statement(block, ctx);
501 p.print_soft_space();
502 }
503 Statement::EmptyStatement(s) => s.print(p, ctx),
504 _ => {
505 p.print_soft_newline();
506 p.indent();
507 self.body.print(p, ctx);
508 p.print_semicolon_if_needed();
509 p.dedent();
510 p.print_indent();
511 }
512 }
513 p.print_str("while");
514 p.print_soft_space();
515 p.print_ascii_byte(b'(');
516 p.print_expression(&self.test);
517 p.print_ascii_byte(b')');
518 p.print_semicolon_after_statement();
519 }
520}
521
522impl Gen for EmptyStatement {
523 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
524 p.add_source_mapping(self.span);
525 p.print_indent();
526 p.print_semicolon();
527 p.print_soft_newline();
528 }
529}
530
531impl Gen for ContinueStatement<'_> {
532 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
533 p.add_source_mapping(self.span);
534 p.print_indent();
535 p.print_space_before_identifier();
536 p.print_str("continue");
537 if let Some(label) = &self.label {
538 p.print_soft_space();
539 label.print(p, ctx);
540 }
541 p.print_semicolon_after_statement();
542 }
543}
544
545impl Gen for BreakStatement<'_> {
546 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
547 p.add_source_mapping(self.span);
548 p.print_indent();
549 p.print_space_before_identifier();
550 p.print_str("break");
551 if let Some(label) = &self.label {
552 p.print_soft_space();
553 label.print(p, ctx);
554 }
555 p.print_semicolon_after_statement();
556 }
557}
558
559impl Gen for SwitchStatement<'_> {
560 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
561 p.add_source_mapping(self.span);
562 p.print_indent();
563 p.print_space_before_identifier();
564 p.print_str("switch");
565 p.print_soft_space();
566 p.print_ascii_byte(b'(');
567 p.print_expression(&self.discriminant);
568 p.print_ascii_byte(b')');
569 p.print_soft_space();
570 p.print_curly_braces(self.span, self.cases.is_empty(), |p| {
571 for case in &self.cases {
572 case.print(p, ctx);
573 }
574 });
575 p.print_soft_newline();
576 p.needs_semicolon = false;
577 }
578}
579
580impl Gen for SwitchCase<'_> {
581 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
582 p.print_semicolon_if_needed();
583 p.print_indent();
584 p.add_source_mapping(self.span);
585 match &self.test {
586 Some(test) => {
587 p.print_str("case");
588 p.print_soft_space();
589 p.print_expression(test);
590 }
591 None => p.print_str("default"),
592 }
593 p.print_colon();
594
595 if self.consequent.len() == 1 {
596 p.print_body(&self.consequent[0], false, ctx);
597 return;
598 }
599
600 p.print_soft_newline();
601 p.indent();
602 for item in &self.consequent {
603 p.print_semicolon_if_needed();
604 item.print(p, ctx);
605 }
606 p.dedent();
607 }
608}
609
610impl Gen for ReturnStatement<'_> {
611 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
612 p.add_source_mapping(self.span);
613 p.print_indent();
614 p.print_space_before_identifier();
615 p.print_str("return");
616 if let Some(arg) = &self.argument {
617 p.print_soft_space();
618 p.print_expression(arg);
619 }
620 p.print_semicolon_after_statement();
621 }
622}
623
624impl Gen for LabeledStatement<'_> {
625 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
626 if !p.options.minify && (p.indent > 0 || p.print_next_indent_as_space) {
627 p.add_source_mapping(self.span);
628 p.print_indent();
629 }
630 p.print_space_before_identifier();
631 self.label.print(p, ctx);
632 p.print_colon();
633 p.print_body(&self.body, false, ctx);
634 }
635}
636
637impl Gen for TryStatement<'_> {
638 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
639 p.add_source_mapping(self.span);
640 p.print_indent();
641 p.print_space_before_identifier();
642 p.print_str("try");
643 p.print_soft_space();
644 p.print_block_statement(&self.block, ctx);
645 if let Some(handler) = &self.handler {
646 handler.r#gen(p, ctx);
647 }
648 if let Some(finalizer) = &self.finalizer {
649 p.print_soft_space();
650 p.print_str("finally");
651 p.print_soft_space();
652 p.print_block_statement(finalizer, ctx);
653 }
654 p.print_soft_newline();
655 }
656}
657
658impl Gen for CatchClause<'_> {
659 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
660 p.print_soft_space();
661 p.print_statement_comments(self.span.start);
662 p.print_str("catch");
663 if let Some(param) = &self.param {
664 p.print_soft_space();
665 p.print_str("(");
666 param.pattern.print(p, ctx);
667 p.print_str(")");
668 }
669 p.print_soft_space();
670 p.print_block_statement(&self.body, ctx);
671 }
672}
673
674impl Gen for ThrowStatement<'_> {
675 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
676 p.add_source_mapping(self.span);
677 p.print_indent();
678 p.print_space_before_identifier();
679 p.print_str("throw");
680 p.print_soft_space();
681 p.print_expression(&self.argument);
682 p.print_semicolon_after_statement();
683 }
684}
685
686impl Gen for WithStatement<'_> {
687 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
688 p.add_source_mapping(self.span);
689 p.print_indent();
690 p.print_space_before_identifier();
691 p.print_str("with");
692 p.print_ascii_byte(b'(');
693 p.print_expression(&self.object);
694 p.print_ascii_byte(b')');
695 p.print_body(&self.body, false, ctx);
696 }
697}
698
699impl Gen for DebuggerStatement {
700 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
701 p.add_source_mapping(self.span);
702 p.print_indent();
703 p.print_space_before_identifier();
704 p.print_str("debugger");
705 p.print_semicolon_after_statement();
706 }
707}
708
709impl Gen for VariableDeclaration<'_> {
710 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
711 p.add_source_mapping(self.span);
712 p.print_space_before_identifier();
713 if self.declare {
714 p.print_str("declare ");
715 }
716
717 p.print_str(match self.kind {
718 VariableDeclarationKind::Const => "const",
719 VariableDeclarationKind::Let => "let",
720 VariableDeclarationKind::Var => "var",
721 VariableDeclarationKind::Using => "using",
722 VariableDeclarationKind::AwaitUsing => "await using",
723 });
724 if !self.declarations.is_empty() {
725 p.print_soft_space();
726 }
727 p.print_list(&self.declarations, ctx);
728 }
729}
730
731impl Gen for VariableDeclarator<'_> {
732 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
733 self.id.kind.print(p, ctx);
734 if self.definite {
735 p.print_ascii_byte(b'!');
736 }
737 if self.id.optional {
738 p.print_str("?");
739 }
740 if let Some(type_annotation) = &self.id.type_annotation {
741 p.print_colon();
742 p.print_soft_space();
743 type_annotation.print(p, ctx);
744 }
745 if let Some(init) = &self.init {
746 p.print_soft_space();
747 p.print_equal();
748 p.print_soft_space();
749 init.print_expr(p, Precedence::Comma, ctx);
750 }
751 }
752}
753
754impl Gen for Function<'_> {
755 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
756 let n = p.code_len();
757 let wrap = self.is_expression() && (p.start_of_stmt == n || p.start_of_default_export == n);
758 p.wrap(wrap, |p| {
759 p.print_space_before_identifier();
760 p.add_source_mapping(self.span);
761 if self.declare {
762 p.print_str("declare ");
763 }
764 if self.r#async {
765 p.print_str("async ");
766 }
767 p.print_str("function");
768 if self.generator {
769 p.print_ascii_byte(b'*');
770 p.print_soft_space();
771 }
772 if let Some(id) = &self.id {
773 p.print_space_before_identifier();
774 id.print(p, ctx);
775 }
776 if let Some(type_parameters) = &self.type_parameters {
777 type_parameters.print(p, ctx);
778 }
779 p.print_ascii_byte(b'(');
780 if let Some(this_param) = &self.this_param {
781 this_param.print(p, ctx);
782 if !self.params.is_empty() || self.params.rest.is_some() {
783 p.print_str(",");
784 p.print_soft_space();
785 }
786 }
787 self.params.print(p, ctx);
788 p.print_ascii_byte(b')');
789 if let Some(return_type) = &self.return_type {
790 p.print_str(": ");
791 return_type.print(p, ctx);
792 }
793 if let Some(body) = &self.body {
794 p.print_soft_space();
795 body.print(p, ctx);
796 } else {
797 p.print_semicolon();
798 }
799 });
800 }
801}
802
803impl Gen for FunctionBody<'_> {
804 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
805 let span_end = self.span.end;
806 let comments_at_end = if p.print_comments && span_end > 0 {
807 p.get_statement_comments(span_end - 1)
808 } else {
809 None
810 };
811 let is_empty = if self.is_empty() {
812 comments_at_end.is_none() || comments_at_end.as_ref().is_some_and(Vec::is_empty)
813 } else {
814 false
815 };
816 p.print_curly_braces(self.span, is_empty, |p| {
817 for directive in &self.directives {
818 directive.print(p, ctx);
819 }
820 for stmt in &self.statements {
821 p.print_semicolon_if_needed();
822 stmt.print(p, ctx);
823 }
824 if let Some(comments) = comments_at_end {
826 p.print_comments(&comments);
827 }
828 });
829 p.needs_semicolon = false;
830 }
831}
832
833impl Gen for FormalParameter<'_> {
834 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
835 for decorator in &self.decorators {
836 decorator.print(p, ctx);
837 p.print_soft_space();
838 }
839 if let Some(accessibility) = self.accessibility {
840 p.print_space_before_identifier();
841 p.print_str(accessibility.as_str());
842 p.print_soft_space();
843 }
844 if self.readonly {
845 p.print_space_before_identifier();
846 p.print_str("readonly");
847 p.print_soft_space();
848 }
849 self.pattern.print(p, ctx);
850 }
851}
852
853impl Gen for FormalParameters<'_> {
854 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
855 p.print_list(&self.items, ctx);
856 if let Some(rest) = &self.rest {
857 if !self.items.is_empty() {
858 p.print_comma();
859 p.print_soft_space();
860 }
861 rest.print(p, ctx);
862 }
863 }
864}
865
866impl Gen for ImportDeclaration<'_> {
867 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
868 p.add_source_mapping(self.span);
869 p.print_indent();
870 p.print_space_before_identifier();
871 p.print_str("import");
872 if self.import_kind.is_type() {
873 p.print_str(" type");
874 }
875 if let Some(phase) = self.phase {
876 p.print_hard_space();
877 p.print_str(phase.as_str());
878 }
879 if let Some(specifiers) = &self.specifiers {
880 if specifiers.is_empty() {
881 p.print_soft_space();
882 p.print_str("{}");
883 p.print_soft_space();
884 p.print_str("from");
885 p.print_soft_space();
886 p.print_ascii_byte(b'"');
887 p.print_str(self.source.value.as_str());
888 p.print_ascii_byte(b'"');
889 if let Some(with_clause) = &self.with_clause {
890 p.print_hard_space();
891 with_clause.print(p, ctx);
892 }
893 p.print_semicolon_after_statement();
894 return;
895 }
896
897 let mut in_block = false;
898 for (index, specifier) in specifiers.iter().enumerate() {
899 match specifier {
900 ImportDeclarationSpecifier::ImportDefaultSpecifier(spec) => {
901 if in_block {
902 p.print_soft_space();
903 p.print_str("},");
904 in_block = false;
905 } else if index == 0 {
906 p.print_hard_space();
907 } else {
908 p.print_comma();
909 p.print_soft_space();
910 }
911 spec.local.print(p, ctx);
912 if index == specifiers.len() - 1 {
913 p.print_hard_space();
914 }
915 }
916 ImportDeclarationSpecifier::ImportNamespaceSpecifier(spec) => {
917 if in_block {
918 p.print_soft_space();
919 p.print_str("},");
920 in_block = false;
921 } else if index == 0 {
922 p.print_soft_space();
923 } else {
924 p.print_comma();
925 p.print_soft_space();
926 }
927 p.print_ascii_byte(b'*');
928 p.print_soft_space();
929 p.print_str("as ");
930 spec.local.print(p, ctx);
931 p.print_hard_space();
932 }
933 ImportDeclarationSpecifier::ImportSpecifier(spec) => {
934 if in_block {
935 p.print_comma();
936 p.print_soft_space();
937 } else {
938 if index != 0 {
939 p.print_comma();
940 }
941 in_block = true;
942 p.print_soft_space();
943 p.print_ascii_byte(b'{');
944 p.print_soft_space();
945 }
946
947 if spec.import_kind.is_type() {
948 p.print_str("type ");
949 }
950
951 spec.imported.print(p, ctx);
952 let local_name = p.get_binding_identifier_name(&spec.local);
953 let imported_name = get_module_export_name(&spec.imported, p);
954 if imported_name != local_name {
955 p.print_str(" as ");
956 spec.local.print(p, ctx);
957 }
958 }
959 }
960 }
961 if in_block {
962 p.print_soft_space();
963 p.print_ascii_byte(b'}');
964 p.print_soft_space();
965 }
966 p.print_str("from");
967 }
968 p.print_soft_space();
969 p.print_string_literal(&self.source, false);
970 if let Some(with_clause) = &self.with_clause {
971 p.print_soft_space();
972 with_clause.print(p, ctx);
973 }
974 p.add_source_mapping_end(self.span);
975 p.print_semicolon_after_statement();
976 }
977}
978
979impl Gen for WithClause<'_> {
980 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
981 p.add_source_mapping(self.span);
982 self.attributes_keyword.print(p, ctx);
983 p.print_soft_space();
984 p.add_source_mapping(self.span);
985 p.print_ascii_byte(b'{');
986 if !self.with_entries.is_empty() {
987 p.print_soft_space();
988 p.print_list(&self.with_entries, ctx);
989 p.print_soft_space();
990 }
991 p.add_source_mapping_end(self.span);
992 p.print_ascii_byte(b'}');
993 }
994}
995
996impl Gen for ImportAttribute<'_> {
997 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
998 match &self.key {
999 ImportAttributeKey::Identifier(identifier) => {
1000 p.print_str(identifier.name.as_str());
1001 }
1002 ImportAttributeKey::StringLiteral(literal) => {
1003 p.print_string_literal(literal, false);
1004 }
1005 }
1006 p.print_colon();
1007 p.print_soft_space();
1008 p.print_string_literal(&self.value, false);
1009 }
1010}
1011
1012impl Gen for ExportNamedDeclaration<'_> {
1013 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1014 p.add_source_mapping(self.span);
1015 p.print_indent();
1016 p.print_str("export");
1017 if let Some(decl) = &self.declaration {
1018 p.print_hard_space();
1019 match decl {
1020 Declaration::VariableDeclaration(decl) => decl.print(p, ctx),
1021 Declaration::FunctionDeclaration(decl) => decl.print(p, ctx),
1022 Declaration::ClassDeclaration(decl) => decl.print(p, ctx),
1023 Declaration::TSModuleDeclaration(decl) => decl.print(p, ctx),
1024 Declaration::TSTypeAliasDeclaration(decl) => decl.print(p, ctx),
1025 Declaration::TSInterfaceDeclaration(decl) => decl.print(p, ctx),
1026 Declaration::TSEnumDeclaration(decl) => decl.print(p, ctx),
1027 Declaration::TSImportEqualsDeclaration(decl) => decl.print(p, ctx),
1028 }
1029 if matches!(
1030 decl,
1031 Declaration::VariableDeclaration(_)
1032 | Declaration::TSTypeAliasDeclaration(_)
1033 | Declaration::TSImportEqualsDeclaration(_)
1034 ) {
1035 p.print_semicolon_after_statement();
1036 } else {
1037 p.print_soft_newline();
1038 p.needs_semicolon = false;
1039 }
1040 } else {
1041 p.print_soft_space();
1042 p.print_ascii_byte(b'{');
1043 if !self.specifiers.is_empty() {
1044 p.print_soft_space();
1045 p.print_list(&self.specifiers, ctx);
1046 p.print_soft_space();
1047 }
1048 p.print_ascii_byte(b'}');
1049 if let Some(source) = &self.source {
1050 p.print_soft_space();
1051 p.print_str("from");
1052 p.print_soft_space();
1053 p.print_string_literal(source, false);
1054 }
1055 p.print_semicolon_after_statement();
1056 }
1057 }
1058}
1059
1060impl Gen for TSExportAssignment<'_> {
1061 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1062 p.print_indent();
1063 p.print_str("export = ");
1064 self.expression.print_expr(p, Precedence::Lowest, ctx);
1065 p.print_semicolon_after_statement();
1066 }
1067}
1068
1069impl Gen for TSNamespaceExportDeclaration<'_> {
1070 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1071 p.print_indent();
1072 p.print_str("export as namespace ");
1073 self.id.print(p, ctx);
1074 p.print_semicolon_after_statement();
1075 }
1076}
1077
1078fn get_module_export_name<'a>(
1079 module_export_name: &ModuleExportName<'a>,
1080 p: &Codegen<'a>,
1081) -> &'a str {
1082 match module_export_name {
1083 ModuleExportName::IdentifierName(ident) => ident.name.as_str(),
1084 ModuleExportName::IdentifierReference(ident) => p.get_identifier_reference_name(ident),
1085 ModuleExportName::StringLiteral(s) => s.value.as_str(),
1086 }
1087}
1088
1089impl Gen for ExportSpecifier<'_> {
1090 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1091 if self.export_kind.is_type() {
1092 p.print_str("type ");
1093 }
1094 self.local.print(p, ctx);
1095 let local_name = get_module_export_name(&self.local, p);
1096 let exported_name = get_module_export_name(&self.exported, p);
1097 if local_name != exported_name {
1098 p.print_str(" as ");
1099 self.exported.print(p, ctx);
1100 }
1101 }
1102}
1103
1104impl Gen for ModuleExportName<'_> {
1105 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1106 match self {
1107 Self::IdentifierName(ident) => ident.print(p, ctx),
1108 Self::IdentifierReference(ident) => ident.print(p, ctx),
1109 Self::StringLiteral(literal) => p.print_string_literal(literal, false),
1110 }
1111 }
1112}
1113
1114impl Gen for ExportAllDeclaration<'_> {
1115 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1116 p.add_source_mapping(self.span);
1117 p.print_indent();
1118 p.print_str("export");
1119 if self.export_kind.is_type() {
1120 p.print_str(" type ");
1121 } else {
1122 p.print_soft_space();
1123 }
1124 p.print_ascii_byte(b'*');
1125
1126 if let Some(exported) = &self.exported {
1127 p.print_soft_space();
1128 p.print_str("as ");
1129 exported.print(p, ctx);
1130 p.print_hard_space();
1131 } else {
1132 p.print_soft_space();
1133 }
1134
1135 p.print_str("from");
1136 p.print_soft_space();
1137 p.print_string_literal(&self.source, false);
1138 if let Some(with_clause) = &self.with_clause {
1139 p.print_hard_space();
1140 with_clause.print(p, ctx);
1141 }
1142 p.print_semicolon_after_statement();
1143 }
1144}
1145
1146impl Gen for ExportDefaultDeclaration<'_> {
1147 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1148 p.add_source_mapping(self.span);
1149 p.print_indent();
1150 p.print_str("export default ");
1151 self.declaration.print(p, ctx);
1152 }
1153}
1154impl Gen for ExportDefaultDeclarationKind<'_> {
1155 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1156 match self {
1157 Self::FunctionDeclaration(func) => {
1158 func.print(p, ctx);
1159 p.print_soft_newline();
1160 }
1161 Self::ClassDeclaration(class) => {
1162 class.print(p, ctx);
1163 p.print_soft_newline();
1164 }
1165 Self::TSInterfaceDeclaration(interface) => interface.print(p, ctx),
1166 _ => {
1167 p.start_of_default_export = p.code_len();
1168 self.to_expression().print_expr(p, Precedence::Comma, Context::empty());
1169 p.print_semicolon_after_statement();
1170 }
1171 }
1172 }
1173}
1174
1175impl GenExpr for Expression<'_> {
1176 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1177 match self {
1178 Self::BooleanLiteral(lit) => lit.print(p, ctx),
1179 Self::NullLiteral(lit) => lit.print(p, ctx),
1180 Self::NumericLiteral(lit) => lit.print_expr(p, precedence, ctx),
1181 Self::BigIntLiteral(lit) => lit.print_expr(p, precedence, ctx),
1182 Self::RegExpLiteral(lit) => lit.print(p, ctx),
1183 Self::StringLiteral(lit) => lit.print(p, ctx),
1184 Self::Identifier(ident) => ident.print(p, ctx),
1185 Self::ThisExpression(expr) => expr.print(p, ctx),
1186 Self::ComputedMemberExpression(expr) => expr.print_expr(p, precedence, ctx),
1187 Self::StaticMemberExpression(expr) => expr.print_expr(p, precedence, ctx),
1188 Self::PrivateFieldExpression(expr) => expr.print_expr(p, precedence, ctx),
1189 Self::CallExpression(expr) => expr.print_expr(p, precedence, ctx),
1190 Self::ArrayExpression(expr) => expr.print(p, ctx),
1191 Self::ObjectExpression(expr) => expr.print_expr(p, precedence, ctx),
1192 Self::FunctionExpression(func) => {
1193 if func.pure && p.options.print_annotation_comments() {
1194 p.print_str(NO_SIDE_EFFECTS_COMMENT);
1195 }
1196 func.print(p, ctx);
1197 }
1198 Self::ArrowFunctionExpression(func) => {
1199 if func.pure && p.options.print_annotation_comments() {
1200 p.print_str(NO_SIDE_EFFECTS_COMMENT);
1201 }
1202 func.print_expr(p, precedence, ctx);
1203 }
1204 Self::YieldExpression(expr) => expr.print_expr(p, precedence, ctx),
1205 Self::UpdateExpression(expr) => expr.print_expr(p, precedence, ctx),
1206 Self::UnaryExpression(expr) => expr.print_expr(p, precedence, ctx),
1207 Self::BinaryExpression(expr) => expr.print_expr(p, precedence, ctx),
1208 Self::PrivateInExpression(expr) => expr.print_expr(p, precedence, ctx),
1209 Self::LogicalExpression(expr) => expr.print_expr(p, precedence, ctx),
1210 Self::ConditionalExpression(expr) => expr.print_expr(p, precedence, ctx),
1211 Self::AssignmentExpression(expr) => expr.print_expr(p, precedence, ctx),
1212 Self::SequenceExpression(expr) => expr.print_expr(p, precedence, ctx),
1213 Self::ImportExpression(expr) => expr.print_expr(p, precedence, ctx),
1214 Self::TemplateLiteral(literal) => literal.print(p, ctx),
1215 Self::TaggedTemplateExpression(expr) => expr.print(p, ctx),
1216 Self::Super(sup) => sup.print(p, ctx),
1217 Self::AwaitExpression(expr) => expr.print_expr(p, precedence, ctx),
1218 Self::ChainExpression(expr) => expr.print_expr(p, precedence, ctx),
1219 Self::NewExpression(expr) => expr.print_expr(p, precedence, ctx),
1220 Self::MetaProperty(expr) => expr.print(p, ctx),
1221 Self::ClassExpression(expr) => expr.print(p, ctx),
1222 Self::JSXElement(el) => el.print(p, ctx),
1223 Self::JSXFragment(fragment) => fragment.print(p, ctx),
1224 Self::ParenthesizedExpression(e) => e.print_expr(p, precedence, ctx),
1225 Self::TSAsExpression(e) => e.print_expr(p, precedence, ctx),
1226 Self::TSSatisfiesExpression(e) => e.print_expr(p, precedence, ctx),
1227 Self::TSTypeAssertion(e) => e.print_expr(p, precedence, ctx),
1228 Self::TSNonNullExpression(e) => e.print_expr(p, precedence, ctx),
1229 Self::TSInstantiationExpression(e) => e.print_expr(p, precedence, ctx),
1230 Self::V8IntrinsicExpression(e) => e.print_expr(p, precedence, ctx),
1231 }
1232 }
1233}
1234
1235impl GenExpr for ParenthesizedExpression<'_> {
1236 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1237 self.expression.print_expr(p, precedence, ctx);
1238 }
1239}
1240
1241impl Gen for IdentifierReference<'_> {
1242 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
1243 let name = p.get_identifier_reference_name(self);
1244 p.print_space_before_identifier();
1245 p.add_source_mapping_for_name(self.span, name);
1246 p.print_str(name);
1247 }
1248}
1249
1250impl Gen for IdentifierName<'_> {
1251 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
1252 p.print_space_before_identifier();
1253 p.add_source_mapping(self.span);
1254 p.print_str(self.name.as_str());
1255 }
1256}
1257
1258impl Gen for BindingIdentifier<'_> {
1259 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
1260 let name = p.get_binding_identifier_name(self);
1261 p.print_space_before_identifier();
1262 p.add_source_mapping_for_name(self.span, name);
1263 p.print_str(name);
1264 }
1265}
1266
1267impl Gen for LabelIdentifier<'_> {
1268 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
1269 p.print_space_before_identifier();
1270 p.add_source_mapping_for_name(self.span, &self.name);
1271 p.print_str(self.name.as_str());
1272 }
1273}
1274
1275impl Gen for BooleanLiteral {
1276 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
1277 p.add_source_mapping(self.span);
1278 p.print_space_before_identifier();
1279 p.print_str(self.as_str());
1280 }
1281}
1282
1283impl Gen for NullLiteral {
1284 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
1285 p.print_space_before_identifier();
1286 p.add_source_mapping(self.span);
1287 p.print_str("null");
1288 }
1289}
1290
1291impl GenExpr for NumericLiteral<'_> {
1292 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1293 p.add_source_mapping(self.span);
1294 let value = self.value;
1295 if ctx.contains(Context::TYPESCRIPT) {
1296 p.print_str(&self.raw_str());
1297 } else if value.is_nan() {
1298 p.print_space_before_identifier();
1299 p.print_str("NaN");
1300 } else if value.is_infinite() {
1301 let wrap = (p.options.minify && precedence >= Precedence::Multiply)
1302 || (value.is_sign_negative() && precedence >= Precedence::Prefix);
1303 p.wrap(wrap, |p| {
1304 if value.is_sign_negative() {
1305 p.print_space_before_operator(Operator::Unary(UnaryOperator::UnaryNegation));
1306 p.print_ascii_byte(b'-');
1307 } else {
1308 p.print_space_before_identifier();
1309 }
1310 if p.options.minify {
1311 p.print_str("1/0");
1312 } else {
1313 p.print_str("Infinity");
1314 }
1315 });
1316 } else if value.is_sign_positive() {
1317 p.print_space_before_identifier();
1318 p.print_non_negative_float(value);
1319 } else if precedence >= Precedence::Prefix {
1320 p.print_str("(-");
1321 p.print_non_negative_float(value.abs());
1322 p.print_ascii_byte(b')');
1323 } else {
1324 p.print_space_before_operator(Operator::Unary(UnaryOperator::UnaryNegation));
1325 p.print_ascii_byte(b'-');
1326 p.print_non_negative_float(value.abs());
1327 }
1328 }
1329}
1330
1331impl GenExpr for BigIntLiteral<'_> {
1332 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, _ctx: Context) {
1333 p.print_space_before_identifier();
1334 p.add_source_mapping(self.span);
1335 let raw = self.raw.as_str().cow_replace('_', "");
1336 if !raw.starts_with('-') {
1337 p.print_str(&raw);
1338 } else if precedence >= Precedence::Prefix {
1339 p.print_ascii_byte(b'(');
1340 p.print_str(&raw);
1341 p.print_ascii_byte(b')');
1342 } else {
1343 p.print_str(&raw);
1344 }
1345 }
1346}
1347
1348impl Gen for RegExpLiteral<'_> {
1349 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
1350 p.add_source_mapping(self.span);
1351 let last = p.last_byte();
1352 let pattern_text = self.regex.pattern.source_text(p.source_text);
1353 if last == Some(b'/')
1355 || (last == Some(b'<') && pattern_text.cow_to_ascii_lowercase().starts_with("script"))
1356 {
1357 p.print_hard_space();
1358 }
1359 p.print_ascii_byte(b'/');
1360 p.print_str(pattern_text.as_ref());
1361 p.print_ascii_byte(b'/');
1362 p.print_str(self.regex.flags.to_inline_string().as_str());
1363 p.prev_reg_exp_end = p.code().len();
1364 }
1365}
1366
1367impl Gen for StringLiteral<'_> {
1368 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
1369 p.print_string_literal(self, true);
1370 }
1371}
1372
1373impl Gen for ThisExpression {
1374 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
1375 p.print_space_before_identifier();
1376 p.add_source_mapping(self.span);
1377 p.print_str("this");
1378 }
1379}
1380
1381impl GenExpr for MemberExpression<'_> {
1382 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1383 match self {
1384 Self::ComputedMemberExpression(expr) => expr.print_expr(p, precedence, ctx),
1385 Self::StaticMemberExpression(expr) => expr.print_expr(p, precedence, ctx),
1386 Self::PrivateFieldExpression(expr) => expr.print_expr(p, precedence, ctx),
1387 }
1388 }
1389}
1390
1391impl GenExpr for ComputedMemberExpression<'_> {
1392 fn gen_expr(&self, p: &mut Codegen, _precedence: Precedence, ctx: Context) {
1393 let wrap = self.object.get_identifier_reference().is_some_and(|r| r.name == "let");
1395 p.wrap(wrap, |p| {
1396 self.object.print_expr(p, Precedence::Postfix, ctx.intersection(Context::FORBID_CALL));
1397 });
1398 if self.optional {
1399 p.print_str("?.");
1400 }
1401 p.print_ascii_byte(b'[');
1402 self.expression.print_expr(p, Precedence::Lowest, Context::empty());
1403 p.print_ascii_byte(b']');
1404 }
1405}
1406
1407impl GenExpr for StaticMemberExpression<'_> {
1408 fn gen_expr(&self, p: &mut Codegen, _precedence: Precedence, ctx: Context) {
1409 self.object.print_expr(p, Precedence::Postfix, ctx.intersection(Context::FORBID_CALL));
1410 if self.optional {
1411 p.print_ascii_byte(b'?');
1412 } else if p.need_space_before_dot == p.code_len() {
1413 p.print_hard_space();
1415 }
1416 p.print_ascii_byte(b'.');
1417 self.property.print(p, ctx);
1418 }
1419}
1420
1421impl GenExpr for PrivateFieldExpression<'_> {
1422 fn gen_expr(&self, p: &mut Codegen, _precedence: Precedence, ctx: Context) {
1423 self.object.print_expr(p, Precedence::Postfix, ctx.intersection(Context::FORBID_CALL));
1424 if self.optional {
1425 p.print_str("?");
1426 }
1427 p.print_ascii_byte(b'.');
1428 self.field.print(p, ctx);
1429 }
1430}
1431
1432impl GenExpr for CallExpression<'_> {
1433 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1434 let is_statement = p.start_of_stmt == p.code_len();
1435 let is_export_default = p.start_of_default_export == p.code_len();
1436 let mut wrap = precedence >= Precedence::New || ctx.intersects(Context::FORBID_CALL);
1437 let pure = self.pure && p.options.print_annotation_comments();
1438 if precedence >= Precedence::Postfix && pure {
1439 wrap = true;
1440 }
1441
1442 p.wrap(wrap, |p| {
1443 if pure {
1444 p.print_str(PURE_COMMENT);
1445 }
1446 if is_export_default {
1447 p.start_of_default_export = p.code_len();
1448 } else if is_statement {
1449 p.start_of_stmt = p.code_len();
1450 }
1451 p.add_source_mapping(self.span);
1452 self.callee.print_expr(p, Precedence::Postfix, Context::empty());
1453 if self.optional {
1454 p.print_str("?.");
1455 }
1456 if let Some(type_parameters) = &self.type_arguments {
1457 type_parameters.print(p, ctx);
1458 }
1459 p.print_ascii_byte(b'(');
1460
1461 let (has_comment, has_comment_before_right_paren) =
1462 p.contains_comment_in_call_like_expression(self.span, self.arguments.as_slice());
1463 if has_comment {
1464 p.indent();
1465 p.print_list_with_comments(self.arguments.as_slice(), ctx);
1466 if !has_comment_before_right_paren || !p.print_expr_comments(self.span.end - 1) {
1468 p.print_soft_newline();
1469 }
1470 p.dedent();
1471 } else {
1472 p.print_list(&self.arguments, ctx);
1473 }
1474 p.print_ascii_byte(b')');
1475 p.add_source_mapping_end(self.span);
1476 });
1477 }
1478}
1479
1480impl Gen for Argument<'_> {
1481 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1482 match self {
1483 Self::SpreadElement(elem) => elem.print(p, ctx),
1484 _ => self.to_expression().print_expr(p, Precedence::Comma, Context::empty()),
1485 }
1486 }
1487}
1488
1489impl Gen for ArrayExpressionElement<'_> {
1490 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1491 match self {
1492 Self::SpreadElement(elem) => elem.print(p, ctx),
1493 Self::Elision(_span) => {}
1494 _ => self.to_expression().print_expr(p, Precedence::Comma, Context::empty()),
1495 }
1496 }
1497}
1498
1499impl Gen for SpreadElement<'_> {
1500 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
1501 p.add_source_mapping(self.span);
1502 p.print_ellipsis();
1503 self.argument.print_expr(p, Precedence::Comma, Context::empty());
1504 }
1505}
1506
1507impl Gen for ArrayExpression<'_> {
1508 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1509 let is_multi_line = self.elements.len() > 2;
1510 p.add_source_mapping(self.span);
1511 p.print_ascii_byte(b'[');
1512 if is_multi_line {
1513 p.indent();
1514 }
1515 for (i, item) in self.elements.iter().enumerate() {
1516 if i != 0 {
1517 p.print_comma();
1518 }
1519 if is_multi_line {
1520 p.print_soft_newline();
1521 p.print_indent();
1522 } else if i != 0 {
1523 p.print_soft_space();
1524 }
1525 item.print(p, ctx);
1526 if i == self.elements.len() - 1 && matches!(item, ArrayExpressionElement::Elision(_)) {
1527 p.print_comma();
1528 }
1529 }
1530 if is_multi_line {
1531 p.print_soft_newline();
1532 p.dedent();
1533 p.print_indent();
1534 }
1535 p.add_source_mapping_end(self.span);
1536 p.print_ascii_byte(b']');
1537 }
1538}
1539
1540impl GenExpr for ObjectExpression<'_> {
1541 fn gen_expr(&self, p: &mut Codegen, _precedence: Precedence, ctx: Context) {
1542 let n = p.code_len();
1543 let len = self.properties.len();
1544 let is_multi_line = len > 1;
1545 let wrap = p.start_of_stmt == n || p.start_of_arrow_expr == n;
1546 p.wrap(wrap, |p| {
1547 p.add_source_mapping(self.span);
1548 p.print_ascii_byte(b'{');
1549 if is_multi_line {
1550 p.indent();
1551 }
1552 for (i, item) in self.properties.iter().enumerate() {
1553 if i != 0 {
1554 p.print_comma();
1555 }
1556 if is_multi_line {
1557 p.print_soft_newline();
1558 p.print_indent();
1559 } else {
1560 p.print_soft_space();
1561 }
1562 item.print(p, ctx);
1563 }
1564 if is_multi_line {
1565 p.print_soft_newline();
1566 p.dedent();
1567 p.print_indent();
1568 } else if len > 0 {
1569 p.print_soft_space();
1570 }
1571 p.add_source_mapping_end(self.span);
1572 p.print_ascii_byte(b'}');
1573 });
1574 }
1575}
1576
1577impl Gen for ObjectPropertyKind<'_> {
1578 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1579 match self {
1580 Self::ObjectProperty(prop) => prop.print(p, ctx),
1581 Self::SpreadProperty(elem) => elem.print(p, ctx),
1582 }
1583 }
1584}
1585
1586impl Gen for ObjectProperty<'_> {
1587 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1588 if let Expression::FunctionExpression(func) = &self.value {
1589 p.add_source_mapping(self.span);
1590 let is_accessor = match &self.kind {
1591 PropertyKind::Init => false,
1592 PropertyKind::Get => {
1593 p.add_source_mapping(self.span);
1594 p.print_str("get");
1595 p.print_soft_space();
1596 true
1597 }
1598 PropertyKind::Set => {
1599 p.add_source_mapping(self.span);
1600 p.print_str("set");
1601 p.print_soft_space();
1602 true
1603 }
1604 };
1605 if self.method || is_accessor {
1606 if func.r#async {
1607 p.print_space_before_identifier();
1608 p.print_str("async");
1609 p.print_soft_space();
1610 }
1611 if func.generator {
1612 p.print_str("*");
1613 }
1614 if self.computed {
1615 p.print_ascii_byte(b'[');
1616 }
1617 self.key.print(p, ctx);
1618 if self.computed {
1619 p.print_ascii_byte(b']');
1620 }
1621 if let Some(type_parameters) = &func.type_parameters {
1622 type_parameters.print(p, ctx);
1623 }
1624 p.print_ascii_byte(b'(');
1625 func.params.print(p, ctx);
1626 p.print_ascii_byte(b')');
1627 if let Some(body) = &func.body {
1628 p.print_soft_space();
1629 body.print(p, ctx);
1630 }
1631 return;
1632 }
1633 }
1634
1635 let mut shorthand = false;
1636 if let PropertyKey::StaticIdentifier(key) = &self.key {
1637 if key.name == "__proto__" {
1638 shorthand = self.shorthand;
1639 } else if let Expression::Identifier(ident) = self.value.without_parentheses() {
1640 if key.name == p.get_identifier_reference_name(ident) {
1641 shorthand = true;
1642 }
1643 }
1644 }
1645
1646 let mut computed = self.computed;
1647
1648 if !computed {
1651 if let Some(Expression::NumericLiteral(n)) = self.key.as_expression() {
1652 if n.value.is_sign_negative() || n.value.is_infinite() {
1653 computed = true;
1654 }
1655 }
1656 }
1657
1658 if computed {
1659 p.print_ascii_byte(b'[');
1660 }
1661 if !shorthand {
1662 self.key.print(p, ctx);
1663 }
1664 if computed {
1665 p.print_ascii_byte(b']');
1666 }
1667 if !shorthand {
1668 p.print_colon();
1669 p.print_soft_space();
1670 }
1671 self.value.print_expr(p, Precedence::Comma, Context::empty());
1672 }
1673}
1674
1675impl Gen for PropertyKey<'_> {
1676 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1677 match self {
1678 Self::StaticIdentifier(ident) => ident.print(p, ctx),
1679 Self::PrivateIdentifier(ident) => ident.print(p, ctx),
1680 Self::StringLiteral(s) => p.print_string_literal(s, false),
1681 _ => self.to_expression().print_expr(p, Precedence::Comma, Context::empty()),
1682 }
1683 }
1684}
1685
1686impl GenExpr for ArrowFunctionExpression<'_> {
1687 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1688 p.wrap(precedence >= Precedence::Assign, |p| {
1689 if self.r#async {
1690 p.print_space_before_identifier();
1691 p.add_source_mapping(self.span);
1692 p.print_str("async");
1693 p.print_soft_space();
1694 }
1695 if let Some(type_parameters) = &self.type_parameters {
1696 type_parameters.print(p, ctx);
1697 }
1698 p.add_source_mapping(self.span);
1699 let remove_params_wrap = p.options.minify
1700 && self.params.items.len() == 1
1701 && self.params.rest.is_none()
1702 && self.type_parameters.is_none()
1703 && self.return_type.is_none()
1704 && {
1705 let param = &self.params.items[0];
1706 param.decorators.is_empty()
1707 && !param.has_modifier()
1708 && param.pattern.kind.is_binding_identifier()
1709 && param.pattern.type_annotation.is_none()
1710 && !param.pattern.optional
1711 };
1712 p.wrap(!remove_params_wrap, |p| {
1713 self.params.print(p, ctx);
1714 });
1715 if let Some(return_type) = &self.return_type {
1716 p.print_str(":");
1717 p.print_soft_space();
1718 return_type.print(p, ctx);
1719 }
1720 p.print_soft_space();
1721 p.print_str("=>");
1722 p.print_soft_space();
1723 if self.expression {
1724 if let Some(Statement::ExpressionStatement(stmt)) = &self.body.statements.first() {
1725 p.start_of_arrow_expr = p.code_len();
1726 stmt.expression.print_expr(p, Precedence::Comma, ctx);
1727 }
1728 } else {
1729 self.body.print(p, ctx);
1730 }
1731 });
1732 }
1733}
1734
1735impl GenExpr for YieldExpression<'_> {
1736 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, _ctx: Context) {
1737 p.wrap(precedence >= Precedence::Assign, |p| {
1738 p.print_space_before_identifier();
1739 p.add_source_mapping(self.span);
1740 p.print_str("yield");
1741 if self.delegate {
1742 p.print_ascii_byte(b'*');
1743 }
1744 if let Some(argument) = self.argument.as_ref() {
1745 p.print_soft_space();
1746 argument.print_expr(p, Precedence::Yield, Context::empty());
1747 }
1748 });
1749 }
1750}
1751
1752impl GenExpr for UpdateExpression<'_> {
1753 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1754 let operator = self.operator.as_str();
1755 p.wrap(precedence >= self.precedence(), |p| {
1756 if self.prefix {
1757 p.add_source_mapping(self.span);
1758 p.print_space_before_operator(self.operator.into());
1759 p.print_str(operator);
1760 p.prev_op = Some(self.operator.into());
1761 p.prev_op_end = p.code().len();
1762 self.argument.print_expr(p, Precedence::Prefix, ctx);
1763 } else {
1764 p.print_space_before_operator(self.operator.into());
1765 self.argument.print_expr(p, Precedence::Postfix, ctx);
1766 p.print_str(operator);
1767 p.prev_op = Some(self.operator.into());
1768 p.prev_op_end = p.code().len();
1769 }
1770 });
1771 }
1772}
1773
1774impl GenExpr for UnaryExpression<'_> {
1775 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1776 p.wrap(precedence >= self.precedence(), |p| {
1777 let operator = self.operator.as_str();
1778 if self.operator.is_keyword() {
1779 p.print_space_before_identifier();
1780 p.print_str(operator);
1781 p.print_soft_space();
1782 } else {
1783 p.print_space_before_operator(self.operator.into());
1784 p.print_str(operator);
1785 p.prev_op = Some(self.operator.into());
1786 p.prev_op_end = p.code().len();
1787 }
1788 let is_delete_infinity = self.operator == UnaryOperator::Delete
1790 && !p.options.minify
1791 && matches!(&self.argument, Expression::NumericLiteral(lit) if lit.value.is_sign_positive() && lit.value.is_infinite());
1792 if is_delete_infinity {
1793 p.print_str("(0,");
1794 p.print_soft_space();
1795 }
1796 self.argument.print_expr(p, Precedence::Exponentiation, ctx);
1797 if is_delete_infinity{
1798 p.print_ascii_byte(b')');
1799 }
1800 });
1801 }
1802}
1803
1804impl GenExpr for BinaryExpression<'_> {
1805 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1806 let v = BinaryExpressionVisitor {
1807 e: Binaryish::Binary(unsafe {
1810 std::mem::transmute::<&BinaryExpression<'_>, &BinaryExpression<'_>>(self)
1811 }),
1812 precedence,
1813 ctx,
1814 left_precedence: Precedence::Lowest,
1815 operator: BinaryishOperator::Binary(self.operator),
1816 wrap: false,
1817 right_precedence: Precedence::Lowest,
1818 };
1819 BinaryExpressionVisitor::gen_expr(v, p);
1820 }
1821}
1822
1823impl GenExpr for PrivateInExpression<'_> {
1824 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1825 p.wrap(precedence >= Precedence::Compare, |p| {
1826 self.left.print(p, ctx);
1827 p.print_str(" in ");
1828 self.right.print_expr(p, Precedence::Equals, Context::FORBID_IN);
1829 });
1830 }
1831}
1832
1833impl GenExpr for LogicalExpression<'_> {
1834 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1835 let v = BinaryExpressionVisitor {
1836 e: Binaryish::Logical(unsafe {
1839 std::mem::transmute::<&LogicalExpression<'_>, &LogicalExpression<'_>>(self)
1840 }),
1841 precedence,
1842 ctx,
1843 left_precedence: Precedence::Lowest,
1844 operator: BinaryishOperator::Logical(self.operator),
1845 wrap: false,
1846 right_precedence: Precedence::Lowest,
1847 };
1848 BinaryExpressionVisitor::gen_expr(v, p);
1849 }
1850}
1851
1852impl GenExpr for ConditionalExpression<'_> {
1853 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1854 let mut ctx = ctx;
1855 let wrap = precedence >= self.precedence();
1856 if wrap {
1857 ctx &= Context::FORBID_IN.not();
1858 }
1859 p.wrap(wrap, |p| {
1860 self.test.print_expr(p, Precedence::Conditional, ctx & Context::FORBID_IN);
1861 p.print_soft_space();
1862 p.print_ascii_byte(b'?');
1863 p.print_soft_space();
1864 self.consequent.print_expr(p, Precedence::Yield, Context::empty());
1865 p.print_soft_space();
1866 p.print_colon();
1867 p.print_soft_space();
1868 self.alternate.print_expr(p, Precedence::Yield, ctx & Context::FORBID_IN);
1869 });
1870 }
1871}
1872
1873impl GenExpr for AssignmentExpression<'_> {
1874 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1875 let n = p.code_len();
1876 let wrap = (p.start_of_stmt == n || p.start_of_arrow_expr == n)
1878 && matches!(self.left, AssignmentTarget::ObjectAssignmentTarget(_));
1879 p.wrap(wrap || precedence >= self.precedence(), |p| {
1880 self.left.print(p, ctx);
1881 p.print_soft_space();
1882 p.print_str(self.operator.as_str());
1883 p.print_soft_space();
1884 self.right.print_expr(p, Precedence::Comma, ctx);
1885 });
1886 }
1887}
1888
1889impl Gen for AssignmentTarget<'_> {
1890 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1891 match self {
1892 match_simple_assignment_target!(Self) => {
1893 self.to_simple_assignment_target().print_expr(
1894 p,
1895 Precedence::Comma,
1896 Context::empty(),
1897 );
1898 }
1899 match_assignment_target_pattern!(Self) => {
1900 self.to_assignment_target_pattern().print(p, ctx);
1901 }
1902 }
1903 }
1904}
1905
1906impl GenExpr for SimpleAssignmentTarget<'_> {
1907 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
1908 match self {
1909 Self::AssignmentTargetIdentifier(ident) => ident.print(p, ctx),
1910 Self::ComputedMemberExpression(expr) => expr.print_expr(p, precedence, ctx),
1911 Self::StaticMemberExpression(expr) => expr.print_expr(p, precedence, ctx),
1912 Self::PrivateFieldExpression(expr) => expr.print_expr(p, precedence, ctx),
1913 Self::TSAsExpression(e) => e.print_expr(p, precedence, ctx),
1914 Self::TSSatisfiesExpression(e) => e.print_expr(p, precedence, ctx),
1915 Self::TSNonNullExpression(e) => e.print_expr(p, precedence, ctx),
1916 Self::TSTypeAssertion(e) => e.print_expr(p, precedence, ctx),
1917 }
1918 }
1919}
1920
1921impl Gen for AssignmentTargetPattern<'_> {
1922 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1923 match self {
1924 Self::ArrayAssignmentTarget(target) => target.print(p, ctx),
1925 Self::ObjectAssignmentTarget(target) => target.print(p, ctx),
1926 }
1927 }
1928}
1929
1930impl Gen for ArrayAssignmentTarget<'_> {
1931 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1932 p.add_source_mapping(self.span);
1933 p.print_ascii_byte(b'[');
1934 for (i, item) in self.elements.iter().enumerate() {
1935 if i != 0 {
1936 p.print_comma();
1937 p.print_soft_space();
1938 }
1939 if let Some(item) = item {
1940 item.print(p, ctx);
1941 }
1942 if i == self.elements.len() - 1 && (item.is_none() || self.rest.is_some()) {
1943 p.print_comma();
1944 }
1945 }
1946 if let Some(target) = &self.rest {
1947 if !self.elements.is_empty() {
1948 p.print_soft_space();
1949 }
1950 p.add_source_mapping(self.span);
1951 target.print(p, ctx);
1952 }
1953 p.print_ascii_byte(b']');
1954 p.add_source_mapping_end(self.span);
1955 }
1956}
1957
1958impl Gen for ObjectAssignmentTarget<'_> {
1959 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1960 p.add_source_mapping(self.span);
1961 p.print_ascii_byte(b'{');
1962 p.print_list(&self.properties, ctx);
1963 if let Some(target) = &self.rest {
1964 if !self.properties.is_empty() {
1965 p.print_comma();
1966 p.print_soft_space();
1967 }
1968 p.add_source_mapping(self.span);
1969 target.print(p, ctx);
1970 }
1971 p.print_ascii_byte(b'}');
1972 p.add_source_mapping_end(self.span);
1973 }
1974}
1975
1976impl Gen for AssignmentTargetMaybeDefault<'_> {
1977 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1978 match self {
1979 match_assignment_target!(Self) => self.to_assignment_target().print(p, ctx),
1980 Self::AssignmentTargetWithDefault(target) => target.print(p, ctx),
1981 }
1982 }
1983}
1984
1985impl Gen for AssignmentTargetWithDefault<'_> {
1986 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1987 self.binding.print(p, ctx);
1988 p.print_soft_space();
1989 p.print_equal();
1990 p.print_soft_space();
1991 self.init.print_expr(p, Precedence::Comma, Context::empty());
1992 }
1993}
1994
1995impl Gen for AssignmentTargetProperty<'_> {
1996 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
1997 match self {
1998 Self::AssignmentTargetPropertyIdentifier(ident) => ident.print(p, ctx),
1999 Self::AssignmentTargetPropertyProperty(prop) => prop.print(p, ctx),
2000 }
2001 }
2002}
2003
2004impl Gen for AssignmentTargetPropertyIdentifier<'_> {
2005 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2006 let ident_name = p.get_identifier_reference_name(&self.binding);
2007 if ident_name == self.binding.name.as_str() {
2008 self.binding.print(p, ctx);
2009 } else {
2010 p.print_str(self.binding.name.as_str());
2012 p.print_colon();
2013 p.print_soft_space();
2014 p.print_str(ident_name);
2015 }
2016 if let Some(expr) = &self.init {
2017 p.print_soft_space();
2018 p.print_equal();
2019 p.print_soft_space();
2020 expr.print_expr(p, Precedence::Comma, Context::empty());
2021 }
2022 }
2023}
2024
2025impl Gen for AssignmentTargetPropertyProperty<'_> {
2026 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2027 let omit_key = if p.options.minify {
2028 let key_name = match &self.name {
2029 PropertyKey::StaticIdentifier(ident) => Some(&ident.name),
2030 _ => None,
2031 };
2032 let value_name =
2033 self.binding.identifier().map(|id| p.get_identifier_reference_name(id));
2034 match (key_name, value_name) {
2035 (Some(key_name), Some(value_name)) => key_name == value_name,
2036 _ => false,
2037 }
2038 } else {
2039 false
2040 };
2041 if !omit_key {
2042 match &self.name {
2043 PropertyKey::StaticIdentifier(ident) => {
2044 ident.print(p, ctx);
2045 }
2046 PropertyKey::PrivateIdentifier(ident) => {
2047 ident.print(p, ctx);
2048 }
2049 key => {
2050 if self.computed {
2051 p.print_ascii_byte(b'[');
2052 }
2053 key.to_expression().print_expr(p, Precedence::Comma, Context::empty());
2054 if self.computed {
2055 p.print_ascii_byte(b']');
2056 }
2057 }
2058 }
2059 p.print_colon();
2060 p.print_soft_space();
2061 }
2062 self.binding.print(p, ctx);
2063 }
2064}
2065
2066impl Gen for AssignmentTargetRest<'_> {
2067 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2068 p.print_ellipsis();
2069 self.target.print(p, ctx);
2070 }
2071}
2072
2073impl GenExpr for SequenceExpression<'_> {
2074 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
2075 p.wrap(precedence >= self.precedence(), |p| {
2076 p.print_expressions(&self.expressions, Precedence::Lowest, ctx.and_forbid_call(false));
2077 });
2078 }
2079}
2080
2081impl GenExpr for ImportExpression<'_> {
2082 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
2083 let wrap = precedence >= Precedence::New || ctx.intersects(Context::FORBID_CALL);
2084
2085 let print_comments = p.options.print_comments();
2086 let has_comment_before_right_paren =
2087 print_comments && self.span.end > 0 && p.has_comment(self.span.end - 1);
2088 let has_comment = print_comments
2089 && (has_comment_before_right_paren
2090 || p.has_comment(self.source.span().start)
2091 || self
2092 .options
2093 .as_ref()
2094 .is_some_and(|options| p.has_comment(options.span().start)));
2095
2096 p.wrap(wrap, |p| {
2097 p.print_space_before_identifier();
2098 p.add_source_mapping(self.span);
2099 p.print_str("import");
2100 if let Some(phase) = self.phase {
2101 p.print_str(phase.as_str());
2102 }
2103 p.print_ascii_byte(b'(');
2104 if has_comment {
2105 p.indent();
2106 }
2107 if p.print_expr_comments(self.source.span().start) {
2108 p.print_indent();
2109 } else if has_comment {
2110 p.print_soft_newline();
2111 p.print_indent();
2112 }
2113 self.source.print_expr(p, Precedence::Comma, Context::empty());
2114 if let Some(options) = &self.options {
2115 p.print_comma();
2116 if has_comment {
2117 p.print_soft_newline();
2118 p.print_indent();
2119 } else {
2120 p.print_soft_space();
2121 }
2122 options.gen_expr(p, Precedence::Comma, Context::empty());
2123 }
2124 if has_comment {
2125 if !has_comment_before_right_paren || !p.print_expr_comments(self.span.end - 1) {
2127 p.print_soft_newline();
2128 }
2129 p.dedent();
2130 }
2131 p.print_ascii_byte(b')');
2132 });
2133 }
2134}
2135
2136impl Gen for TemplateLiteral<'_> {
2137 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
2138 p.print_ascii_byte(b'`');
2139 let mut expressions = self.expressions.iter();
2140
2141 for quasi in &self.quasis {
2142 p.add_source_mapping(quasi.span);
2143 p.print_str(quasi.value.raw.as_str());
2144
2145 if let Some(expr) = expressions.next() {
2146 p.print_str("${");
2147 p.print_expression(expr);
2148 p.print_ascii_byte(b'}');
2149 }
2150 }
2151
2152 p.print_ascii_byte(b'`');
2153 }
2154}
2155
2156impl Gen for TaggedTemplateExpression<'_> {
2157 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2158 p.add_source_mapping(self.span);
2159 self.tag.print_expr(p, Precedence::Postfix, Context::empty());
2160 if let Some(type_parameters) = &self.type_arguments {
2161 type_parameters.print(p, ctx);
2162 }
2163 self.quasi.print(p, ctx);
2164 }
2165}
2166
2167impl Gen for Super {
2168 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
2169 p.print_space_before_identifier();
2170 p.add_source_mapping(self.span);
2171 p.print_str("super");
2172 }
2173}
2174
2175impl GenExpr for AwaitExpression<'_> {
2176 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
2177 p.wrap(precedence >= self.precedence(), |p| {
2178 p.print_space_before_identifier();
2179 p.add_source_mapping(self.span);
2180 p.print_str("await");
2181 p.print_soft_space();
2182 self.argument.print_expr(p, Precedence::Exponentiation, ctx);
2183 });
2184 }
2185}
2186
2187impl GenExpr for ChainExpression<'_> {
2188 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
2189 p.wrap(precedence >= Precedence::Postfix, |p| match &self.expression {
2190 ChainElement::CallExpression(expr) => expr.print_expr(p, precedence, ctx),
2191 ChainElement::TSNonNullExpression(expr) => expr.print_expr(p, precedence, ctx),
2192 ChainElement::ComputedMemberExpression(expr) => expr.print_expr(p, precedence, ctx),
2193 ChainElement::StaticMemberExpression(expr) => expr.print_expr(p, precedence, ctx),
2194 ChainElement::PrivateFieldExpression(expr) => expr.print_expr(p, precedence, ctx),
2195 });
2196 }
2197}
2198
2199impl GenExpr for NewExpression<'_> {
2200 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
2201 let mut wrap = precedence >= self.precedence();
2202 let pure = self.pure && p.options.print_annotation_comments();
2203 if precedence >= Precedence::Postfix && pure {
2204 wrap = true;
2205 }
2206 p.wrap(wrap, |p| {
2207 if pure {
2208 p.print_str(PURE_COMMENT);
2209 }
2210 p.print_space_before_identifier();
2211 p.add_source_mapping(self.span);
2212 p.print_str("new");
2213 p.print_soft_space();
2214 self.callee.print_expr(p, Precedence::New, Context::FORBID_CALL);
2215
2216 if !p.options.minify || !self.arguments.is_empty() || precedence >= Precedence::Postfix
2218 {
2219 p.print_ascii_byte(b'(');
2220 let (has_comment, has_comment_before_right_paren) = p
2221 .contains_comment_in_call_like_expression(self.span, self.arguments.as_slice());
2222 if has_comment {
2223 p.indent();
2224 p.print_list_with_comments(self.arguments.as_slice(), ctx);
2225 if !has_comment_before_right_paren || !p.print_expr_comments(self.span.end - 1)
2227 {
2228 p.print_soft_newline();
2229 }
2230 p.dedent();
2231 } else {
2232 p.print_list(&self.arguments, ctx);
2233 }
2234 p.print_ascii_byte(b')');
2235 }
2236 });
2237 }
2238}
2239
2240impl GenExpr for TSAsExpression<'_> {
2241 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
2242 let wrap = precedence >= Precedence::Shift;
2243
2244 p.wrap(wrap, |p| {
2245 self.expression.print_expr(p, Precedence::Exponentiation, ctx);
2246 p.print_str(" as ");
2247 self.type_annotation.print(p, ctx);
2248 });
2249 }
2250}
2251
2252impl GenExpr for TSSatisfiesExpression<'_> {
2253 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
2254 p.print_ascii_byte(b'(');
2255 p.print_ascii_byte(b'(');
2256 self.expression.print_expr(p, precedence, Context::default());
2257 p.print_ascii_byte(b')');
2258 p.print_str(" satisfies ");
2259 self.type_annotation.print(p, ctx);
2260 p.print_ascii_byte(b')');
2261 }
2262}
2263
2264impl GenExpr for TSNonNullExpression<'_> {
2265 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
2266 p.wrap(matches!(self.expression, Expression::ParenthesizedExpression(_)), |p| {
2267 self.expression.print_expr(p, precedence, ctx);
2268 });
2269 p.print_ascii_byte(b'!');
2270 if p.options.minify {
2271 p.print_hard_space();
2272 }
2273 }
2274}
2275
2276impl GenExpr for TSInstantiationExpression<'_> {
2277 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
2278 self.expression.print_expr(p, precedence, ctx);
2279 self.type_arguments.print(p, ctx);
2280 if p.options.minify {
2281 p.print_hard_space();
2282 }
2283 }
2284}
2285
2286impl GenExpr for TSTypeAssertion<'_> {
2287 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
2288 p.wrap(precedence >= self.precedence(), |p| {
2289 p.print_str("<");
2290 if matches!(self.type_annotation, TSType::TSFunctionType(_)) {
2293 p.print_hard_space();
2294 }
2295 self.type_annotation.print(p, ctx);
2296 p.print_str(">");
2297 self.expression.print_expr(p, Precedence::Member, ctx);
2298 });
2299 }
2300}
2301
2302impl Gen for MetaProperty<'_> {
2303 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2304 p.print_space_before_identifier();
2305 p.add_source_mapping(self.span);
2306 self.meta.print(p, ctx);
2307 p.print_ascii_byte(b'.');
2308 self.property.print(p, ctx);
2309 }
2310}
2311
2312impl Gen for Class<'_> {
2313 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2314 p.add_source_mapping(self.span);
2315 let n = p.code_len();
2316 let wrap = self.is_expression() && (p.start_of_stmt == n || p.start_of_default_export == n);
2317 p.wrap(wrap, |p| {
2318 for decorator in &self.decorators {
2319 decorator.print(p, ctx);
2320 p.print_hard_space();
2321 }
2322 p.print_space_before_identifier();
2323 p.add_source_mapping(self.span);
2324 if self.declare {
2325 p.print_str("declare ");
2326 }
2327 if self.r#abstract {
2328 p.print_str("abstract ");
2329 }
2330 p.print_str("class");
2331 if let Some(id) = &self.id {
2332 p.print_hard_space();
2333 id.print(p, ctx);
2334 if let Some(type_parameters) = self.type_parameters.as_ref() {
2335 type_parameters.print(p, ctx);
2336 }
2337 }
2338 if let Some(super_class) = self.super_class.as_ref() {
2339 p.print_str(" extends ");
2340 super_class.print_expr(p, Precedence::Postfix, Context::empty());
2341 if let Some(super_type_parameters) = &self.super_type_arguments {
2342 super_type_parameters.print(p, ctx);
2343 }
2344 }
2345 if !self.implements.is_empty() {
2346 p.print_str(" implements ");
2347 p.print_list(&self.implements, ctx);
2348 }
2349 p.print_soft_space();
2350 self.body.print(p, ctx);
2351 p.needs_semicolon = false;
2352 });
2353 }
2354}
2355
2356impl Gen for ClassBody<'_> {
2357 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2358 p.print_curly_braces(self.span, self.body.is_empty(), |p| {
2359 for item in &self.body {
2360 p.print_semicolon_if_needed();
2361 p.print_leading_comments(item.span().start);
2362 p.print_indent();
2363 item.print(p, ctx);
2364 }
2365 });
2366 }
2367}
2368
2369impl Gen for ClassElement<'_> {
2370 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2371 match self {
2372 Self::StaticBlock(elem) => {
2373 elem.print(p, ctx);
2374 p.print_soft_newline();
2375 }
2376 Self::MethodDefinition(elem) => {
2377 elem.print(p, ctx);
2378 p.print_soft_newline();
2379 }
2380 Self::PropertyDefinition(elem) => {
2381 elem.print(p, ctx);
2382 p.print_semicolon_after_statement();
2383 }
2384 Self::AccessorProperty(elem) => {
2385 elem.print(p, ctx);
2386 p.print_semicolon_after_statement();
2387 }
2388 Self::TSIndexSignature(elem) => {
2389 elem.print(p, ctx);
2390 p.print_semicolon_after_statement();
2391 }
2392 }
2393 }
2394}
2395
2396impl Gen for JSXIdentifier<'_> {
2397 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
2398 p.add_source_mapping_for_name(self.span, &self.name);
2399 p.print_str(self.name.as_str());
2400 }
2401}
2402
2403impl Gen for JSXMemberExpressionObject<'_> {
2404 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2405 match self {
2406 Self::IdentifierReference(ident) => ident.print(p, ctx),
2407 Self::MemberExpression(member_expr) => member_expr.print(p, ctx),
2408 Self::ThisExpression(expr) => expr.print(p, ctx),
2409 }
2410 }
2411}
2412
2413impl Gen for JSXMemberExpression<'_> {
2414 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2415 self.object.print(p, ctx);
2416 p.print_ascii_byte(b'.');
2417 self.property.print(p, ctx);
2418 }
2419}
2420
2421impl Gen for JSXElementName<'_> {
2422 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2423 match self {
2424 Self::Identifier(identifier) => identifier.print(p, ctx),
2425 Self::IdentifierReference(identifier) => identifier.print(p, ctx),
2426 Self::NamespacedName(namespaced_name) => namespaced_name.print(p, ctx),
2427 Self::MemberExpression(member_expr) => member_expr.print(p, ctx),
2428 Self::ThisExpression(expr) => expr.print(p, ctx),
2429 }
2430 }
2431}
2432
2433impl Gen for JSXNamespacedName<'_> {
2434 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2435 self.namespace.print(p, ctx);
2436 p.print_colon();
2437 self.name.print(p, ctx);
2438 }
2439}
2440
2441impl Gen for JSXAttributeName<'_> {
2442 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2443 match self {
2444 Self::Identifier(ident) => ident.print(p, ctx),
2445 Self::NamespacedName(namespaced_name) => namespaced_name.print(p, ctx),
2446 }
2447 }
2448}
2449
2450impl Gen for JSXAttribute<'_> {
2451 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2452 self.name.print(p, ctx);
2453 if let Some(value) = &self.value {
2454 p.print_equal();
2455 value.print(p, ctx);
2456 }
2457 }
2458}
2459
2460impl Gen for JSXEmptyExpression {
2461 fn r#gen(&self, _: &mut Codegen, _ctx: Context) {}
2462}
2463
2464impl Gen for JSXExpression<'_> {
2465 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2466 match self {
2467 Self::EmptyExpression(expr) => expr.print(p, ctx),
2468 _ => p.print_expression(self.to_expression()),
2469 }
2470 }
2471}
2472
2473impl Gen for JSXExpressionContainer<'_> {
2474 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2475 p.print_ascii_byte(b'{');
2476 self.expression.print(p, ctx);
2477 p.print_ascii_byte(b'}');
2478 }
2479}
2480
2481impl Gen for JSXAttributeValue<'_> {
2482 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2483 match self {
2484 Self::Fragment(fragment) => fragment.print(p, ctx),
2485 Self::Element(el) => el.print(p, ctx),
2486 Self::StringLiteral(lit) => {
2487 let quote = if lit.value.contains('"') { b'\'' } else { b'"' };
2488 p.print_ascii_byte(quote);
2489 p.print_str(&lit.value);
2490 p.print_ascii_byte(quote);
2491 }
2492 Self::ExpressionContainer(expr_container) => expr_container.print(p, ctx),
2493 }
2494 }
2495}
2496
2497impl Gen for JSXSpreadAttribute<'_> {
2498 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
2499 p.print_str("{...");
2500 self.argument.print_expr(p, Precedence::Comma, Context::empty());
2501 p.print_ascii_byte(b'}');
2502 }
2503}
2504
2505impl Gen for JSXAttributeItem<'_> {
2506 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2507 match self {
2508 Self::Attribute(attr) => attr.print(p, ctx),
2509 Self::SpreadAttribute(spread_attr) => spread_attr.print(p, ctx),
2510 }
2511 }
2512}
2513
2514impl Gen for JSXElement<'_> {
2515 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2516 p.add_source_mapping(self.opening_element.span);
2520 p.print_ascii_byte(b'<');
2521 self.opening_element.name.print(p, ctx);
2522 for attr in &self.opening_element.attributes {
2523 match attr {
2524 JSXAttributeItem::Attribute(_) => {
2525 p.print_hard_space();
2526 }
2527 JSXAttributeItem::SpreadAttribute(_) => {
2528 p.print_soft_space();
2529 }
2530 }
2531 attr.print(p, ctx);
2532 }
2533 if self.closing_element.is_none() {
2534 p.print_soft_space();
2535 p.print_str("/");
2536 }
2537 p.print_ascii_byte(b'>');
2538
2539 for child in &self.children {
2541 child.print(p, ctx);
2542 }
2543
2544 if let Some(closing_element) = &self.closing_element {
2546 p.add_source_mapping(closing_element.span);
2547 p.print_str("</");
2548 closing_element.name.print(p, ctx);
2549 p.print_ascii_byte(b'>');
2550 }
2551 }
2552}
2553
2554impl Gen for JSXOpeningFragment {
2555 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
2556 p.add_source_mapping(self.span);
2557 p.print_str("<>");
2558 }
2559}
2560
2561impl Gen for JSXClosingFragment {
2562 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
2563 p.add_source_mapping(self.span);
2564 p.print_str("</>");
2565 }
2566}
2567
2568impl Gen for JSXText<'_> {
2569 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
2570 p.add_source_mapping(self.span);
2571 p.print_str(self.value.as_str());
2572 }
2573}
2574
2575impl Gen for JSXSpreadChild<'_> {
2576 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
2577 p.print_str("{...");
2578 p.print_expression(&self.expression);
2579 p.print_ascii_byte(b'}');
2580 }
2581}
2582
2583impl Gen for JSXChild<'_> {
2584 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2585 match self {
2586 Self::Fragment(fragment) => fragment.print(p, ctx),
2587 Self::Element(el) => el.print(p, ctx),
2588 Self::Spread(spread) => spread.print(p, ctx),
2589 Self::ExpressionContainer(expr_container) => expr_container.print(p, ctx),
2590 Self::Text(text) => text.print(p, ctx),
2591 }
2592 }
2593}
2594
2595impl Gen for JSXFragment<'_> {
2596 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2597 self.opening_fragment.print(p, ctx);
2598 for child in &self.children {
2599 child.print(p, ctx);
2600 }
2601 self.closing_fragment.print(p, ctx);
2602 }
2603}
2604
2605impl Gen for StaticBlock<'_> {
2606 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2607 p.add_source_mapping(self.span);
2608 p.print_str("static");
2609 p.print_soft_space();
2610 p.print_curly_braces(self.span, self.body.is_empty(), |p| {
2611 for stmt in &self.body {
2612 p.print_semicolon_if_needed();
2613 stmt.print(p, ctx);
2614 }
2615 });
2616 p.needs_semicolon = false;
2617 }
2618}
2619
2620impl Gen for MethodDefinition<'_> {
2621 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2622 p.add_source_mapping(self.span);
2623 for decorator in &self.decorators {
2624 decorator.print(p, ctx);
2625 p.print_soft_space();
2626 }
2627 if let Some(accessibility) = &self.accessibility {
2628 p.print_space_before_identifier();
2629 p.print_str(accessibility.as_str());
2630 p.print_soft_space();
2631 }
2632 if self.r#type == MethodDefinitionType::TSAbstractMethodDefinition {
2633 p.print_space_before_identifier();
2634 p.print_str("abstract");
2635 p.print_soft_space();
2636 }
2637 if self.r#static {
2638 p.print_space_before_identifier();
2639 p.add_source_mapping(self.span);
2640 p.print_str("static");
2641 p.print_soft_space();
2642 }
2643 match &self.kind {
2644 MethodDefinitionKind::Constructor | MethodDefinitionKind::Method => {}
2645 MethodDefinitionKind::Get => {
2646 p.print_space_before_identifier();
2647 p.add_source_mapping(self.span);
2648 p.print_str("get");
2649 p.print_soft_space();
2650 }
2651 MethodDefinitionKind::Set => {
2652 p.print_space_before_identifier();
2653 p.add_source_mapping(self.span);
2654 p.print_str("set");
2655 p.print_soft_space();
2656 }
2657 }
2658 if self.value.r#async {
2659 p.print_space_before_identifier();
2660 p.add_source_mapping(self.span);
2661 p.print_str("async");
2662 p.print_soft_space();
2663 }
2664 if self.value.generator {
2665 p.add_source_mapping(self.span);
2666 p.print_str("*");
2667 }
2668 if self.computed {
2669 p.print_ascii_byte(b'[');
2670 }
2671 self.key.print(p, ctx);
2672 if self.computed {
2673 p.print_ascii_byte(b']');
2674 }
2675 if self.optional {
2676 p.print_ascii_byte(b'?');
2677 }
2678 if let Some(type_parameters) = self.value.type_parameters.as_ref() {
2679 type_parameters.print(p, ctx);
2680 }
2681 p.print_ascii_byte(b'(');
2682 if let Some(this_param) = &self.value.this_param {
2683 this_param.print(p, ctx);
2684 if !self.value.params.is_empty() || self.value.params.rest.is_some() {
2685 p.print_str(",");
2686 p.print_soft_space();
2687 }
2688 }
2689 self.value.params.print(p, ctx);
2690 p.print_ascii_byte(b')');
2691 if let Some(return_type) = &self.value.return_type {
2692 p.print_colon();
2693 p.print_soft_space();
2694 return_type.print(p, ctx);
2695 }
2696 if let Some(body) = &self.value.body {
2697 p.print_soft_space();
2698 body.print(p, ctx);
2699 } else {
2700 p.print_semicolon();
2701 }
2702 }
2703}
2704
2705impl Gen for PropertyDefinition<'_> {
2706 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2707 p.add_source_mapping(self.span);
2708 for decorator in &self.decorators {
2709 decorator.print(p, ctx);
2710 p.print_soft_space();
2711 }
2712 if self.declare {
2713 p.print_space_before_identifier();
2714 p.print_str("declare");
2715 p.print_soft_space();
2716 }
2717 if let Some(accessibility) = self.accessibility {
2718 p.print_space_before_identifier();
2719 p.print_str(accessibility.as_str());
2720 p.print_soft_space();
2721 }
2722 if self.r#type == PropertyDefinitionType::TSAbstractPropertyDefinition {
2723 p.print_space_before_identifier();
2724 p.print_str("abstract");
2725 p.print_soft_space();
2726 }
2727 if self.r#static {
2728 p.print_space_before_identifier();
2729 p.add_source_mapping(self.span);
2730 p.print_str("static");
2731 p.print_soft_space();
2732 }
2733 if self.readonly {
2734 p.print_space_before_identifier();
2735 p.print_str("readonly");
2736 p.print_soft_space();
2737 }
2738 if self.computed {
2739 p.print_ascii_byte(b'[');
2740 }
2741 self.key.print(p, ctx);
2742 if self.computed {
2743 p.print_ascii_byte(b']');
2744 }
2745 if self.optional {
2746 p.print_str("?");
2747 }
2748 if let Some(type_annotation) = &self.type_annotation {
2749 p.print_colon();
2750 p.print_soft_space();
2751 type_annotation.print(p, ctx);
2752 }
2753 if let Some(value) = &self.value {
2754 p.print_soft_space();
2755 p.print_equal();
2756 p.print_soft_space();
2757 value.print_expr(p, Precedence::Comma, Context::empty());
2758 }
2759 }
2760}
2761
2762impl Gen for AccessorProperty<'_> {
2763 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2764 p.add_source_mapping(self.span);
2765 for decorator in &self.decorators {
2766 decorator.print(p, ctx);
2767 p.print_soft_space();
2768 }
2769 if self.r#type.is_abstract() {
2770 p.print_space_before_identifier();
2771 p.add_source_mapping(self.span);
2772 p.print_str("abstract");
2773 p.print_soft_space();
2774 }
2775 if let Some(accessibility) = self.accessibility {
2776 p.print_space_before_identifier();
2777 p.print_str(accessibility.as_str());
2778 p.print_soft_space();
2779 }
2780 if self.r#static {
2781 p.print_space_before_identifier();
2782 p.add_source_mapping(self.span);
2783 p.print_str("static");
2784 p.print_soft_space();
2785 }
2786 if self.r#override {
2787 p.print_space_before_identifier();
2788 p.print_str("override");
2789 p.print_soft_space();
2790 }
2791 p.print_space_before_identifier();
2792 p.print_str("accessor");
2793 if self.computed {
2794 p.print_soft_space();
2795 p.print_ascii_byte(b'[');
2796 } else {
2797 p.print_hard_space();
2798 }
2799 self.key.print(p, ctx);
2800 if self.computed {
2801 p.print_ascii_byte(b']');
2802 }
2803 if let Some(type_annotation) = &self.type_annotation {
2804 p.print_colon();
2805 p.print_soft_space();
2806 type_annotation.print(p, ctx);
2807 }
2808 if let Some(value) = &self.value {
2809 p.print_soft_space();
2810 p.print_equal();
2811 p.print_soft_space();
2812 value.print_expr(p, Precedence::Comma, Context::empty());
2813 }
2814 }
2815}
2816
2817impl Gen for PrivateIdentifier<'_> {
2818 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
2819 p.add_source_mapping_for_name(self.span, &self.name);
2820 p.print_ascii_byte(b'#');
2821 p.print_str(self.name.as_str());
2822 }
2823}
2824
2825impl Gen for BindingPattern<'_> {
2826 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2827 self.kind.print(p, ctx);
2828 if self.optional {
2829 p.print_str("?");
2830 }
2831 if let Some(type_annotation) = &self.type_annotation {
2832 p.print_colon();
2833 p.print_soft_space();
2834 type_annotation.print(p, ctx);
2835 }
2836 }
2837}
2838
2839impl Gen for BindingPatternKind<'_> {
2840 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2841 match self {
2842 BindingPatternKind::BindingIdentifier(ident) => ident.print(p, ctx),
2843 BindingPatternKind::ObjectPattern(pattern) => pattern.print(p, ctx),
2844 BindingPatternKind::ArrayPattern(pattern) => pattern.print(p, ctx),
2845 BindingPatternKind::AssignmentPattern(pattern) => pattern.print(p, ctx),
2846 }
2847 }
2848}
2849
2850impl Gen for ObjectPattern<'_> {
2851 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2852 p.add_source_mapping(self.span);
2853 p.print_ascii_byte(b'{');
2854 if !self.is_empty() {
2855 p.print_soft_space();
2856 }
2857 p.print_list(&self.properties, ctx);
2858 if let Some(rest) = &self.rest {
2859 if !self.properties.is_empty() {
2860 p.print_comma();
2861 }
2862 rest.print(p, ctx);
2863 }
2864 if !self.is_empty() {
2865 p.print_soft_space();
2866 }
2867 p.print_ascii_byte(b'}');
2868 p.add_source_mapping_end(self.span);
2869 }
2870}
2871
2872impl Gen for BindingProperty<'_> {
2873 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2874 p.add_source_mapping(self.span);
2875 if self.computed {
2876 p.print_ascii_byte(b'[');
2877 }
2878
2879 let mut shorthand = false;
2880 if let PropertyKey::StaticIdentifier(key) = &self.key {
2881 match &self.value.kind {
2882 BindingPatternKind::BindingIdentifier(ident)
2883 if key.name == p.get_binding_identifier_name(ident) =>
2884 {
2885 shorthand = true;
2886 }
2887 BindingPatternKind::AssignmentPattern(assignment_pattern) => {
2888 if let BindingPatternKind::BindingIdentifier(ident) =
2889 &assignment_pattern.left.kind
2890 {
2891 if key.name == p.get_binding_identifier_name(ident) {
2892 shorthand = true;
2893 }
2894 }
2895 }
2896 _ => {}
2897 }
2898 }
2899
2900 if !shorthand {
2901 self.key.print(p, ctx);
2902 }
2903 if self.computed {
2904 p.print_ascii_byte(b']');
2905 }
2906 if !shorthand {
2907 p.print_colon();
2908 p.print_soft_space();
2909 }
2910 self.value.print(p, ctx);
2911 }
2912}
2913
2914impl Gen for BindingRestElement<'_> {
2915 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2916 p.add_source_mapping(self.span);
2917 p.print_ellipsis();
2918 self.argument.print(p, ctx);
2919 }
2920}
2921
2922impl Gen for ArrayPattern<'_> {
2923 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2924 p.add_source_mapping(self.span);
2925 p.print_ascii_byte(b'[');
2926 for (index, item) in self.elements.iter().enumerate() {
2927 if index != 0 {
2928 p.print_comma();
2929 p.print_soft_space();
2930 }
2931 if let Some(item) = item {
2932 item.print(p, ctx);
2933 }
2934 if index == self.elements.len() - 1 && (item.is_none() || self.rest.is_some()) {
2935 p.print_comma();
2936 }
2937 }
2938 if let Some(rest) = &self.rest {
2939 p.print_soft_space();
2940 rest.print(p, ctx);
2941 }
2942 p.print_ascii_byte(b']');
2943 p.add_source_mapping_end(self.span);
2944 }
2945}
2946
2947impl Gen for AssignmentPattern<'_> {
2948 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2949 self.left.print(p, ctx);
2950 p.print_soft_space();
2951 p.print_equal();
2952 p.print_soft_space();
2953 self.right.print_expr(p, Precedence::Comma, Context::empty());
2954 }
2955}
2956
2957impl Gen for Decorator<'_> {
2958 fn r#gen(&self, p: &mut Codegen, _ctx: Context) {
2959 fn need_wrap(expr: &Expression) -> bool {
2960 match expr {
2961 Expression::Identifier(_)
2965 | Expression::StaticMemberExpression(_)
2966 | Expression::PrivateFieldExpression(_) => false,
2967 Expression::CallExpression(call_expr) => need_wrap(&call_expr.callee),
2968 _ => true,
2972 }
2973 }
2974
2975 p.add_source_mapping(self.span);
2976 p.print_ascii_byte(b'@');
2977 let wrap = need_wrap(&self.expression);
2978 p.wrap(wrap, |p| {
2979 self.expression.print_expr(p, Precedence::Lowest, Context::empty());
2980 });
2981 }
2982}
2983
2984impl Gen for TSClassImplements<'_> {
2985 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2986 self.expression.print(p, ctx);
2987 if let Some(type_parameters) = self.type_arguments.as_ref() {
2988 type_parameters.print(p, ctx);
2989 }
2990 }
2991}
2992
2993impl Gen for TSTypeParameterDeclaration<'_> {
2994 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
2995 let is_multi_line = self.params.len() >= 2;
2996 p.print_ascii_byte(b'<');
2997 if is_multi_line {
2998 p.indent();
2999 }
3000 for (index, item) in self.params.iter().enumerate() {
3001 if index != 0 {
3002 p.print_comma();
3003 }
3004 if is_multi_line {
3005 p.print_soft_newline();
3006 p.print_indent();
3007 } else if index != 0 {
3008 p.print_soft_space();
3009 }
3010 item.print(p, ctx);
3011 }
3012 if is_multi_line {
3013 p.print_soft_newline();
3014 p.dedent();
3015 p.print_indent();
3016 } else if p.is_jsx {
3017 p.print_str(",");
3020 }
3021 p.print_ascii_byte(b'>');
3022 }
3023}
3024
3025impl Gen for TSTypeAnnotation<'_> {
3026 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3027 self.type_annotation.print(p, ctx);
3028 }
3029}
3030
3031impl Gen for TSType<'_> {
3032 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3033 let ctx = ctx.with_typescript();
3034 match self {
3035 Self::TSFunctionType(ty) => ty.print(p, ctx),
3036 Self::TSConstructorType(ty) => ty.print(p, ctx),
3037 Self::TSArrayType(ty) => ty.print(p, ctx),
3038 Self::TSTupleType(ty) => ty.print(p, ctx),
3039 Self::TSUnionType(ty) => ty.print(p, ctx),
3040 Self::TSParenthesizedType(ty) => ty.print(p, ctx),
3041 Self::TSIntersectionType(ty) => ty.print(p, ctx),
3042 Self::TSConditionalType(ty) => ty.print(p, ctx),
3043 Self::TSInferType(ty) => ty.print(p, ctx),
3044 Self::TSIndexedAccessType(ty) => ty.print(p, ctx),
3045 Self::TSMappedType(ty) => ty.print(p, ctx),
3046 Self::TSNamedTupleMember(ty) => ty.print(p, ctx),
3047 Self::TSLiteralType(ty) => ty.literal.print(p, ctx),
3048 Self::TSImportType(ty) => ty.print(p, ctx),
3049 Self::TSAnyKeyword(_) => p.print_str("any"),
3050 Self::TSBigIntKeyword(_) => p.print_str("bigint"),
3051 Self::TSBooleanKeyword(_) => p.print_str("boolean"),
3052 Self::TSIntrinsicKeyword(_) => p.print_str("intrinsic"),
3053 Self::TSNeverKeyword(_) => p.print_str("never"),
3054 Self::TSNullKeyword(_) => p.print_str("null"),
3055 Self::TSNumberKeyword(_) => p.print_str("number"),
3056 Self::TSObjectKeyword(_) => p.print_str("object"),
3057 Self::TSStringKeyword(_) => p.print_str("string"),
3058 Self::TSSymbolKeyword(_) => p.print_str("symbol"),
3059 Self::TSThisType(_) => p.print_str("this"),
3060 Self::TSUndefinedKeyword(_) => p.print_str("undefined"),
3061 Self::TSUnknownKeyword(_) => p.print_str("unknown"),
3062 Self::TSVoidKeyword(_) => p.print_str("void"),
3063 Self::TSTemplateLiteralType(ty) => ty.print(p, ctx),
3064 Self::TSTypeLiteral(ty) => ty.print(p, ctx),
3065 Self::TSTypeOperatorType(ty) => ty.print(p, ctx),
3066 Self::TSTypePredicate(ty) => ty.print(p, ctx),
3067 Self::TSTypeQuery(ty) => ty.print(p, ctx),
3068 Self::TSTypeReference(ty) => ty.print(p, ctx),
3069 Self::JSDocNullableType(ty) => ty.print(p, ctx),
3070 Self::JSDocNonNullableType(ty) => ty.print(p, ctx),
3071 Self::JSDocUnknownType(_ty) => p.print_str("unknown"),
3072 }
3073 }
3074}
3075
3076impl Gen for TSArrayType<'_> {
3077 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3078 self.element_type.print(p, ctx);
3079 p.print_str("[]");
3080 }
3081}
3082
3083impl Gen for TSTupleType<'_> {
3084 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3085 p.print_str("[");
3086 p.print_list(&self.element_types, ctx);
3087 p.print_str("]");
3088 }
3089}
3090
3091impl Gen for TSUnionType<'_> {
3092 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3093 let Some((first, rest)) = self.types.split_first() else {
3094 return;
3095 };
3096 first.print(p, ctx);
3097 for item in rest {
3098 p.print_soft_space();
3099 p.print_str("|");
3100 p.print_soft_space();
3101 item.print(p, ctx);
3102 }
3103 }
3104}
3105
3106impl Gen for TSParenthesizedType<'_> {
3107 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3108 p.print_ascii_byte(b'(');
3109 self.type_annotation.print(p, ctx);
3110 p.print_ascii_byte(b')');
3111 }
3112}
3113
3114impl Gen for TSIntersectionType<'_> {
3115 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3116 let Some((first, rest)) = self.types.split_first() else {
3117 return;
3118 };
3119 first.print(p, ctx);
3120 for item in rest {
3121 p.print_soft_space();
3122 p.print_str("&");
3123 p.print_soft_space();
3124 item.print(p, ctx);
3125 }
3126 }
3127}
3128
3129impl Gen for TSConditionalType<'_> {
3130 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3131 self.check_type.print(p, ctx);
3132 p.print_str(" extends ");
3133 self.extends_type.print(p, ctx);
3134 p.print_str(" ? ");
3135 self.true_type.print(p, ctx);
3136 p.print_str(" : ");
3137 self.false_type.print(p, ctx);
3138 }
3139}
3140
3141impl Gen for TSInferType<'_> {
3142 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3143 p.print_str("infer ");
3144 self.type_parameter.print(p, ctx);
3145 }
3146}
3147
3148impl Gen for TSIndexedAccessType<'_> {
3149 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3150 self.object_type.print(p, ctx);
3151 p.print_str("[");
3152 self.index_type.print(p, ctx);
3153 p.print_str("]");
3154 }
3155}
3156
3157impl Gen for TSMappedType<'_> {
3158 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3159 p.print_str("{");
3160 p.print_soft_space();
3161 match self.readonly {
3162 TSMappedTypeModifierOperator::True => {
3163 p.print_str("readonly ");
3164 }
3165 TSMappedTypeModifierOperator::Plus => {
3166 p.print_str("+readonly ");
3167 }
3168 TSMappedTypeModifierOperator::Minus => {
3169 p.print_str("-readonly ");
3170 }
3171 TSMappedTypeModifierOperator::None => {}
3172 }
3173 p.print_str("[");
3174 self.type_parameter.name.print(p, ctx);
3175 if let Some(constraint) = &self.type_parameter.constraint {
3176 p.print_str(" in ");
3177 constraint.print(p, ctx);
3178 }
3179 if let Some(default) = &self.type_parameter.default {
3180 p.print_str(" = ");
3181 default.print(p, ctx);
3182 }
3183 if let Some(name_type) = &self.name_type {
3184 p.print_str(" as ");
3185 name_type.print(p, ctx);
3186 }
3187 p.print_str("]");
3188 match self.optional {
3189 TSMappedTypeModifierOperator::True => {
3190 p.print_str("?");
3191 }
3192 TSMappedTypeModifierOperator::Plus => {
3193 p.print_str("+?");
3194 }
3195 TSMappedTypeModifierOperator::Minus => {
3196 p.print_str("-?");
3197 }
3198 TSMappedTypeModifierOperator::None => {}
3199 }
3200 p.print_soft_space();
3201 if let Some(type_annotation) = &self.type_annotation {
3202 p.print_str(":");
3203 p.print_soft_space();
3204 type_annotation.print(p, ctx);
3205 }
3206 p.print_soft_space();
3207 p.print_str("}");
3208 }
3209}
3210
3211impl Gen for TSQualifiedName<'_> {
3212 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3213 self.left.print(p, ctx);
3214 p.print_str(".");
3215 self.right.print(p, ctx);
3216 }
3217}
3218
3219impl Gen for TSTypeOperator<'_> {
3220 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3221 p.print_str(self.operator.to_str());
3222 p.print_hard_space();
3223 self.type_annotation.print(p, ctx);
3224 }
3225}
3226
3227impl Gen for TSTypePredicate<'_> {
3228 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3229 if self.asserts {
3230 p.print_str("asserts ");
3231 }
3232 match &self.parameter_name {
3233 TSTypePredicateName::Identifier(ident) => {
3234 ident.print(p, ctx);
3235 }
3236 TSTypePredicateName::This(_ident) => {
3237 p.print_str("this");
3238 }
3239 }
3240 if let Some(type_annotation) = &self.type_annotation {
3241 p.print_str(" is ");
3242 type_annotation.print(p, ctx);
3243 }
3244 }
3245}
3246
3247impl Gen for TSTypeReference<'_> {
3248 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3249 self.type_name.print(p, ctx);
3250 if let Some(type_parameters) = &self.type_arguments {
3251 type_parameters.print(p, ctx);
3252 }
3253 }
3254}
3255
3256impl Gen for JSDocNullableType<'_> {
3257 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3258 if self.postfix {
3259 self.type_annotation.print(p, ctx);
3260 p.print_str("?");
3261 } else {
3262 p.print_str("?");
3263 self.type_annotation.print(p, ctx);
3264 }
3265 }
3266}
3267
3268impl Gen for JSDocNonNullableType<'_> {
3269 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3270 if self.postfix {
3271 self.type_annotation.print(p, ctx);
3272 p.print_str("!");
3273 } else {
3274 p.print_str("!");
3275 self.type_annotation.print(p, ctx);
3276 }
3277 }
3278}
3279
3280impl Gen for TSTemplateLiteralType<'_> {
3281 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3282 p.print_str("`");
3283 for (index, item) in self.quasis.iter().enumerate() {
3284 if index != 0 {
3285 if let Some(types) = self.types.get(index - 1) {
3286 p.print_str("${");
3287 types.print(p, ctx);
3288 p.print_str("}");
3289 }
3290 }
3291 p.print_str(item.value.raw.as_str());
3292 }
3293 p.print_str("`");
3294 }
3295}
3296
3297impl Gen for TSTypeLiteral<'_> {
3298 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3299 p.print_curly_braces(self.span, self.members.is_empty(), |p| {
3300 for item in &self.members {
3301 p.print_leading_comments(item.span().start);
3302 p.print_indent();
3303 item.print(p, ctx);
3304 if p.options.minify {
3305 p.print_semicolon();
3306 }
3307 p.print_soft_newline();
3308 }
3309 });
3310 }
3311}
3312
3313impl Gen for TSTypeName<'_> {
3314 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3315 match self {
3316 Self::IdentifierReference(ident) => {
3317 ident.print(p, ctx);
3318 }
3319 Self::QualifiedName(decl) => {
3320 decl.left.print(p, ctx);
3321 p.print_str(".");
3322 decl.right.print(p, ctx);
3323 }
3324 }
3325 }
3326}
3327
3328impl Gen for TSLiteral<'_> {
3329 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3330 match self {
3331 Self::BooleanLiteral(decl) => decl.print(p, ctx),
3332 Self::NumericLiteral(decl) => decl.print_expr(p, Precedence::Lowest, ctx),
3333 Self::BigIntLiteral(decl) => decl.print_expr(p, Precedence::Lowest, ctx),
3334 Self::StringLiteral(decl) => decl.print(p, ctx),
3335 Self::TemplateLiteral(decl) => decl.print(p, ctx),
3336 Self::UnaryExpression(decl) => decl.print_expr(p, Precedence::Comma, ctx),
3337 }
3338 }
3339}
3340
3341impl Gen for TSTypeParameter<'_> {
3342 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3343 if self.r#const {
3344 p.print_str("const ");
3345 }
3346 self.name.print(p, ctx);
3347 if let Some(constraint) = &self.constraint {
3348 p.print_str(" extends ");
3349 constraint.print(p, ctx);
3350 }
3351 if let Some(default) = &self.default {
3352 p.print_str(" = ");
3353 default.print(p, ctx);
3354 }
3355 }
3356}
3357
3358impl Gen for TSFunctionType<'_> {
3359 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3360 if let Some(type_parameters) = &self.type_parameters {
3361 type_parameters.print(p, ctx);
3362 }
3363 p.print_str("(");
3364 if let Some(this_param) = &self.this_param {
3365 this_param.print(p, ctx);
3366 if !self.params.is_empty() || self.params.rest.is_some() {
3367 p.print_str(",");
3368 p.print_soft_space();
3369 }
3370 }
3371 self.params.print(p, ctx);
3372 p.print_str(")");
3373 p.print_soft_space();
3374 p.print_str("=>");
3375 p.print_soft_space();
3376 self.return_type.print(p, ctx);
3377 }
3378}
3379
3380impl Gen for TSThisParameter<'_> {
3381 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3382 p.print_str("this");
3383 if let Some(type_annotation) = &self.type_annotation {
3384 p.print_str(": ");
3385 type_annotation.print(p, ctx);
3386 }
3387 }
3388}
3389
3390impl Gen for TSSignature<'_> {
3391 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3392 match self {
3393 Self::TSIndexSignature(signature) => signature.print(p, ctx),
3394 Self::TSPropertySignature(signature) => signature.r#gen(p, ctx),
3395 Self::TSCallSignatureDeclaration(signature) => {
3396 if let Some(type_parameters) = signature.type_parameters.as_ref() {
3397 type_parameters.print(p, ctx);
3398 }
3399 p.print_str("(");
3400 if let Some(this_param) = &signature.this_param {
3401 this_param.print(p, ctx);
3402 if !signature.params.is_empty() || signature.params.rest.is_some() {
3403 p.print_str(",");
3404 p.print_soft_space();
3405 }
3406 }
3407 signature.params.print(p, ctx);
3408 p.print_str(")");
3409 if let Some(return_type) = &signature.return_type {
3410 p.print_colon();
3411 p.print_soft_space();
3412 return_type.print(p, ctx);
3413 }
3414 }
3415 Self::TSConstructSignatureDeclaration(signature) => {
3416 p.print_str("new ");
3417 if let Some(type_parameters) = signature.type_parameters.as_ref() {
3418 type_parameters.print(p, ctx);
3419 }
3420 p.print_str("(");
3421 signature.params.print(p, ctx);
3422 p.print_str(")");
3423 if let Some(return_type) = &signature.return_type {
3424 p.print_colon();
3425 p.print_soft_space();
3426 return_type.print(p, ctx);
3427 }
3428 }
3429 Self::TSMethodSignature(signature) => {
3430 match signature.kind {
3431 TSMethodSignatureKind::Method => {}
3432 TSMethodSignatureKind::Get => p.print_str("get "),
3433 TSMethodSignatureKind::Set => p.print_str("set "),
3434 }
3435 if signature.computed {
3436 p.print_ascii_byte(b'[');
3437 signature.key.print(p, ctx);
3438 p.print_ascii_byte(b']');
3439 } else {
3440 match &signature.key {
3441 PropertyKey::StaticIdentifier(key) => {
3442 key.print(p, ctx);
3443 }
3444 PropertyKey::PrivateIdentifier(key) => {
3445 p.print_str(key.name.as_str());
3446 }
3447 PropertyKey::StringLiteral(key) => {
3448 p.print_string_literal(key, false);
3449 }
3450 key => {
3451 key.to_expression().print_expr(p, Precedence::Comma, ctx);
3452 }
3453 }
3454 }
3455 if signature.optional {
3456 p.print_str("?");
3457 }
3458 if let Some(type_parameters) = &signature.type_parameters {
3459 type_parameters.print(p, ctx);
3460 }
3461 p.print_str("(");
3462 if let Some(this_param) = &signature.this_param {
3463 this_param.print(p, ctx);
3464 if !signature.params.is_empty() || signature.params.rest.is_some() {
3465 p.print_str(",");
3466 p.print_soft_space();
3467 }
3468 }
3469 signature.params.print(p, ctx);
3470 p.print_str(")");
3471 if let Some(return_type) = &signature.return_type {
3472 p.print_colon();
3473 p.print_soft_space();
3474 return_type.print(p, ctx);
3475 }
3476 }
3477 }
3478 }
3479}
3480
3481impl Gen for TSPropertySignature<'_> {
3482 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3483 if self.readonly {
3484 p.print_str("readonly ");
3485 }
3486 if self.computed {
3487 p.print_ascii_byte(b'[');
3488 self.key.print(p, ctx);
3489 p.print_ascii_byte(b']');
3490 } else {
3491 match &self.key {
3492 PropertyKey::StaticIdentifier(key) => {
3493 key.print(p, ctx);
3494 }
3495 PropertyKey::PrivateIdentifier(key) => {
3496 p.print_str(key.name.as_str());
3497 }
3498 PropertyKey::StringLiteral(key) => {
3499 p.print_string_literal(key, false);
3500 }
3501 key => {
3502 key.to_expression().print_expr(p, Precedence::Comma, ctx);
3503 }
3504 }
3505 }
3506 if self.optional {
3507 p.print_str("?");
3508 }
3509 if let Some(type_annotation) = &self.type_annotation {
3510 p.print_colon();
3511 p.print_soft_space();
3512 type_annotation.print(p, ctx);
3513 }
3514 }
3515}
3516
3517impl Gen for TSTypeQuery<'_> {
3518 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3519 p.print_str("typeof ");
3520 self.expr_name.print(p, ctx);
3521 if let Some(type_params) = &self.type_arguments {
3522 type_params.print(p, ctx);
3523 }
3524 }
3525}
3526
3527impl Gen for TSTypeQueryExprName<'_> {
3528 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3529 match self {
3530 match_ts_type_name!(Self) => self.to_ts_type_name().print(p, ctx),
3531 Self::TSImportType(decl) => decl.print(p, ctx),
3532 }
3533 }
3534}
3535
3536impl Gen for TSImportType<'_> {
3537 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3538 p.print_str("import(");
3539 self.argument.print(p, ctx);
3540 if let Some(options) = &self.options {
3541 p.print_str(", ");
3542 options.print_expr(p, Precedence::Lowest, ctx);
3543 }
3544 p.print_str(")");
3545 if let Some(qualifier) = &self.qualifier {
3546 p.print_ascii_byte(b'.');
3547 qualifier.print(p, ctx);
3548 }
3549 if let Some(type_parameters) = &self.type_arguments {
3550 type_parameters.print(p, ctx);
3551 }
3552 }
3553}
3554
3555impl Gen for TSTypeParameterInstantiation<'_> {
3556 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3557 p.print_str("<");
3558 p.print_list(&self.params, ctx);
3559 p.print_str(">");
3560 }
3561}
3562
3563impl Gen for TSIndexSignature<'_> {
3564 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3565 if self.readonly {
3566 p.print_str("readonly ");
3567 }
3568 p.print_str("[");
3569 for (index, parameter) in self.parameters.iter().enumerate() {
3570 if index != 0 {
3571 p.print_str(" | ");
3572 }
3573 p.print_str(parameter.name.as_str());
3574 p.print_colon();
3575 p.print_soft_space();
3576 parameter.type_annotation.print(p, ctx);
3577 }
3578 p.print_str("]");
3579 p.print_colon();
3580 p.print_soft_space();
3581 self.type_annotation.print(p, ctx);
3582 }
3583}
3584
3585impl Gen for TSTupleElement<'_> {
3586 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3587 match self {
3588 match_ts_type!(TSTupleElement) => self.to_ts_type().print(p, ctx),
3589 TSTupleElement::TSOptionalType(ts_type) => {
3590 ts_type.type_annotation.print(p, ctx);
3591 p.print_str("?");
3592 }
3593 TSTupleElement::TSRestType(ts_type) => {
3594 p.print_str("...");
3595 ts_type.type_annotation.print(p, ctx);
3596 }
3597 }
3598 }
3599}
3600
3601impl Gen for TSNamedTupleMember<'_> {
3602 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3603 self.label.print(p, ctx);
3604 if self.optional {
3605 p.print_str("?");
3606 }
3607 p.print_str(":");
3608 p.print_soft_space();
3609 self.element_type.print(p, ctx);
3610 }
3611}
3612
3613impl Gen for TSModuleDeclaration<'_> {
3614 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3615 if self.declare {
3616 p.print_str("declare ");
3617 }
3618 p.print_str(self.kind.as_str());
3619 if !self.kind.is_global() {
3621 p.print_space_before_identifier();
3622 self.id.print(p, ctx);
3623 }
3624
3625 if let Some(body) = &self.body {
3626 let mut body = body;
3627 loop {
3628 match body {
3629 TSModuleDeclarationBody::TSModuleDeclaration(b) => {
3630 p.print_ascii_byte(b'.');
3631 b.id.print(p, ctx);
3632 if let Some(b) = &b.body {
3633 body = b;
3634 } else {
3635 break;
3636 }
3637 }
3638 TSModuleDeclarationBody::TSModuleBlock(body) => {
3639 p.print_soft_space();
3640 body.print(p, ctx);
3641 break;
3642 }
3643 }
3644 }
3645 } else {
3646 p.print_semicolon();
3647 }
3648 p.needs_semicolon = false;
3649 }
3650}
3651
3652impl Gen for TSModuleDeclarationName<'_> {
3653 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3654 match self {
3655 Self::Identifier(ident) => ident.print(p, ctx),
3656 Self::StringLiteral(s) => p.print_string_literal(s, false),
3657 }
3658 }
3659}
3660
3661impl Gen for TSModuleBlock<'_> {
3662 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3663 let is_empty = self.directives.is_empty() && self.body.is_empty();
3664 p.print_curly_braces(self.span, is_empty, |p| {
3665 for directive in &self.directives {
3666 directive.print(p, ctx);
3667 }
3668 for stmt in &self.body {
3669 p.print_semicolon_if_needed();
3670 stmt.print(p, ctx);
3671 }
3672 });
3673 p.needs_semicolon = false;
3674 }
3675}
3676
3677impl Gen for TSTypeAliasDeclaration<'_> {
3678 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3679 if self.declare {
3680 p.print_str("declare ");
3681 }
3682 p.print_str("type");
3683 p.print_space_before_identifier();
3684 self.id.print(p, ctx);
3685 if let Some(type_parameters) = &self.type_parameters {
3686 type_parameters.print(p, ctx);
3687 }
3688 p.print_soft_space();
3689 p.print_str("=");
3690 p.print_soft_space();
3691 self.type_annotation.print(p, ctx);
3692 }
3693}
3694
3695impl Gen for TSInterfaceDeclaration<'_> {
3696 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3697 p.print_str("interface");
3698 p.print_hard_space();
3699 self.id.print(p, ctx);
3700 if let Some(type_parameters) = &self.type_parameters {
3701 type_parameters.print(p, ctx);
3702 }
3703 if let Some(extends) = &self.extends {
3704 if !extends.is_empty() {
3705 p.print_str(" extends ");
3706 p.print_list(extends, ctx);
3707 }
3708 }
3709 p.print_soft_space();
3710 p.print_curly_braces(self.body.span, self.body.body.is_empty(), |p| {
3711 for item in &self.body.body {
3712 p.print_leading_comments(item.span().start);
3713 p.print_indent();
3714 item.print(p, ctx);
3715 p.print_semicolon();
3716 p.print_soft_newline();
3717 }
3718 });
3719 }
3720}
3721
3722impl Gen for TSInterfaceHeritage<'_> {
3723 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3724 self.expression.print_expr(p, Precedence::Call, ctx);
3725 if let Some(type_parameters) = &self.type_arguments {
3726 type_parameters.print(p, ctx);
3727 }
3728 }
3729}
3730
3731impl Gen for TSEnumDeclaration<'_> {
3732 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3733 p.print_indent();
3734 if self.declare {
3735 p.print_str("declare ");
3736 }
3737 if self.r#const {
3738 p.print_str("const ");
3739 }
3740 p.print_space_before_identifier();
3741 p.print_str("enum ");
3742 self.id.print(p, ctx);
3743 p.print_space_before_identifier();
3744 self.body.print(p, ctx);
3745 }
3746}
3747
3748impl Gen for TSEnumBody<'_> {
3749 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3750 p.print_curly_braces(self.span, self.members.is_empty(), |p| {
3751 for (index, member) in self.members.iter().enumerate() {
3752 p.print_leading_comments(member.span().start);
3753 p.print_indent();
3754 member.print(p, ctx);
3755 if index != self.members.len() - 1 {
3756 p.print_comma();
3757 }
3758 p.print_soft_newline();
3759 }
3760 });
3761 }
3762}
3763
3764impl Gen for TSEnumMember<'_> {
3765 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3766 match &self.id {
3767 TSEnumMemberName::Identifier(decl) => decl.print(p, ctx),
3768 TSEnumMemberName::String(decl) => p.print_string_literal(decl, false),
3769 TSEnumMemberName::ComputedString(decl) => {
3770 p.print_ascii_byte(b'[');
3771 p.print_string_literal(decl, false);
3772 p.print_ascii_byte(b']');
3773 }
3774 TSEnumMemberName::ComputedTemplateString(decl) => {
3775 let quasi = decl.quasis.first().unwrap();
3776 p.add_source_mapping(quasi.span);
3777
3778 p.print_str("[`");
3779 p.print_str(quasi.value.raw.as_str());
3780 p.print_str("`]");
3781 }
3782 }
3783
3784 if let Some(init) = &self.initializer {
3785 p.print_soft_space();
3786 p.print_equal();
3787 p.print_soft_space();
3788 init.print_expr(p, Precedence::Lowest, ctx);
3789 }
3790 }
3791}
3792
3793impl Gen for TSConstructorType<'_> {
3794 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3795 if self.r#abstract {
3796 p.print_str("abstract ");
3797 }
3798 p.print_str("new ");
3799 if let Some(type_parameters) = &self.type_parameters {
3800 type_parameters.print(p, ctx);
3801 }
3802 p.print_str("(");
3803 self.params.print(p, ctx);
3804 p.print_str(")");
3805 p.print_soft_space();
3806 p.print_str("=>");
3807 p.print_soft_space();
3808 self.return_type.print(p, ctx);
3809 }
3810}
3811
3812impl Gen for TSImportEqualsDeclaration<'_> {
3813 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3814 p.print_str("import ");
3815 self.id.print(p, ctx);
3816 p.print_str(" = ");
3817 self.module_reference.print(p, ctx);
3818 }
3819}
3820
3821impl Gen for TSModuleReference<'_> {
3822 fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3823 match self {
3824 Self::ExternalModuleReference(decl) => {
3825 p.print_str("require(");
3826 p.print_string_literal(&decl.expression, false);
3827 p.print_str(")");
3828 }
3829 match_ts_type_name!(Self) => self.to_ts_type_name().print(p, ctx),
3830 }
3831 }
3832}
3833
3834impl GenExpr for V8IntrinsicExpression<'_> {
3835 fn gen_expr(&self, p: &mut Codegen, precedence: Precedence, ctx: Context) {
3836 let is_statement = p.start_of_stmt == p.code_len();
3837 let is_export_default = p.start_of_default_export == p.code_len();
3838 let mut wrap = precedence >= Precedence::New || ctx.intersects(Context::FORBID_CALL);
3839 if precedence >= Precedence::Postfix {
3840 wrap = true;
3841 }
3842
3843 p.wrap(wrap, |p| {
3844 if is_export_default {
3845 p.start_of_default_export = p.code_len();
3846 } else if is_statement {
3847 p.start_of_stmt = p.code_len();
3848 }
3849 p.add_source_mapping(self.span);
3850 p.print_ascii_byte(b'%');
3851 self.name.print(p, Context::empty());
3852 p.print_ascii_byte(b'(');
3853 let (has_comment, has_comment_before_right_paren) =
3854 p.contains_comment_in_call_like_expression(self.span, self.arguments.as_slice());
3855 if has_comment {
3856 p.indent();
3857 p.print_list_with_comments(self.arguments.as_slice(), ctx);
3858 if !has_comment_before_right_paren || !p.print_expr_comments(self.span.end - 1) {
3860 p.print_soft_newline();
3861 }
3862 p.dedent();
3863 } else {
3864 p.print_list(&self.arguments, ctx);
3865 }
3866 p.print_ascii_byte(b')');
3867 p.add_source_mapping_end(self.span);
3868 });
3869 }
3870}