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