1use crate::context::emit::EmitContext;
26use crate::context::transform::{IdentifierId, TransformContext, TransformDirective};
27use crate::output::source_writer::{SourcePosition, SourceWriter, source_position_from_offset};
28use crate::transforms::{ClassES5Emitter, EnumES5Emitter, NamespaceES5Emitter};
29use rustc_hash::{FxHashMap, FxHashSet};
30use std::collections::VecDeque;
31use std::sync::Arc;
32use tracing::{debug, warn};
33use tsz_parser::parser::NodeIndex;
34use tsz_parser::parser::node::{Node, NodeArena};
35use tsz_parser::parser::syntax_kind_ext;
36use tsz_scanner::SyntaxKind;
37
38mod binding_patterns;
39mod comment_helpers;
40mod comments;
41mod declarations;
42mod declarations_class;
43mod declarations_class_members;
44mod declarations_namespace;
45mod es5;
46mod expressions;
47mod expressions_literals;
48mod functions;
49mod helpers;
50mod jsx;
51mod literals;
52mod module_emission;
53mod module_emission_exports;
54mod module_emission_imports;
55mod module_wrapper;
56mod source_file;
57mod special_expressions;
58mod statements;
59mod template_literals;
60mod transform_dispatch;
61pub mod type_printer;
62mod types;
63
64pub use comments::{
65 CommentKind, CommentRange, get_leading_comment_ranges, get_trailing_comment_ranges,
66};
67
68pub use tsz_common::common::{ModuleKind, NewLineKind, ScriptTarget};
70
71#[derive(Clone, Debug)]
77pub struct PrinterOptions {
78 pub remove_comments: bool,
80 pub target: ScriptTarget,
82 pub single_quote: bool,
84 pub omit_trailing_semicolon: bool,
86 pub no_emit_helpers: bool,
88 pub module: ModuleKind,
90 pub new_line: NewLineKind,
92 pub downlevel_iteration: bool,
94 pub type_only_nodes: Arc<FxHashSet<NodeIndex>>,
96 pub always_strict: bool,
98 pub use_define_for_class_fields: bool,
100 pub legacy_decorators: bool,
102 pub es_module_interop: bool,
104 pub module_detection_force: bool,
106}
107
108impl Default for PrinterOptions {
109 fn default() -> Self {
110 Self {
111 remove_comments: false,
112 target: ScriptTarget::ESNext,
113 single_quote: false,
114 omit_trailing_semicolon: false,
115 no_emit_helpers: false,
116 module: ModuleKind::None,
117 new_line: NewLineKind::LineFeed,
118 downlevel_iteration: false,
119 type_only_nodes: Arc::new(FxHashSet::default()),
120 always_strict: false,
121 use_define_for_class_fields: false,
122 legacy_decorators: false,
123 es_module_interop: false,
124 module_detection_force: false,
125 }
126 }
127}
128
129#[derive(Default)]
130struct ParamTransformPlan {
131 params: Vec<ParamTransform>,
132 rest: Option<RestParamTransform>,
133}
134
135#[derive(Default)]
136struct TempScopeState {
137 temp_var_counter: u32,
138 generated_temp_names: FxHashSet<String>,
139 first_for_of_emitted: bool,
140 preallocated_temp_names: VecDeque<String>,
141 preallocated_assignment_temps: VecDeque<String>,
142 preallocated_logical_assignment_value_temps: VecDeque<String>,
143 hoisted_assignment_value_temps: Vec<String>,
144 hoisted_assignment_temps: Vec<String>,
145}
146
147impl ParamTransformPlan {
148 const fn has_transforms(&self) -> bool {
149 !self.params.is_empty() || self.rest.is_some()
150 }
151}
152
153struct ParamTransform {
154 name: String,
155 pattern: Option<NodeIndex>,
156 initializer: Option<NodeIndex>,
157}
158
159struct RestParamTransform {
160 name: String,
161 pattern: Option<NodeIndex>,
162 index: usize,
163}
164
165struct TemplateParts {
166 cooked: Vec<String>,
167 raw: Vec<String>,
168 expressions: Vec<NodeIndex>,
169}
170
171const MAX_EMIT_RECURSION_DEPTH: u32 = 1000;
177
178pub struct Printer<'a> {
184 pub(super) arena: &'a NodeArena,
186
187 pub(super) writer: SourceWriter,
189
190 pub(super) ctx: EmitContext,
192
193 pub(super) transforms: TransformContext,
195
196 pub(super) emit_missing_initializer_as_void_0: bool,
198
199 pub(super) source_text: Option<&'a str>,
201
202 pub(super) source_map_text: Option<&'a str>,
204
205 pub(super) pending_source_pos: Option<SourcePosition>,
207
208 emit_recursion_depth: u32,
210
211 pub(super) all_comments: Vec<tsz_common::comments::CommentRange>,
214
215 pub(super) comment_emit_idx: usize,
218
219 pub(super) file_identifiers: FxHashSet<String>,
223
224 pub(super) generated_temp_names: FxHashSet<String>,
227
228 temp_scope_stack: Vec<TempScopeState>,
230
231 pub(super) first_for_of_emitted: bool,
233
234 pub(super) in_namespace_iife: bool,
236
237 pub(super) enum_namespace_export: Option<String>,
240
241 pub(super) namespace_export_inner: bool,
245
246 pub(super) emitting_function_body_block: bool,
248
249 pub(super) current_namespace_name: Option<String>,
252
253 pub(super) anonymous_default_export_name: Option<String>,
256 pub(super) pending_commonjs_class_export_name: Option<String>,
259
260 pub(super) declared_namespace_names: FxHashSet<String>,
262
263 pub(super) namespace_exported_names: FxHashSet<String>,
266
267 pub(super) suppress_ns_qualification: bool,
269
270 pub(super) suppress_commonjs_named_import_substitution: bool,
273
274 pub(super) pending_class_field_inits: Vec<(String, NodeIndex)>,
277
278 pub(super) pending_auto_accessor_inits: Vec<(String, Option<NodeIndex>)>,
283
284 pub(super) hoisted_assignment_value_temps: Vec<String>,
287
288 pub(super) preallocated_logical_assignment_value_temps: VecDeque<String>,
291
292 pub(super) preallocated_assignment_temps: VecDeque<String>,
295
296 pub(super) hoisted_assignment_temps: Vec<String>,
299
300 pub(super) preallocated_temp_names: VecDeque<String>,
302
303 pub(super) hoisted_for_of_temps: Vec<String>,
306
307 pub(super) commonjs_named_import_substitutions: FxHashMap<String, String>,
310
311 pub(super) reserved_iterator_return_temps: FxHashMap<NodeIndex, String>,
315
316 pub(super) iterator_for_of_depth: usize,
318
319 pub(super) destructuring_read_depth: u32,
321}
322
323impl<'a> Printer<'a> {
324 const DEFAULT_OUTPUT_CAPACITY: usize = 1024;
325
326 fn estimate_output_capacity(source_len: usize) -> usize {
327 source_len
330 .saturating_mul(3)
331 .saturating_div(2)
332 .max(Self::DEFAULT_OUTPUT_CAPACITY)
333 }
334
335 pub fn new(arena: &'a NodeArena) -> Self {
337 Self::with_options(arena, PrinterOptions::default())
338 }
339
340 pub fn with_source_text_len_and_options(
342 arena: &'a NodeArena,
343 source_text_len: usize,
344 options: PrinterOptions,
345 ) -> Self {
346 let capacity = Self::estimate_output_capacity(source_text_len);
347 Self::with_capacity_and_options(arena, capacity, options)
348 }
349
350 pub fn with_source_text_len(arena: &'a NodeArena, source_text_len: usize) -> Self {
352 Self::with_source_text_len_and_options(arena, source_text_len, PrinterOptions::default())
353 }
354
355 pub fn with_root_and_options(
357 arena: &'a NodeArena,
358 root: NodeIndex,
359 options: PrinterOptions,
360 ) -> Self {
361 let source_text_len = arena
362 .get(root)
363 .and_then(|node| arena.get_source_file(node))
364 .map_or(0, |source| source.text.len());
365 Self::with_source_text_len_and_options(arena, source_text_len, options)
366 }
367
368 pub fn with_root(arena: &'a NodeArena, root: NodeIndex) -> Self {
370 Self::with_root_and_options(arena, root, PrinterOptions::default())
371 }
372
373 pub fn with_capacity(arena: &'a NodeArena, capacity: usize) -> Self {
376 Self::with_capacity_and_options(arena, capacity, PrinterOptions::default())
377 }
378
379 pub fn with_options(arena: &'a NodeArena, options: PrinterOptions) -> Self {
381 Self::with_capacity_and_options(arena, Self::DEFAULT_OUTPUT_CAPACITY, options)
382 }
383
384 pub fn with_capacity_and_options(
386 arena: &'a NodeArena,
387 capacity: usize,
388 options: PrinterOptions,
389 ) -> Self {
390 let mut writer = SourceWriter::with_capacity(capacity);
391 writer.set_new_line_kind(options.new_line);
392
393 let ctx = EmitContext::with_options(options);
395
396 Printer {
397 arena,
398 writer,
399 ctx,
400 transforms: TransformContext::new(), emit_missing_initializer_as_void_0: false,
402 source_text: None,
403 source_map_text: None,
404 pending_source_pos: None,
405 emit_recursion_depth: 0,
406 all_comments: Vec::new(),
407 comment_emit_idx: 0,
408 file_identifiers: FxHashSet::default(),
409 generated_temp_names: FxHashSet::default(),
410 temp_scope_stack: Vec::new(),
411 first_for_of_emitted: false,
412 in_namespace_iife: false,
413 enum_namespace_export: None,
414 namespace_export_inner: false,
415 emitting_function_body_block: false,
416 current_namespace_name: None,
417 anonymous_default_export_name: None,
418 pending_commonjs_class_export_name: None,
419 declared_namespace_names: FxHashSet::default(),
420 namespace_exported_names: FxHashSet::default(),
421 suppress_ns_qualification: false,
422 suppress_commonjs_named_import_substitution: false,
423 pending_class_field_inits: Vec::new(),
424 pending_auto_accessor_inits: Vec::new(),
425 hoisted_assignment_value_temps: Vec::new(),
426 preallocated_logical_assignment_value_temps: VecDeque::new(),
427 preallocated_assignment_temps: VecDeque::new(),
428 hoisted_assignment_temps: Vec::new(),
429 preallocated_temp_names: VecDeque::new(),
430 hoisted_for_of_temps: Vec::new(),
431 commonjs_named_import_substitutions: FxHashMap::default(),
432 reserved_iterator_return_temps: FxHashMap::default(),
433 iterator_for_of_depth: 0,
434 destructuring_read_depth: 0,
435 }
436 }
437
438 pub fn with_transforms(arena: &'a NodeArena, transforms: TransformContext) -> Self {
441 let mut printer = Self::new(arena);
442 printer.transforms = transforms;
443 printer
444 }
445
446 pub fn with_transforms_and_options(
448 arena: &'a NodeArena,
449 transforms: TransformContext,
450 options: PrinterOptions,
451 ) -> Self {
452 let mut printer = Self::with_options(arena, options);
453 printer.transforms = transforms;
454 printer
455 }
456
457 pub const fn set_target_es5(&mut self, es5: bool) {
462 self.ctx.set_target_es5(es5);
463 }
464
465 pub const fn set_target(&mut self, target: ScriptTarget) {
469 self.ctx.set_target(target);
470 }
471
472 pub const fn set_module_kind(&mut self, kind: ModuleKind) {
474 self.ctx.options.module = kind;
475 }
476
477 pub const fn set_auto_detect_module(&mut self, enabled: bool) {
481 self.ctx.auto_detect_module = enabled;
482 }
483
484 pub fn set_source_text(&mut self, text: &'a str) {
486 self.source_text = Some(text);
487 let estimated = Self::estimate_output_capacity(text.len());
488 self.writer.ensure_output_capacity(estimated);
489 }
490
491 pub const fn set_declaration_emit(&mut self, enabled: bool) {
498 self.ctx.flags.in_declaration_emit = enabled;
499 }
500
501 pub const fn set_source_map_text(&mut self, text: &'a str) {
503 self.source_map_text = Some(text);
504 }
505
506 pub fn enable_source_map(&mut self, output_name: &str, source_name: &str) {
508 self.writer.enable_source_map(output_name.to_string());
509 let content = self
510 .source_text_for_map()
511 .map(std::string::ToString::to_string);
512 self.writer.add_source(source_name.to_string(), content);
513 }
514
515 pub fn generate_source_map_json(&mut self) -> Option<String> {
517 self.writer.generate_source_map_json()
518 }
519
520 fn source_text_for_map(&self) -> Option<&'a str> {
521 self.source_map_text.or(self.source_text)
522 }
523
524 fn queue_source_mapping(&mut self, node: &Node) {
525 if !self.writer.has_source_map() {
526 self.pending_source_pos = None;
527 return;
528 }
529
530 let Some(text) = self.source_text_for_map() else {
531 self.pending_source_pos = None;
532 return;
533 };
534
535 self.pending_source_pos = Some(source_position_from_offset(text, node.pos));
536 }
537
538 fn is_single_line(&self, node: &Node) -> bool {
542 if let Some(text) = self.source_text {
543 let actual_start = self.skip_trivia_forward(node.pos, node.end) as usize;
544 let token_end = self.find_token_end_before_trivia(node.pos, node.end);
548 let end = std::cmp::min(token_end as usize, text.len());
549 if actual_start < end {
550 let slice = &text[actual_start..end];
551 if let Some(open) = slice.find('{') {
554 let mut depth = 1;
555 let mut close = None;
556 for (i, ch) in slice[open + 1..].char_indices() {
557 match ch {
558 '{' => depth += 1,
559 '}' => {
560 depth -= 1;
561 if depth == 0 {
562 close = Some(open + 1 + i);
563 break;
564 }
565 }
566 _ => {}
567 }
568 }
569 if let Some(close) = close {
570 let inner = &slice[open..close + 1];
571 return !inner.contains('\n');
572 }
573 }
574 return !slice.contains('\n');
575 }
576 }
577 false
578 }
579
580 fn are_on_same_line_in_source(
582 &self,
583 node1: tsz_parser::parser::NodeIndex,
584 node2: tsz_parser::parser::NodeIndex,
585 ) -> bool {
586 if let Some(text) = self.source_text
587 && let (Some(n1), Some(n2)) = (self.arena.get(node1), self.arena.get(node2))
588 {
589 let start = std::cmp::min(n1.end as usize, text.len());
590 let end = std::cmp::min(n2.pos as usize, text.len());
591 if start < end {
592 return !text[start..end].contains('\n');
594 }
595 }
596 false
597 }
598
599 pub fn get_output(&self) -> &str {
601 self.writer.get_output()
602 }
603
604 pub fn take_output(self) -> String {
606 self.writer.take_output()
607 }
608 pub fn emit(&mut self, idx: NodeIndex) {
614 if idx.is_none() {
615 return;
616 }
617
618 let Some(node) = self.arena.get(idx) else {
619 return;
620 };
621
622 if let Some(source) = self.arena.get_source_file(node)
623 && self.transforms.is_empty()
624 {
625 let format = match self.ctx.options.module {
626 ModuleKind::AMD => Some(crate::context::transform::ModuleFormat::AMD),
627 ModuleKind::UMD => Some(crate::context::transform::ModuleFormat::UMD),
628 ModuleKind::System => Some(crate::context::transform::ModuleFormat::System),
629 _ => None,
630 };
631 if let Some(format) = format
632 && self.file_is_module(&source.statements)
633 {
634 let dependencies = self.collect_module_dependencies(&source.statements.nodes);
635 self.emit_module_wrapper(format, &dependencies, node, source, idx);
636 return;
637 }
638 }
639
640 self.emit_node(node, idx);
641 }
642
643 pub fn emit_expression(&mut self, idx: NodeIndex) {
646 if idx.is_none() {
647 self.write("void 0");
648 return;
649 }
650
651 let Some(node) = self.arena.get(idx) else {
652 self.write("void 0");
653 return;
654 };
655
656 use tsz_scanner::SyntaxKind;
658 if node.kind == SyntaxKind::Unknown as u16 {
659 self.write("void 0");
660 return;
661 }
662
663 self.emit_node(node, idx);
665 }
666
667 fn emit_node(&mut self, node: &Node, idx: NodeIndex) {
669 self.emit_recursion_depth += 1;
671 if self.emit_recursion_depth > MAX_EMIT_RECURSION_DEPTH {
672 warn!(
675 depth = MAX_EMIT_RECURSION_DEPTH,
676 node_kind = node.kind,
677 node_pos = node.pos,
678 "Emit recursion limit exceeded"
679 );
680 self.write("/* emit recursion limit exceeded */");
681 self.emit_recursion_depth -= 1;
682 return;
683 }
684
685 let has_transform = !self.transforms.is_empty()
687 && Self::kind_may_have_transform(node.kind)
688 && self.transforms.has_transform(idx);
689 let previous_pending = self.pending_source_pos;
690
691 self.queue_source_mapping(node);
692 if has_transform {
693 self.apply_transform(node, idx);
694 } else {
695 let kind = node.kind;
696 self.emit_node_by_kind(node, idx, kind);
697 }
698
699 self.pending_source_pos = previous_pending;
700 self.emit_recursion_depth -= 1;
701 }
702
703 const fn kind_may_have_transform(kind: u16) -> bool {
704 matches!(
705 kind,
706 k if k == syntax_kind_ext::SOURCE_FILE
707 || k == syntax_kind_ext::CLASS_DECLARATION
708 || k == syntax_kind_ext::CLASS_EXPRESSION
709 || k == syntax_kind_ext::MODULE_DECLARATION
710 || k == syntax_kind_ext::ENUM_DECLARATION
711 || k == syntax_kind_ext::FUNCTION_DECLARATION
712 || k == syntax_kind_ext::FUNCTION_EXPRESSION
713 || k == syntax_kind_ext::ARROW_FUNCTION
714 || k == syntax_kind_ext::VARIABLE_STATEMENT
715 || k == syntax_kind_ext::VARIABLE_DECLARATION_LIST
716 || k == syntax_kind_ext::FOR_OF_STATEMENT
717 || k == syntax_kind_ext::OBJECT_LITERAL_EXPRESSION
718 || k == syntax_kind_ext::ARRAY_LITERAL_EXPRESSION
719 || k == syntax_kind_ext::TAGGED_TEMPLATE_EXPRESSION
720 || k == syntax_kind_ext::TEMPLATE_EXPRESSION
721 || k == syntax_kind_ext::CALL_EXPRESSION
722 || k == SyntaxKind::NoSubstitutionTemplateLiteral as u16
723 )
724 }
725
726 fn emit_node_by_kind(&mut self, node: &Node, idx: NodeIndex, kind: u16) {
729 match kind {
730 k if k == SyntaxKind::Identifier as u16 => {
732 if self.transforms.has_transform(idx) {
734 if let Some(directive) = self.transforms.get(idx) {
735 match directive {
736 TransformDirective::SubstituteArguments => self.write("arguments"),
737 TransformDirective::SubstituteThis { capture_name } => {
738 let name = std::sync::Arc::clone(capture_name);
739 self.write(&name);
740 }
741 _ => self.emit_identifier(node),
742 }
743 } else {
744 self.emit_identifier(node);
745 }
746 } else {
747 self.emit_identifier(node);
748 }
749 }
750 k if k == SyntaxKind::PrivateIdentifier as u16 => {
751 if let Some(ident) = self.arena.get_identifier(node) {
754 self.write(&ident.escaped_text);
755 }
756 }
757 k if k == syntax_kind_ext::TYPE_PARAMETER => {
758 self.emit_type_parameter(node);
759 }
760
761 k if k == SyntaxKind::NumericLiteral as u16 => {
763 self.emit_numeric_literal(node);
764 }
765 k if k == SyntaxKind::BigIntLiteral as u16 => {
766 self.emit_bigint_literal(node);
767 }
768 k if k == SyntaxKind::StringLiteral as u16 => {
769 self.emit_string_literal(node);
770 }
771 k if k == SyntaxKind::RegularExpressionLiteral as u16 => {
772 self.emit_regex_literal(node);
773 }
774 k if k == SyntaxKind::TrueKeyword as u16 => {
775 self.write("true");
776 }
777 k if k == SyntaxKind::FalseKeyword as u16 => {
778 self.write("false");
779 }
780 k if k == SyntaxKind::NullKeyword as u16 => {
781 self.write("null");
782 }
783
784 k if k == syntax_kind_ext::BINARY_EXPRESSION => {
786 self.emit_binary_expression(node);
787 }
788
789 k if k == syntax_kind_ext::PREFIX_UNARY_EXPRESSION => {
791 self.emit_prefix_unary(node);
792 }
793 k if k == syntax_kind_ext::POSTFIX_UNARY_EXPRESSION => {
794 self.emit_postfix_unary(node);
795 }
796
797 k if k == syntax_kind_ext::CALL_EXPRESSION => {
799 self.emit_call_expression(node);
800 }
801
802 k if k == syntax_kind_ext::NEW_EXPRESSION => {
804 self.emit_new_expression(node);
805 }
806
807 k if k == syntax_kind_ext::PROPERTY_ACCESS_EXPRESSION => {
809 self.emit_property_access(node);
810 }
811
812 k if k == syntax_kind_ext::ELEMENT_ACCESS_EXPRESSION => {
814 self.emit_element_access(node);
815 }
816
817 k if k == syntax_kind_ext::PARENTHESIZED_EXPRESSION => {
819 self.emit_parenthesized(node);
820 }
821 k if k == syntax_kind_ext::TYPE_ASSERTION
822 || k == syntax_kind_ext::AS_EXPRESSION
823 || k == syntax_kind_ext::SATISFIES_EXPRESSION =>
824 {
825 self.emit_type_assertion_expression(node);
826 }
827 k if k == syntax_kind_ext::NON_NULL_EXPRESSION => {
828 self.emit_non_null_expression(node);
829 }
830
831 k if k == syntax_kind_ext::CONDITIONAL_EXPRESSION => {
833 self.emit_conditional(node);
834 }
835
836 k if k == syntax_kind_ext::ARRAY_LITERAL_EXPRESSION => {
838 self.emit_array_literal(node);
839 }
840
841 k if k == syntax_kind_ext::OBJECT_LITERAL_EXPRESSION => {
843 self.emit_object_literal(node);
844 }
845
846 k if k == syntax_kind_ext::ARROW_FUNCTION => {
848 self.emit_arrow_function(node, idx);
849 }
850
851 k if k == syntax_kind_ext::FUNCTION_EXPRESSION => {
853 self.emit_function_expression(node, idx);
854 }
855
856 k if k == syntax_kind_ext::FUNCTION_DECLARATION => {
858 self.emit_function_declaration(node, idx);
859 }
860
861 k if k == syntax_kind_ext::VARIABLE_DECLARATION => {
863 self.emit_variable_declaration(node);
864 }
865
866 k if k == syntax_kind_ext::VARIABLE_DECLARATION_LIST => {
868 self.emit_variable_declaration_list(node);
869 }
870
871 k if k == syntax_kind_ext::VARIABLE_STATEMENT => {
873 self.emit_variable_statement(node);
874 }
875
876 k if k == syntax_kind_ext::EXPRESSION_STATEMENT => {
878 self.emit_expression_statement(node);
879 }
880
881 k if k == syntax_kind_ext::BLOCK => {
883 self.emit_block(node, idx);
884 }
885
886 k if k == syntax_kind_ext::CLASS_STATIC_BLOCK_DECLARATION => {
888 self.write("static ");
889 self.emit_block(node, idx);
891 }
892
893 k if k == syntax_kind_ext::IF_STATEMENT => {
895 self.emit_if_statement(node);
896 }
897
898 k if k == syntax_kind_ext::WHILE_STATEMENT => {
900 self.emit_while_statement(node);
901 }
902
903 k if k == syntax_kind_ext::FOR_STATEMENT => {
905 self.emit_for_statement(node);
906 }
907
908 k if k == syntax_kind_ext::FOR_IN_STATEMENT => {
910 self.emit_for_in_statement(node);
911 }
912
913 k if k == syntax_kind_ext::FOR_OF_STATEMENT => {
915 self.emit_for_of_statement(node);
916 }
917
918 k if k == syntax_kind_ext::RETURN_STATEMENT => {
920 self.emit_return_statement(node);
921 }
922
923 k if k == syntax_kind_ext::CLASS_DECLARATION => {
925 self.emit_class_declaration(node, idx);
926 }
927
928 k if k == syntax_kind_ext::CLASS_EXPRESSION => {
930 self.emit_class_declaration(node, idx);
931 }
932
933 k if k == syntax_kind_ext::PROPERTY_ASSIGNMENT => {
935 self.emit_property_assignment(node);
936 }
937
938 k if k == syntax_kind_ext::SHORTHAND_PROPERTY_ASSIGNMENT => {
940 self.emit_shorthand_property(node);
941 }
942
943 k if k == syntax_kind_ext::SPREAD_ASSIGNMENT => {
946 if let Some(spread) = self.arena.get_spread(node) {
947 self.write("...");
948 self.emit_expression(spread.expression);
949 }
950 }
951
952 k if k == syntax_kind_ext::PARAMETER => {
954 self.emit_parameter(node);
955 }
956
957 k if k == SyntaxKind::NumberKeyword as u16 => self.write("number"),
959 k if k == SyntaxKind::StringKeyword as u16 => self.write("string"),
960 k if k == SyntaxKind::BooleanKeyword as u16 => self.write("boolean"),
961 k if k == SyntaxKind::VoidKeyword as u16 => self.write("void"),
962 k if k == SyntaxKind::AnyKeyword as u16 => self.write("any"),
963 k if k == SyntaxKind::NeverKeyword as u16 => self.write("never"),
964 k if k == SyntaxKind::UnknownKeyword as u16 => self.write("unknown"),
965 k if k == SyntaxKind::UndefinedKeyword as u16 => self.write("undefined"),
966 k if k == SyntaxKind::ObjectKeyword as u16 => self.write("object"),
967 k if k == SyntaxKind::SymbolKeyword as u16 => self.write("symbol"),
968 k if k == SyntaxKind::BigIntKeyword as u16 => self.write("bigint"),
969
970 k if k == syntax_kind_ext::TYPE_REFERENCE => {
972 self.emit_type_reference(node);
973 }
974
975 k if k == syntax_kind_ext::ARRAY_TYPE => {
977 self.emit_array_type(node);
978 }
979
980 k if k == syntax_kind_ext::UNION_TYPE => {
982 self.emit_union_type(node);
983 }
984
985 k if k == syntax_kind_ext::INTERSECTION_TYPE => {
987 self.emit_intersection_type(node);
988 }
989
990 k if k == syntax_kind_ext::TUPLE_TYPE => {
992 self.emit_tuple_type(node);
993 }
994
995 k if k == syntax_kind_ext::FUNCTION_TYPE => {
997 self.emit_function_type(node);
998 }
999
1000 k if k == syntax_kind_ext::TYPE_LITERAL => {
1002 self.emit_type_literal(node);
1003 }
1004
1005 k if k == syntax_kind_ext::PARENTHESIZED_TYPE => {
1007 self.emit_parenthesized_type(node);
1008 }
1009
1010 k if k == syntax_kind_ext::EMPTY_STATEMENT => {
1012 self.write_semicolon();
1013 }
1014
1015 k if k == syntax_kind_ext::JSX_ELEMENT => {
1017 self.emit_jsx_element(node);
1018 }
1019 k if k == syntax_kind_ext::JSX_SELF_CLOSING_ELEMENT => {
1020 self.emit_jsx_self_closing_element(node);
1021 }
1022 k if k == syntax_kind_ext::JSX_OPENING_ELEMENT => {
1023 self.emit_jsx_opening_element(node);
1024 }
1025 k if k == syntax_kind_ext::JSX_CLOSING_ELEMENT => {
1026 self.emit_jsx_closing_element(node);
1027 }
1028 k if k == syntax_kind_ext::JSX_FRAGMENT => {
1029 self.emit_jsx_fragment(node);
1030 }
1031 k if k == syntax_kind_ext::JSX_OPENING_FRAGMENT => {
1032 self.write("<>");
1033 }
1034 k if k == syntax_kind_ext::JSX_CLOSING_FRAGMENT => {
1035 self.write("</>");
1036 }
1037 k if k == syntax_kind_ext::JSX_ATTRIBUTES => {
1038 self.emit_jsx_attributes(node);
1039 }
1040 k if k == syntax_kind_ext::JSX_ATTRIBUTE => {
1041 self.emit_jsx_attribute(node);
1042 }
1043 k if k == syntax_kind_ext::JSX_SPREAD_ATTRIBUTE => {
1044 self.emit_jsx_spread_attribute(node);
1045 }
1046 k if k == syntax_kind_ext::JSX_EXPRESSION => {
1047 self.emit_jsx_expression(node);
1048 }
1049 k if k == SyntaxKind::JsxText as u16 => {
1050 self.emit_jsx_text(node);
1051 }
1052 k if k == syntax_kind_ext::JSX_NAMESPACED_NAME => {
1053 self.emit_jsx_namespaced_name(node);
1054 }
1055
1056 k if k == syntax_kind_ext::IMPORT_DECLARATION => {
1058 self.emit_import_declaration(node);
1059 }
1060 k if k == syntax_kind_ext::IMPORT_EQUALS_DECLARATION => {
1061 self.emit_import_equals_declaration(node);
1062 }
1063 k if k == syntax_kind_ext::IMPORT_CLAUSE => {
1064 self.emit_import_clause(node);
1065 }
1066 k if k == syntax_kind_ext::NAMED_IMPORTS || k == syntax_kind_ext::NAMESPACE_IMPORT => {
1067 self.emit_named_imports(node);
1068 }
1069 k if k == syntax_kind_ext::IMPORT_SPECIFIER => {
1070 self.emit_specifier(node);
1071 }
1072 k if k == syntax_kind_ext::EXPORT_DECLARATION => {
1073 self.emit_export_declaration(node);
1074 }
1075 k if k == syntax_kind_ext::NAMESPACE_EXPORT => {
1076 if let Some(data) = self.arena.get_named_imports(node) {
1078 self.write("* as ");
1079 self.emit(data.name);
1080 }
1081 }
1082 k if k == syntax_kind_ext::NAMED_EXPORTS => {
1083 self.emit_named_exports(node);
1084 }
1085 k if k == syntax_kind_ext::EXPORT_SPECIFIER => {
1086 self.emit_specifier(node);
1087 }
1088 k if k == syntax_kind_ext::EXPORT_ASSIGNMENT => {
1089 self.emit_export_assignment(node);
1090 }
1091
1092 k if k == syntax_kind_ext::THROW_STATEMENT => {
1094 self.emit_throw_statement(node);
1095 }
1096 k if k == syntax_kind_ext::TRY_STATEMENT => {
1097 self.emit_try_statement(node);
1098 }
1099 k if k == syntax_kind_ext::CATCH_CLAUSE => {
1100 self.emit_catch_clause(node);
1101 }
1102 k if k == syntax_kind_ext::SWITCH_STATEMENT => {
1103 self.emit_switch_statement(node);
1104 }
1105 k if k == syntax_kind_ext::CASE_CLAUSE => {
1106 self.emit_case_clause(node);
1107 }
1108 k if k == syntax_kind_ext::DEFAULT_CLAUSE => {
1109 self.emit_default_clause(node);
1110 }
1111 k if k == syntax_kind_ext::CASE_BLOCK => {
1112 self.emit_case_block(node);
1113 }
1114 k if k == syntax_kind_ext::BREAK_STATEMENT => {
1115 self.emit_break_statement(node);
1116 }
1117 k if k == syntax_kind_ext::CONTINUE_STATEMENT => {
1118 self.emit_continue_statement(node);
1119 }
1120 k if k == syntax_kind_ext::LABELED_STATEMENT => {
1121 self.emit_labeled_statement(node);
1122 }
1123 k if k == syntax_kind_ext::DO_STATEMENT => {
1124 self.emit_do_statement(node);
1125 }
1126 k if k == syntax_kind_ext::DEBUGGER_STATEMENT => {
1127 self.emit_debugger_statement(node);
1128 }
1129 k if k == syntax_kind_ext::WITH_STATEMENT => {
1130 self.emit_with_statement(node);
1131 }
1132
1133 k if k == syntax_kind_ext::ENUM_DECLARATION => {
1135 self.emit_enum_declaration(node, idx);
1136 }
1137 k if k == syntax_kind_ext::ENUM_MEMBER => {
1138 self.emit_enum_member(node);
1139 }
1140 k if k == syntax_kind_ext::INTERFACE_DECLARATION => {
1141 if self.ctx.flags.in_declaration_emit {
1143 self.emit_interface_declaration(node);
1144 } else {
1145 self.skip_comments_for_erased_node(node);
1148 }
1149 }
1150 k if k == syntax_kind_ext::TYPE_ALIAS_DECLARATION => {
1151 if self.ctx.flags.in_declaration_emit {
1153 self.emit_type_alias_declaration(node);
1154 } else {
1155 self.skip_comments_for_erased_node(node);
1156 }
1157 }
1158 k if k == syntax_kind_ext::MODULE_DECLARATION => {
1159 self.emit_module_declaration(node, idx);
1160 }
1161
1162 k if k == syntax_kind_ext::COMPUTED_PROPERTY_NAME => {
1164 if let Some(computed) = self.arena.get_computed_property(node) {
1165 self.write("[");
1166 self.emit(computed.expression);
1167 if let Some(text) = self.source_text_for_map() {
1172 let expr_end = self
1173 .arena
1174 .get(computed.expression)
1175 .map_or(node.pos + 1, |e| e.end);
1176 self.pending_source_pos = Some(source_position_from_offset(text, expr_end));
1177 }
1178 self.write("]");
1179 }
1180 }
1181
1182 k if k == syntax_kind_ext::METHOD_DECLARATION => {
1184 self.emit_method_declaration(node);
1185 }
1186 k if k == syntax_kind_ext::PROPERTY_DECLARATION => {
1187 self.emit_property_declaration(node);
1188 }
1189 k if k == syntax_kind_ext::CONSTRUCTOR => {
1190 self.emit_constructor_declaration(node);
1191 }
1192 k if k == syntax_kind_ext::GET_ACCESSOR => {
1193 self.emit_get_accessor(node);
1194 }
1195 k if k == syntax_kind_ext::SET_ACCESSOR => {
1196 self.emit_set_accessor(node);
1197 }
1198 k if k == syntax_kind_ext::SEMICOLON_CLASS_ELEMENT => {
1199 self.write(";");
1200 }
1201 k if k == syntax_kind_ext::DECORATOR => {
1202 self.emit_decorator(node);
1203 }
1204
1205 k if k == syntax_kind_ext::PROPERTY_SIGNATURE => {
1207 self.emit_property_signature(node);
1208 }
1209 k if k == syntax_kind_ext::METHOD_SIGNATURE => {
1210 self.emit_method_signature(node);
1211 }
1212 k if k == syntax_kind_ext::CALL_SIGNATURE => {
1213 if self.ctx.flags.in_declaration_emit {
1215 self.emit_call_signature(node);
1216 }
1217 }
1218 k if k == syntax_kind_ext::CONSTRUCT_SIGNATURE => {
1219 if self.ctx.flags.in_declaration_emit {
1221 self.emit_construct_signature(node);
1222 }
1223 }
1224 k if k == syntax_kind_ext::INDEX_SIGNATURE => {
1225 if self.ctx.flags.in_declaration_emit {
1227 self.emit_index_signature(node);
1228 }
1229 }
1230
1231 k if k == syntax_kind_ext::TAGGED_TEMPLATE_EXPRESSION => {
1233 self.emit_tagged_template_expression(node, idx);
1234 }
1235 k if k == syntax_kind_ext::TEMPLATE_EXPRESSION => {
1236 self.emit_template_expression(node);
1237 }
1238 k if k == SyntaxKind::NoSubstitutionTemplateLiteral as u16 => {
1239 self.emit_no_substitution_template(node);
1240 }
1241 k if k == syntax_kind_ext::TEMPLATE_SPAN => {
1242 self.emit_template_span(node);
1243 }
1244 k if k == SyntaxKind::TemplateHead as u16 => {
1245 self.emit_template_head(node);
1246 }
1247 k if k == SyntaxKind::TemplateMiddle as u16 => {
1248 self.emit_template_middle(node);
1249 }
1250 k if k == SyntaxKind::TemplateTail as u16 => {
1251 self.emit_template_tail(node);
1252 }
1253
1254 k if k == syntax_kind_ext::YIELD_EXPRESSION => {
1256 self.emit_yield_expression(node);
1257 }
1258 k if k == syntax_kind_ext::AWAIT_EXPRESSION => {
1259 self.emit_await_expression(node);
1260 }
1261 k if k == syntax_kind_ext::SPREAD_ELEMENT => {
1262 self.emit_spread_element(node);
1263 }
1264
1265 k if k == syntax_kind_ext::SOURCE_FILE => {
1267 self.emit_source_file(node, idx);
1268 }
1269
1270 k if k == SyntaxKind::ThisKeyword as u16 => {
1272 if let Some(TransformDirective::SubstituteThis { capture_name }) =
1275 self.transforms.get(idx)
1276 {
1277 let name = std::sync::Arc::clone(capture_name);
1278 self.write(&name);
1279 } else {
1280 self.write("this");
1281 }
1282 }
1283 k if k == SyntaxKind::SuperKeyword as u16 => self.write("super"),
1284 k if k == SyntaxKind::ImportKeyword as u16 => self.write("import"),
1285
1286 k if k == syntax_kind_ext::OBJECT_BINDING_PATTERN => {
1288 self.emit_object_binding_pattern(node);
1290 }
1291 k if k == syntax_kind_ext::ARRAY_BINDING_PATTERN => {
1292 self.emit_array_binding_pattern(node);
1293 }
1294 k if k == syntax_kind_ext::BINDING_ELEMENT => {
1295 self.emit_binding_element(node);
1296 }
1297
1298 k if k == syntax_kind_ext::EXPRESSION_WITH_TYPE_ARGUMENTS => {
1302 if let Some(data) = self.arena.get_expr_type_args(node) {
1303 self.write("(");
1304 self.emit(data.expression);
1305 self.write(")");
1306 }
1307 }
1308
1309 _ => {}
1311 }
1312 }
1313}
1314
1315pub(super) use crate::transforms::emit_utils::is_valid_identifier_name;
1320
1321const fn get_operator_text(op: u16) -> &'static str {
1322 crate::transforms::emit_utils::operator_to_str(op)
1323}