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