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