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