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