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