1use crate::diagnostic::{Diagnostic, DiagnosticCode};
31use crate::source::{SourceId, SourceText, TextRange};
32use crate::syntax::*;
33
34pub mod codes {
36 use crate::diagnostic::DiagnosticCode;
37
38 pub const MISSING_EXPRESSION: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1001");
40 pub const MISSING_STATEMENT: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1002");
42 pub const MISSING_TYPE: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1003");
44 pub const MISSING_BINDING: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1004");
46 pub const MISSING_TARGET: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1005");
48 pub const MISSING_PROPERTY_NAME: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1006");
50 pub const MISSING_NAME: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1007");
52 pub const MISSING_MEMBER: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1008");
54 pub const MISSING_ELEMENT: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1009");
56 pub const UNRESOLVED_TOKEN: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1010");
58 pub const NAMESPACE_UNLOWERED: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1011");
60 pub const DECORATOR_UNLOWERED: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1012");
62 pub const ENUM_MEMBER_INITIALIZER: DiagnosticCode = DiagnosticCode::new("TS-EMIT-1013");
64}
65
66#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
68pub enum EmitMode {
69 JavaScript,
71 Declaration,
73}
74
75#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
77pub enum Newline {
78 Lf,
80 CrLf,
82}
83
84impl Newline {
85 const fn as_str(self) -> &'static str {
86 match self {
87 Self::Lf => "\n",
88 Self::CrLf => "\r\n",
89 }
90 }
91}
92
93#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
95pub struct EmitOptions {
96 pub mode: EmitMode,
98 pub newline: Newline,
100 pub indent_width: u8,
102}
103
104impl Default for EmitOptions {
105 fn default() -> Self {
106 Self {
107 mode: EmitMode::JavaScript,
108 newline: Newline::Lf,
109 indent_width: 4,
110 }
111 }
112}
113
114impl EmitOptions {
115 #[must_use]
117 pub const fn javascript() -> Self {
118 Self {
119 mode: EmitMode::JavaScript,
120 newline: Newline::Lf,
121 indent_width: 4,
122 }
123 }
124
125 #[must_use]
127 pub const fn declaration() -> Self {
128 Self {
129 mode: EmitMode::Declaration,
130 newline: Newline::Lf,
131 indent_width: 4,
132 }
133 }
134
135 #[must_use]
137 pub const fn with_newline(mut self, newline: Newline) -> Self {
138 self.newline = newline;
139 self
140 }
141
142 #[must_use]
144 pub const fn with_indent_width(mut self, indent_width: u8) -> Self {
145 self.indent_width = indent_width;
146 self
147 }
148}
149
150#[derive(Clone, Debug, Eq, PartialEq)]
152pub struct EmitOutput {
153 pub code: String,
155 pub diagnostics: Vec<Diagnostic>,
157}
158
159impl EmitOutput {
160 #[must_use]
162 pub fn has_errors(&self) -> bool {
163 self.diagnostics.iter().any(|d| !d.is_warning())
164 }
165}
166
167#[must_use]
169pub fn emit(file: &SourceFile, options: EmitOptions) -> EmitOutput {
170 let mut emitter = Emitter {
171 source: file.source_text(),
172 source_id: file.source_id(),
173 options,
174 out: String::new(),
175 indent: 0,
176 pending_indent: false,
177 anchor: file.range(),
178 diagnostics: Vec::new(),
179 enum_context: None,
180 decl_ambient: false,
181 decl_in_export: false,
182 };
183 match options.mode {
184 EmitMode::JavaScript => emitter.emit_module_js(file.statements()),
185 EmitMode::Declaration => emitter.emit_module_decl(file.statements()),
186 }
187 emitter.diagnostics.sort();
188 EmitOutput {
189 code: emitter.out,
190 diagnostics: emitter.diagnostics,
191 }
192}
193
194const P_SEQUENCE: u8 = 1;
196const P_ASSIGN: u8 = 2;
197const P_CONDITIONAL: u8 = 3;
198const P_NULLISH: u8 = 4;
199const P_LOGICAL_OR: u8 = 4;
200const P_LOGICAL_AND: u8 = 5;
201const P_BIT_OR: u8 = 6;
202const P_BIT_XOR: u8 = 7;
203const P_BIT_AND: u8 = 8;
204const P_EQUALITY: u8 = 9;
205const P_RELATIONAL: u8 = 10;
206const P_SHIFT: u8 = 11;
207const P_ADDITIVE: u8 = 12;
208const P_MULTIPLICATIVE: u8 = 13;
209const P_EXPONENT: u8 = 14;
210const P_UNARY: u8 = 15;
211const P_POSTFIX: u8 = 16;
212const P_CALL_MEMBER: u8 = 17;
213const P_PRIMARY: u8 = 18;
214
215struct EnumContext {
216 object: String,
217 members: Vec<String>,
218}
219
220struct Emitter<'a> {
221 source: &'a SourceText,
222 source_id: SourceId,
223 options: EmitOptions,
224 out: String,
225 indent: usize,
226 pending_indent: bool,
227 anchor: TextRange,
228 diagnostics: Vec<Diagnostic>,
229 enum_context: Option<EnumContext>,
230 decl_ambient: bool,
231 decl_in_export: bool,
232}
233
234impl<'a> Emitter<'a> {
235 fn raw(&mut self, text: &str) {
238 if text.is_empty() {
239 return;
240 }
241 if self.pending_indent {
242 let spaces = self.indent * self.options.indent_width as usize;
243 for _ in 0..spaces {
244 self.out.push(' ');
245 }
246 self.pending_indent = false;
247 }
248 self.out.push_str(text);
249 }
250
251 fn newline(&mut self) {
252 self.out.push_str(self.options.newline.as_str());
253 self.pending_indent = true;
254 }
255
256 fn diag(&mut self, code: DiagnosticCode, message: &'static str, range: TextRange) {
257 self.diagnostics
258 .push(Diagnostic::error(code, self.source_id, range, message));
259 }
260
261 fn diag_here(&mut self, code: DiagnosticCode, message: &'static str) {
262 let range = self.anchor;
263 self.diag(code, message, range);
264 }
265
266 fn text(&self, token: &Token) -> Option<&'a str> {
268 if token.is_missing() {
269 return Some("");
270 }
271 let source: &'a SourceText = self.source;
272 let range = token.range();
273 let start = source.utf16_to_byte(range.start()).ok()?;
274 let end = source.utf16_to_byte(range.end()).ok()?;
275 source.as_str().get(start..end)
276 }
277
278 fn emit_token(&mut self, token: &Token) {
279 match self.text(token) {
280 Some(text) => self.raw(text),
281 None => {
282 let range = token.range();
283 self.diag(
284 codes::UNRESOLVED_TOKEN,
285 "token text is not a valid slice of the source",
286 range,
287 );
288 }
289 }
290 }
291
292 fn emit_ident(&mut self, ident: &IdentifierNode) {
293 self.emit_token(ident.data().token());
294 }
295
296 fn emit_string(&mut self, literal: &StringLiteralNode) {
297 self.emit_token(literal.data().token());
298 }
299
300 fn emit_module_js(&mut self, statements: &[Stmt]) {
303 for statement in statements {
304 if self.emit_statement(statement) {
305 self.newline();
306 }
307 }
308 }
309
310 fn emit_module_decl(&mut self, statements: &[Stmt]) {
311 self.decl_ambient = true;
312 for statement in statements {
313 if self.emit_declaration(statement) {
314 self.newline();
315 }
316 }
317 }
318
319 fn emit_statement(&mut self, statement: &Stmt) -> bool {
324 let previous = self.anchor;
325 self.anchor = statement.range();
326 let emitted = match statement.data() {
327 Statement::Import(import) => self.emit_import(import, false),
328 Statement::ImportEquals(import) => {
329 if import.is_type_only {
330 false
331 } else {
332 self.emit_import_equals_js(import);
333 true
334 }
335 }
336 Statement::Export(export) => self.emit_export_js(export),
337 Statement::Variable(declaration) => {
338 self.emit_variable_head(declaration);
339 self.raw(";");
340 true
341 }
342 Statement::Function(function) => {
343 if function.function.body.is_none() {
344 false
345 } else {
346 self.emit_function_declaration_js(&function.function);
347 true
348 }
349 }
350 Statement::Class(class) => {
351 self.emit_class_js(class);
352 true
353 }
354 Statement::Interface(_) | Statement::TypeAlias(_) | Statement::Declare(_) => false,
355 Statement::Enum(declaration) => self.emit_enum_js(declaration),
356 Statement::Namespace(_) => {
357 self.diag_here(
358 codes::NAMESPACE_UNLOWERED,
359 "namespace runtime lowering requires semantic analysis",
360 );
361 false
362 }
363 Statement::Block(block) => {
364 self.emit_block(block.data());
365 true
366 }
367 Statement::Empty => false,
368 Statement::Expression(statement) => {
369 self.emit_expression_statement(statement);
370 true
371 }
372 Statement::If(_) => {
373 self.emit_if(statement);
374 true
375 }
376 Statement::Switch(switch) => {
377 self.emit_switch(switch);
378 true
379 }
380 Statement::For(statement) => {
381 self.emit_for(statement);
382 true
383 }
384 Statement::ForIn(statement) => {
385 self.emit_for_in(statement);
386 true
387 }
388 Statement::ForOf(statement) => {
389 self.emit_for_of(statement);
390 true
391 }
392 Statement::While(statement) => {
393 self.raw("while (");
394 self.emit_expression(&statement.test);
395 self.raw(")");
396 self.emit_control_body(&statement.body);
397 true
398 }
399 Statement::DoWhile(statement) => {
400 self.raw("do");
401 self.emit_control_body(&statement.body);
402 self.raw(" while (");
403 self.emit_expression(&statement.test);
404 self.raw(");");
405 true
406 }
407 Statement::Try(statement) => {
408 self.emit_try(statement);
409 true
410 }
411 Statement::With(statement) => {
412 self.raw("with (");
413 self.emit_expression(&statement.object);
414 self.raw(")");
415 self.emit_control_body(&statement.body);
416 true
417 }
418 Statement::Labeled(statement) => {
419 self.emit_ident(&statement.label);
420 self.raw(": ");
421 self.emit_statement(&statement.body);
422 true
423 }
424 Statement::Break(jump) => {
425 self.raw("break");
426 if let Some(label) = &jump.label {
427 self.raw(" ");
428 self.emit_ident(label);
429 }
430 self.raw(";");
431 true
432 }
433 Statement::Continue(jump) => {
434 self.raw("continue");
435 if let Some(label) = &jump.label {
436 self.raw(" ");
437 self.emit_ident(label);
438 }
439 self.raw(";");
440 true
441 }
442 Statement::Return(statement) => {
443 self.raw("return");
444 if let Some(argument) = &statement.argument {
445 self.raw(" ");
446 self.emit_expression(argument);
447 }
448 self.raw(";");
449 true
450 }
451 Statement::Throw(statement) => {
452 self.raw("throw ");
453 self.emit_expression(&statement.argument);
454 self.raw(";");
455 true
456 }
457 Statement::Debugger => {
458 self.raw("debugger;");
459 true
460 }
461 Statement::Missing(_) => {
462 self.diag_here(
463 codes::MISSING_STATEMENT,
464 "cannot emit a missing statement node",
465 );
466 self.raw(";");
467 true
468 }
469 };
470 self.anchor = previous;
471 emitted
472 }
473
474 fn emit_expression_statement(&mut self, statement: &ExpressionStatement) {
475 let expression = &statement.expression;
476 let wrap = self.leads_with_bad_token(expression, false);
477 if wrap {
478 self.raw("(");
479 self.emit_expression_prec(expression, 0);
480 self.raw(")");
481 } else {
482 self.emit_expression_prec(expression, 0);
483 }
484 self.raw(";");
485 }
486
487 fn emit_if(&mut self, statement: &Stmt) {
488 let Statement::If(if_statement) = statement.data() else {
489 return;
490 };
491 self.raw("if (");
492 self.emit_expression(&if_statement.test);
493 self.raw(")");
494 self.emit_control_body(&if_statement.consequent);
495 if let Some(alternate) = &if_statement.alternate {
496 if matches!(alternate.data(), Statement::If(_)) {
497 self.raw(" else ");
498 self.emit_if(alternate);
499 } else {
500 self.raw(" else");
501 self.emit_control_body(alternate);
502 }
503 }
504 }
505
506 fn emit_control_body(&mut self, statement: &Stmt) {
507 self.raw(" ");
508 match statement.data() {
509 Statement::Block(block) => self.emit_block(block.data()),
510 Statement::Empty => self.raw("{}"),
511 _ => {
512 self.raw("{");
513 self.newline();
514 self.indent += 1;
515 if self.emit_statement(statement) {
516 self.newline();
517 }
518 self.indent -= 1;
519 self.raw("}");
520 }
521 }
522 }
523
524 fn emit_block(&mut self, block: &Block) {
525 if block.statements.is_empty() {
526 self.raw("{}");
527 return;
528 }
529 self.raw("{");
530 self.newline();
531 self.indent += 1;
532 for statement in &block.statements {
533 if self.emit_statement(statement) {
534 self.newline();
535 }
536 }
537 self.indent -= 1;
538 self.raw("}");
539 }
540
541 fn emit_switch(&mut self, switch: &SwitchStatement) {
542 self.raw("switch (");
543 self.emit_expression(&switch.discriminant);
544 self.raw(") ");
545 if switch.cases.is_empty() {
546 self.raw("{}");
547 return;
548 }
549 self.raw("{");
550 self.newline();
551 self.indent += 1;
552 for case in &switch.cases {
553 let case = case.data();
554 match &case.test {
555 Some(test) => {
556 self.raw("case ");
557 self.emit_expression(test);
558 self.raw(":");
559 }
560 None => self.raw("default:"),
561 }
562 self.newline();
563 if !case.consequent.is_empty() {
564 self.indent += 1;
565 for statement in &case.consequent {
566 if self.emit_statement(statement) {
567 self.newline();
568 }
569 }
570 self.indent -= 1;
571 }
572 }
573 self.indent -= 1;
574 self.raw("}");
575 }
576
577 fn emit_for(&mut self, statement: &ForStatement) {
578 self.raw("for (");
579 match &statement.initializer {
580 Some(ForInitializer::Variable(declaration)) => self.emit_variable_head(declaration),
581 Some(ForInitializer::Expression(expression)) => {
582 self.emit_expression_prec(expression, 0);
583 }
584 None => {}
585 }
586 self.raw(";");
587 if let Some(test) = &statement.test {
588 self.raw(" ");
589 self.emit_expression(test);
590 }
591 self.raw(";");
592 if let Some(update) = &statement.update {
593 self.raw(" ");
594 self.emit_expression(update);
595 }
596 self.raw(")");
597 self.emit_control_body(&statement.body);
598 }
599
600 fn emit_for_in(&mut self, statement: &ForInStatement) {
601 self.raw("for (");
602 self.emit_for_binding(&statement.binding);
603 self.raw(" in ");
604 self.emit_expression_prec(&statement.object, P_ASSIGN);
605 self.raw(")");
606 self.emit_control_body(&statement.body);
607 }
608
609 fn emit_for_of(&mut self, statement: &ForOfStatement) {
610 if matches!(statement.mode, ForOfMode::Async) {
611 self.raw("for await (");
612 } else {
613 self.raw("for (");
614 }
615 self.emit_for_binding(&statement.binding);
616 self.raw(" of ");
617 self.emit_expression_prec(&statement.iterable, P_ASSIGN);
618 self.raw(")");
619 self.emit_control_body(&statement.body);
620 }
621
622 fn emit_for_binding(&mut self, binding: &ForBinding) {
623 match binding {
624 ForBinding::Variable(declaration) => self.emit_variable_head(declaration),
625 ForBinding::Target(target) => self.emit_assignment_target(target),
626 }
627 }
628
629 fn emit_try(&mut self, statement: &TryStatement) {
630 self.raw("try ");
631 self.emit_block(statement.block.data());
632 if let Some(handler) = &statement.handler {
633 let handler = handler.data();
634 self.raw(" catch");
635 if let Some(binding) = &handler.binding {
636 self.raw(" (");
637 self.emit_pattern(binding);
638 self.raw(")");
639 }
640 self.raw(" ");
641 self.emit_block(handler.body.data());
642 }
643 if let Some(finalizer) = &statement.finalizer {
644 self.raw(" finally ");
645 self.emit_block(finalizer.data());
646 }
647 }
648
649 fn emit_variable_head(&mut self, declaration: &VariableDeclaration) {
650 self.raw(variable_kind_str(declaration.kind));
651 self.raw(" ");
652 for (index, declarator) in declaration.declarations.iter().enumerate() {
653 if index > 0 {
654 self.raw(", ");
655 }
656 let declarator = declarator.data();
657 self.emit_pattern(&declarator.binding);
658 if let Some(initializer) = &declarator.initializer {
659 self.raw(" = ");
660 self.emit_expression_prec(initializer, P_ASSIGN);
661 }
662 }
663 }
664
665 fn emit_import(&mut self, import: &ImportDeclaration, keep_types: bool) -> bool {
668 if import.type_only && !keep_types {
669 return false;
670 }
671
672 if !keep_types && let Some(clause) = &import.clause {
676 let has_value = clause.default.is_some()
677 || matches!(&clause.binding, Some(ImportBinding::Namespace(_)))
678 || matches!(
679 &clause.binding,
680 Some(ImportBinding::Named(specifiers))
681 if specifiers
682 .iter()
683 .any(|s| matches!(s.data().mode, ImportSpecifierMode::Value))
684 );
685 if !has_value {
686 return false;
687 }
688 }
689
690 self.raw("import ");
691 if keep_types && import.type_only {
692 self.raw("type ");
693 }
694 if let Some(clause) = &import.clause {
695 let mut wrote = false;
696 if let Some(default) = &clause.default {
697 self.emit_ident(default);
698 wrote = true;
699 }
700 if let Some(binding) = &clause.binding {
701 match binding {
702 ImportBinding::Namespace(name) => {
703 if wrote {
704 self.raw(", ");
705 }
706 self.raw("* as ");
707 self.emit_ident(name);
708 }
709 ImportBinding::Named(specifiers) => {
710 if wrote {
711 self.raw(", ");
712 }
713 self.emit_named_imports(specifiers, keep_types);
714 }
715 }
716 }
717 self.raw(" from ");
718 }
719 self.emit_string(&import.source);
720 if let Some(attributes) = &import.attributes {
721 self.emit_import_attributes(attributes);
722 }
723 self.raw(";");
724 true
725 }
726
727 fn emit_named_imports(&mut self, specifiers: &[ImportSpecifierNode], keep_types: bool) {
728 let visible: Vec<&ImportSpecifierNode> = specifiers
729 .iter()
730 .filter(|s| keep_types || matches!(s.data().mode, ImportSpecifierMode::Value))
731 .collect();
732 if visible.is_empty() {
733 self.raw("{}");
734 return;
735 }
736 self.raw("{ ");
737 for (index, specifier) in visible.iter().enumerate() {
738 if index > 0 {
739 self.raw(", ");
740 }
741 let specifier = specifier.data();
742 if keep_types && matches!(specifier.mode, ImportSpecifierMode::TypeOnly) {
743 self.raw("type ");
744 }
745 if self.module_name_matches_ident(&specifier.imported, &specifier.local) {
746 self.emit_ident(&specifier.local);
747 } else {
748 self.emit_module_export_name(&specifier.imported);
749 self.raw(" as ");
750 self.emit_ident(&specifier.local);
751 }
752 }
753 self.raw(" }");
754 }
755
756 fn emit_import_attributes(&mut self, attributes: &ImportAttributes) {
757 if attributes.entries.is_empty() {
758 return;
759 }
760 self.raw(" with { ");
761 for (index, entry) in attributes.entries.iter().enumerate() {
762 if index > 0 {
763 self.raw(", ");
764 }
765 self.emit_module_export_name(&entry.name);
766 self.raw(": ");
767 self.emit_string(&entry.value);
768 }
769 self.raw(" }");
770 }
771
772 fn emit_import_equals_js(&mut self, import: &ImportEqualsDeclaration) {
773 self.raw("const ");
774 self.emit_ident(&import.local);
775 self.raw(" = ");
776 match &import.reference {
777 ExternalModuleReference::Require(source) => {
778 self.raw("require(");
779 self.emit_string(source);
780 self.raw(")");
781 }
782 ExternalModuleReference::Qualified(name) => self.emit_entity_name(name),
783 ExternalModuleReference::Missing(_) => {
784 self.diag_here(
785 codes::MISSING_NAME,
786 "cannot emit a missing module reference",
787 );
788 }
789 }
790 self.raw(";");
791 }
792
793 fn emit_export_js(&mut self, export: &ExportDeclaration) -> bool {
794 match export {
795 ExportDeclaration::Named(ExportNamedDeclaration::Declaration(inner)) => {
796 if !self.js_statement_emits(inner) {
797 self.emit_statement(inner);
799 return false;
800 }
801 self.raw("export ");
802 self.emit_statement(inner)
803 }
804 ExportDeclaration::Named(ExportNamedDeclaration::Specifiers {
805 type_only,
806 specifiers,
807 source,
808 attributes,
809 }) => {
810 if *type_only {
811 return false;
812 }
813 let visible: Vec<&ExportSpecifierNode> = specifiers
814 .iter()
815 .filter(|s| matches!(s.data().mode, ExportSpecifierMode::Value))
816 .collect();
817 if visible.is_empty() {
818 return false;
819 }
820 self.raw("export { ");
821 for (index, specifier) in visible.iter().enumerate() {
822 if index > 0 {
823 self.raw(", ");
824 }
825 self.emit_export_specifier(specifier.data(), false);
826 }
827 self.raw(" }");
828 if let Some(source) = source {
829 self.raw(" from ");
830 self.emit_string(source);
831 if let Some(attributes) = attributes {
832 self.emit_import_attributes(attributes);
833 }
834 }
835 self.raw(";");
836 true
837 }
838 ExportDeclaration::All(all) => {
839 if all.type_only {
840 return false;
841 }
842 self.raw("export * ");
843 if let Some(name) = &all.exported {
844 self.raw("as ");
845 self.emit_module_export_name(name);
846 self.raw(" ");
847 }
848 self.raw("from ");
849 self.emit_string(&all.source);
850 if let Some(attributes) = &all.attributes {
851 self.emit_import_attributes(attributes);
852 }
853 self.raw(";");
854 true
855 }
856 ExportDeclaration::Default(default) => match &default.value {
857 ExportDefaultValue::Function(function) => {
858 self.raw("export default ");
859 self.emit_function_declaration_js(function);
860 true
861 }
862 ExportDefaultValue::Class(class) => {
863 self.raw("export default ");
864 self.emit_class_core_js(class);
865 true
866 }
867 ExportDefaultValue::Expression(expression) => {
868 self.raw("export default ");
869 self.emit_expression_prec(expression, P_ASSIGN);
870 self.raw(";");
871 true
872 }
873 ExportDefaultValue::Missing(_) => {
874 self.diag_here(
875 codes::MISSING_EXPRESSION,
876 "cannot emit a missing default export",
877 );
878 false
879 }
880 },
881 ExportDeclaration::Assignment(expression) => {
882 self.raw("module.exports = ");
883 self.emit_expression_prec(expression, P_ASSIGN);
884 self.raw(";");
885 true
886 }
887 }
888 }
889
890 fn emit_export_specifier(&mut self, specifier: &ExportSpecifier, keep_type: bool) {
891 if keep_type && matches!(specifier.mode, ExportSpecifierMode::TypeOnly) {
892 self.raw("type ");
893 }
894 if self.module_names_match(&specifier.local, &specifier.exported) {
895 self.emit_module_export_name(&specifier.local);
896 } else {
897 self.emit_module_export_name(&specifier.local);
898 self.raw(" as ");
899 self.emit_module_export_name(&specifier.exported);
900 }
901 }
902
903 fn js_statement_emits(&self, statement: &Stmt) -> bool {
904 match statement.data() {
905 Statement::Interface(_)
906 | Statement::TypeAlias(_)
907 | Statement::Declare(_)
908 | Statement::Namespace(_)
909 | Statement::Empty => false,
910 Statement::Function(function) => function.function.body.is_some(),
911 Statement::Import(import) => !import.type_only,
912 _ => true,
913 }
914 }
915
916 fn emit_enum_js(&mut self, declaration: &EnumDeclaration) -> bool {
921 let Some(name) = self
922 .text(declaration.name.data().token())
923 .map(str::to_owned)
924 else {
925 self.diag(
926 codes::UNRESOLVED_TOKEN,
927 "token text is not a valid slice of the source",
928 declaration.name.range(),
929 );
930 return false;
931 };
932 if name.is_empty() {
933 return false;
934 }
935
936 let members: Vec<String> = declaration
937 .members
938 .iter()
939 .filter_map(|member| match &member.data().name {
940 PropertyName::Identifier(ident) => {
941 self.text(ident.data().token()).map(str::to_owned)
942 }
943 _ => None,
944 })
945 .collect();
946
947 self.raw("var ");
948 self.raw(&name);
949 self.raw(";");
950 self.newline();
951 self.raw("(function (");
952 self.raw(&name);
953 self.raw(") {");
954 self.newline();
955 self.indent += 1;
956
957 self.enum_context = Some(EnumContext {
958 object: name.clone(),
959 members,
960 });
961 let mut auto: Option<i64> = Some(0);
962 for member in &declaration.members {
963 self.emit_enum_member(&name, member.data(), &mut auto);
964 self.newline();
965 }
966 self.enum_context = None;
967
968 self.indent -= 1;
969 self.raw("})(");
970 self.raw(&name);
971 self.raw(" || (");
972 self.raw(&name);
973 self.raw(" = {}));");
974 true
975 }
976
977 fn emit_enum_member(&mut self, object: &str, member: &EnumMember, auto: &mut Option<i64>) {
978 let Some(key) = self.enum_member_key(&member.name) else {
979 self.diag_here(
980 codes::MISSING_PROPERTY_NAME,
981 "cannot emit an enum member with this name",
982 );
983 return;
984 };
985
986 match &member.initializer {
987 None => match *auto {
988 Some(value) => {
989 self.raw(object);
990 self.raw("[");
991 self.raw(object);
992 self.raw("[");
993 self.raw(&key);
994 self.raw("] = ");
995 self.raw(&value.to_string());
996 self.raw("] = ");
997 self.raw(&key);
998 self.raw(";");
999 *auto = value.checked_add(1);
1000 }
1001 None => {
1002 self.diag_here(
1003 codes::ENUM_MEMBER_INITIALIZER,
1004 "enum member without initializer requires a constant predecessor",
1005 );
1006 self.raw(object);
1007 self.raw("[");
1008 self.raw(&key);
1009 self.raw("] = void 0;");
1010 }
1011 },
1012 Some(initializer) => {
1013 if let Some(value) = numeric_literal_value(initializer) {
1014 self.raw(object);
1015 self.raw("[");
1016 self.raw(object);
1017 self.raw("[");
1018 self.raw(&key);
1019 self.raw("] = ");
1020 self.emit_expression_prec(initializer, P_ASSIGN);
1021 self.raw("] = ");
1022 self.raw(&key);
1023 self.raw(";");
1024 *auto = value.and_then(|v| v.checked_add(1));
1025 } else {
1026 self.raw(object);
1027 self.raw("[");
1028 self.raw(&key);
1029 self.raw("] = ");
1030 self.emit_expression_prec(initializer, P_ASSIGN);
1031 self.raw(";");
1032 *auto = None;
1033 }
1034 }
1035 }
1036 }
1037
1038 fn enum_member_key(&self, name: &PropertyName) -> Option<String> {
1039 match name {
1040 PropertyName::Identifier(ident) => {
1041 self.text(ident.data().token()).map(|s| format!("\"{s}\""))
1042 }
1043 PropertyName::String(string) => self.text(string.data().token()).map(str::to_owned),
1044 PropertyName::Number(number) => {
1045 self.text(number.data().token()).map(|s| format!("\"{s}\""))
1046 }
1047 PropertyName::Private(_) | PropertyName::Computed(_) | PropertyName::Missing(_) => None,
1048 }
1049 }
1050
1051 fn emit_function_declaration_js(&mut self, function: &FunctionLike) {
1056 if function.is_async {
1057 self.raw("async ");
1058 }
1059 self.raw("function");
1060 if function.is_generator {
1061 self.raw("*");
1062 }
1063 if let Some(name) = &function.name {
1064 self.raw(" ");
1065 self.emit_ident(name);
1066 }
1067 self.emit_params_js(&function.parameters);
1068 self.raw(" ");
1069 self.emit_function_body_js(function.body.as_ref());
1070 }
1071
1072 fn emit_function_expression_js(&mut self, function: &FunctionLike) {
1073 if function.is_async {
1074 self.raw("async ");
1075 }
1076 self.raw("function");
1077 if function.is_generator {
1078 self.raw("*");
1079 }
1080 if let Some(name) = &function.name {
1081 self.raw(" ");
1082 self.emit_ident(name);
1083 }
1084 self.emit_params_js(&function.parameters);
1085 self.raw(" ");
1086 self.emit_function_body_js(function.body.as_ref());
1087 }
1088
1089 fn emit_arrow_js(&mut self, arrow: &ArrowFunction) {
1090 if arrow.is_async {
1091 self.raw("async ");
1092 }
1093 self.emit_params_js(&arrow.parameters);
1094 self.raw(" => ");
1095 match &arrow.body {
1096 FunctionBody::Block(block) => self.emit_block(block.data()),
1097 FunctionBody::Expression(expression) => {
1098 if self.leads_with_bad_token(expression, true) {
1099 self.raw("(");
1100 self.emit_expression_prec(expression, 0);
1101 self.raw(")");
1102 } else {
1103 self.emit_expression_prec(expression, P_ASSIGN);
1104 }
1105 }
1106 FunctionBody::Missing(_) => {
1107 self.diag_here(
1108 codes::MISSING_STATEMENT,
1109 "cannot emit a missing function body",
1110 );
1111 self.raw("{}");
1112 }
1113 }
1114 }
1115
1116 fn emit_function_body_js(&mut self, body: Option<&FunctionBody>) {
1117 match body {
1118 Some(FunctionBody::Block(block)) => self.emit_block(block.data()),
1119 Some(FunctionBody::Expression(expression)) => {
1120 self.raw("{ return ");
1121 self.emit_expression_prec(expression, 0);
1122 self.raw("; }");
1123 }
1124 Some(FunctionBody::Missing(_)) | None => {
1125 self.diag_here(
1126 codes::MISSING_STATEMENT,
1127 "cannot emit a missing function body",
1128 );
1129 self.raw("{}");
1130 }
1131 }
1132 }
1133
1134 fn emit_params_js(&mut self, parameters: &[ParameterNode]) {
1135 self.raw("(");
1136 let mut first = true;
1137 for parameter in parameters {
1138 let parameter = parameter.data();
1139 if self.is_this_parameter(parameter) {
1140 continue;
1141 }
1142 for decorator in ¶meter.decorators {
1143 self.emit_decorator_diag(decorator);
1144 }
1145 if !first {
1146 self.raw(", ");
1147 }
1148 first = false;
1149 self.emit_pattern(¶meter.binding);
1150 if let Some(initializer) = ¶meter.initializer {
1151 self.raw(" = ");
1152 self.emit_expression_prec(initializer, P_ASSIGN);
1153 }
1154 }
1155 self.raw(")");
1156 }
1157
1158 fn is_this_parameter(&self, parameter: &Parameter) -> bool {
1159 if let BindingPattern::Identifier(ident) = parameter.binding.data() {
1160 matches!(self.text(ident.data().token()), Some("this"))
1161 } else {
1162 false
1163 }
1164 }
1165
1166 fn emit_decorator_diag(&mut self, decorator: &DecoratorNode) {
1167 let range = decorator.range();
1168 self.diag(
1169 codes::DECORATOR_UNLOWERED,
1170 "decorator runtime lowering requires semantic analysis",
1171 range,
1172 );
1173 }
1174
1175 fn emit_class_js(&mut self, class: &ClassDeclaration) {
1176 self.emit_class_core_js(class);
1177 }
1178
1179 fn emit_class_core_js(&mut self, class: &ClassDeclaration) {
1180 for decorator in &class.decorators {
1181 self.emit_decorator_diag(decorator);
1182 }
1183 self.raw("class");
1184 if let Some(name) = &class.name {
1185 self.raw(" ");
1186 self.emit_ident(name);
1187 }
1188 if let Some(heritage) = &class.extends {
1189 self.raw(" extends ");
1190 self.emit_expression_prec(&heritage.expression, P_CALL_MEMBER);
1191 }
1192 self.raw(" ");
1193 self.emit_class_body_js(&class.members);
1194 }
1195
1196 fn emit_class_body_js(&mut self, members: &[ClassMemberNode]) {
1197 self.raw("{");
1198 let has = members
1199 .iter()
1200 .any(|member| self.class_member_emits_js(member.data()));
1201 if has {
1202 self.newline();
1203 self.indent += 1;
1204 }
1205 for member in members {
1206 if self.emit_class_member_js(member.data()) {
1207 self.newline();
1208 }
1209 }
1210 if has {
1211 self.indent -= 1;
1212 }
1213 self.raw("}");
1214 }
1215
1216 fn class_member_emits_js(&self, member: &ClassMember) -> bool {
1217 match member {
1218 ClassMember::Constructor(_) | ClassMember::StaticBlock(_) => true,
1219 ClassMember::Method(method) => {
1220 method.function.body.is_some() && !method.modifiers.is_abstract
1221 }
1222 ClassMember::Property(property) => {
1223 !property.modifiers.is_abstract && !property.modifiers.is_declare
1224 }
1225 ClassMember::AutoAccessor(accessor) => {
1226 !accessor.modifiers.is_abstract && !accessor.modifiers.is_declare
1227 }
1228 ClassMember::IndexSignature(_) | ClassMember::Missing(_) => false,
1229 }
1230 }
1231
1232 fn emit_class_member_js(&mut self, member: &ClassMember) -> bool {
1233 match member {
1234 ClassMember::Constructor(constructor) => {
1235 self.emit_constructor_js(constructor);
1236 true
1237 }
1238 ClassMember::Method(method) => {
1239 if method.function.body.is_none() || method.modifiers.is_abstract {
1240 return false;
1241 }
1242 self.emit_method_js(method);
1243 true
1244 }
1245 ClassMember::Property(property) => {
1246 if property.modifiers.is_abstract || property.modifiers.is_declare {
1247 return false;
1248 }
1249 if property.modifiers.is_static {
1250 self.raw("static ");
1251 }
1252 self.emit_property_name(&property.name);
1253 if let Some(initializer) = &property.initializer {
1254 self.raw(" = ");
1255 self.emit_expression_prec(initializer, P_ASSIGN);
1256 }
1257 self.raw(";");
1258 true
1259 }
1260 ClassMember::AutoAccessor(accessor) => {
1261 if accessor.modifiers.is_abstract || accessor.modifiers.is_declare {
1262 return false;
1263 }
1264 if accessor.modifiers.is_static {
1265 self.raw("static ");
1266 }
1267 self.raw("accessor ");
1268 self.emit_property_name(&accessor.name);
1269 if let Some(initializer) = &accessor.initializer {
1270 self.raw(" = ");
1271 self.emit_expression_prec(initializer, P_ASSIGN);
1272 }
1273 self.raw(";");
1274 true
1275 }
1276 ClassMember::StaticBlock(block) => {
1277 self.raw("static ");
1278 self.emit_block(block.data());
1279 true
1280 }
1281 ClassMember::IndexSignature(_) => false,
1282 ClassMember::Missing(_) => {
1283 self.diag_here(codes::MISSING_MEMBER, "cannot emit a missing class member");
1284 false
1285 }
1286 }
1287 }
1288
1289 fn emit_method_js(&mut self, method: &MethodDeclaration) {
1290 if method.modifiers.is_static {
1291 self.raw("static ");
1292 }
1293 match method.modifier {
1294 PropertyModifier::Get => self.raw("get "),
1295 PropertyModifier::Set => self.raw("set "),
1296 PropertyModifier::None => {
1297 if method.function.is_async {
1298 self.raw("async ");
1299 }
1300 if method.function.is_generator {
1301 self.raw("*");
1302 }
1303 }
1304 }
1305 self.emit_property_name(&method.name);
1306 self.emit_params_js(&method.function.parameters);
1307 self.raw(" ");
1308 self.emit_function_body_js(method.function.body.as_ref());
1309 }
1310
1311 fn emit_constructor_js(&mut self, constructor: &ConstructorDeclaration) {
1312 self.raw("constructor");
1313 self.emit_params_js(&constructor.parameters);
1314 self.raw(" ");
1315
1316 let injections: Vec<&ParameterNode> = constructor
1317 .parameters
1318 .iter()
1319 .filter(|parameter| is_parameter_property(parameter.data()))
1320 .collect();
1321 let body = constructor.body.data();
1322 if injections.is_empty() && body.statements.is_empty() {
1323 self.raw("{}");
1324 return;
1325 }
1326 self.raw("{");
1327 self.newline();
1328 self.indent += 1;
1329 for parameter in injections {
1330 if let BindingPattern::Identifier(name) = parameter.data().binding.data() {
1331 self.raw("this.");
1332 self.emit_ident(name);
1333 self.raw(" = ");
1334 self.emit_ident(name);
1335 self.raw(";");
1336 self.newline();
1337 } else {
1338 self.diag(
1339 codes::MISSING_TARGET,
1340 "parameter property must bind a plain identifier",
1341 parameter.range(),
1342 );
1343 }
1344 }
1345 for statement in &body.statements {
1346 if self.emit_statement(statement) {
1347 self.newline();
1348 }
1349 }
1350 self.indent -= 1;
1351 self.raw("}");
1352 }
1353
1354 fn emit_expression(&mut self, expression: &Expr) {
1359 self.emit_expression_prec(expression, 0);
1360 }
1361
1362 fn emit_expression_prec(&mut self, expression: &Expr, min_prec: u8) {
1363 let previous = self.anchor;
1364 self.anchor = expression.range();
1365 let prec = self.expression_prec(expression);
1366 let parenthesize = prec < min_prec;
1367 if parenthesize {
1368 self.raw("(");
1369 }
1370 self.emit_expression_inner(expression);
1371 if parenthesize {
1372 self.raw(")");
1373 }
1374 self.anchor = previous;
1375 }
1376
1377 fn expression_prec(&self, expression: &Expr) -> u8 {
1378 match expression.data() {
1379 Expression::Sequence(_) => P_SEQUENCE,
1380 Expression::Assignment(_) | Expression::Arrow(_) | Expression::Yield(_) => P_ASSIGN,
1381 Expression::Conditional(_) => P_CONDITIONAL,
1382 Expression::Logical(logical) => match logical.operator {
1383 LogicalOperator::And => P_LOGICAL_AND,
1384 LogicalOperator::Or => P_LOGICAL_OR,
1385 LogicalOperator::Nullish => P_NULLISH,
1386 },
1387 Expression::Binary(binary) => binary_prec(binary.operator),
1388 Expression::Unary(_) | Expression::Await(_) => P_UNARY,
1389 Expression::Update(update) => {
1390 if update.prefix {
1391 P_UNARY
1392 } else {
1393 P_POSTFIX
1394 }
1395 }
1396 Expression::Call(_)
1397 | Expression::New(_)
1398 | Expression::Member(_)
1399 | Expression::TaggedTemplate(_)
1400 | Expression::Import(_) => P_CALL_MEMBER,
1401 Expression::Parenthesized(inner) => self.expression_prec(inner),
1402 Expression::As(as_expr) => self.expression_prec(&as_expr.expression),
1403 Expression::Satisfies(satisfies) => self.expression_prec(&satisfies.expression),
1404 Expression::TypeAssertion(assertion) => self.expression_prec(&assertion.expression),
1405 Expression::NonNull(non_null) => self.expression_prec(&non_null.expression),
1406 _ => P_PRIMARY,
1407 }
1408 }
1409
1410 fn emit_expression_inner(&mut self, expression: &Expr) {
1411 match expression.data() {
1412 Expression::Identifier(ident) => self.emit_ident_expression(ident),
1413 Expression::This => self.raw("this"),
1414 Expression::Super => self.raw("super"),
1415 Expression::Literal(literal) => self.emit_literal(literal),
1416 Expression::Template(template) => self.emit_template(template),
1417 Expression::TaggedTemplate(tagged) => {
1418 self.emit_expression_prec(&tagged.tag, P_CALL_MEMBER);
1419 self.emit_template(&tagged.template);
1420 }
1421 Expression::Array(array) => self.emit_array(array),
1422 Expression::Object(object) => self.emit_object(object),
1423 Expression::Function(function) => self.emit_function_expression_js(&function.function),
1424 Expression::Class(class) => self.emit_class_core_js(&class.class),
1425 Expression::Arrow(arrow) => self.emit_arrow_js(arrow),
1426 Expression::Call(call) => self.emit_call(call),
1427 Expression::Member(member) => self.emit_member(member),
1428 Expression::New(new) => self.emit_new(new),
1429 Expression::Await(await_expr) => {
1430 self.raw("await ");
1431 self.emit_expression_prec(&await_expr.argument, P_UNARY);
1432 }
1433 Expression::Yield(yield_expr) => self.emit_yield(yield_expr),
1434 Expression::Unary(unary) => self.emit_unary(unary),
1435 Expression::Update(update) => self.emit_update(update),
1436 Expression::Binary(binary) => self.emit_binary(binary),
1437 Expression::Logical(logical) => self.emit_logical(logical),
1438 Expression::Conditional(conditional) => self.emit_conditional(conditional),
1439 Expression::Assignment(assignment) => self.emit_assignment(assignment),
1440 Expression::Sequence(sequence) => self.emit_sequence(sequence),
1441 Expression::Parenthesized(inner) => self.emit_expression_prec(inner, 0),
1442 Expression::As(as_expr) => self.emit_expression_prec(&as_expr.expression, 0),
1443 Expression::Satisfies(satisfies) => {
1444 self.emit_expression_prec(&satisfies.expression, 0);
1445 }
1446 Expression::TypeAssertion(assertion) => {
1447 self.emit_expression_prec(&assertion.expression, 0);
1448 }
1449 Expression::NonNull(non_null) => self.emit_expression_prec(&non_null.expression, 0),
1450 Expression::Import(import) => {
1451 self.raw("import(");
1452 self.emit_expression_prec(&import.source, P_ASSIGN);
1453 if let Some(options) = &import.options {
1454 self.raw(", ");
1455 self.emit_expression_prec(options, P_ASSIGN);
1456 }
1457 self.raw(")");
1458 }
1459 Expression::Meta(meta) => match meta {
1460 MetaProperty::NewTarget => self.raw("new.target"),
1461 MetaProperty::ImportMeta => self.raw("import.meta"),
1462 },
1463 Expression::Missing(_) => {
1464 self.diag_here(
1465 codes::MISSING_EXPRESSION,
1466 "cannot emit a missing expression node",
1467 );
1468 self.raw("void 0");
1469 }
1470 }
1471 }
1472
1473 fn emit_ident_expression(&mut self, ident: &IdentifierNode) {
1474 let Some(text) = self.text(ident.data().token()) else {
1475 let range = ident.range();
1476 self.diag(
1477 codes::UNRESOLVED_TOKEN,
1478 "token text is not a valid slice of the source",
1479 range,
1480 );
1481 return;
1482 };
1483 let qualified = self
1484 .enum_context
1485 .as_ref()
1486 .filter(|context| context.members.iter().any(|member| member == text))
1487 .map(|context| context.object.clone());
1488 if let Some(object) = qualified {
1489 self.raw(&object);
1490 self.raw(".");
1491 }
1492 self.raw(text);
1493 }
1494
1495 fn emit_literal(&mut self, literal: &Literal) {
1496 match literal {
1497 Literal::String(node) => self.emit_token(node.data().token()),
1498 Literal::Number(node) => self.emit_token(node.data().token()),
1499 Literal::BigInt(node) => self.emit_token(node.data().token()),
1500 Literal::Boolean(node) => self.emit_token(node.data().token()),
1501 Literal::Null(node) => match self.text(node.data().token()) {
1502 Some(text) if !text.is_empty() => self.raw(text),
1503 _ => self.raw("null"),
1504 },
1505 Literal::Regex(node) => self.emit_token(node.data().token()),
1506 }
1507 }
1508
1509 fn emit_template(&mut self, template: &TemplateLiteral) {
1510 if template.elements.is_empty() {
1511 return;
1512 }
1513 self.emit_token(template.elements[0].data().token());
1514 for (index, expression) in template.expressions.iter().enumerate() {
1515 self.emit_expression_prec(expression, 0);
1516 if let Some(element) = template.elements.get(index + 1) {
1517 self.emit_token(element.data().token());
1518 }
1519 }
1520 }
1521
1522 fn emit_array(&mut self, array: &ArrayLiteral) {
1523 self.raw("[");
1524 let elements = &array.elements;
1525 for (index, element) in elements.iter().enumerate() {
1526 if index > 0 {
1527 self.raw(", ");
1528 }
1529 match element {
1530 ArrayElement::Expression(expression) => {
1531 self.emit_expression_prec(expression, P_ASSIGN);
1532 }
1533 ArrayElement::Spread(spread) => {
1534 self.raw("...");
1535 self.emit_expression_prec(&spread.argument, P_ASSIGN);
1536 }
1537 ArrayElement::Elision => {}
1538 ArrayElement::Missing(_) => {
1539 self.diag_here(
1540 codes::MISSING_ELEMENT,
1541 "cannot emit a missing array element",
1542 );
1543 }
1544 }
1545 }
1546 if matches!(elements.last(), Some(ArrayElement::Elision)) {
1547 self.raw(",");
1548 }
1549 self.raw("]");
1550 }
1551
1552 fn emit_object(&mut self, object: &ObjectLiteral) {
1553 if object.members.is_empty() {
1554 self.raw("{}");
1555 return;
1556 }
1557 self.raw("{");
1558 self.newline();
1559 self.indent += 1;
1560 let count = object.members.len();
1561 for (index, member) in object.members.iter().enumerate() {
1562 self.emit_object_member(member.data());
1563 if index + 1 < count {
1564 self.raw(",");
1565 }
1566 self.newline();
1567 }
1568 self.indent -= 1;
1569 self.raw("}");
1570 }
1571
1572 fn emit_object_member(&mut self, member: &ObjectMember) {
1573 match member {
1574 ObjectMember::Property(property) => {
1575 if property.shorthand && matches!(property.name, PropertyName::Identifier(_)) {
1576 self.emit_property_name(&property.name);
1577 } else {
1578 self.emit_property_name(&property.name);
1579 self.raw(": ");
1580 self.emit_expression_prec(&property.value, P_ASSIGN);
1581 }
1582 }
1583 ObjectMember::Method(method) => self.emit_object_method(method),
1584 ObjectMember::Spread(spread) => {
1585 self.raw("...");
1586 self.emit_expression_prec(&spread.argument, P_ASSIGN);
1587 }
1588 ObjectMember::Missing(_) => {
1589 self.diag_here(codes::MISSING_MEMBER, "cannot emit a missing object member");
1590 }
1591 }
1592 }
1593
1594 fn emit_object_method(&mut self, method: &ObjectMethod) {
1595 match method.modifier {
1596 PropertyModifier::Get => self.raw("get "),
1597 PropertyModifier::Set => self.raw("set "),
1598 PropertyModifier::None => {
1599 if method.function.is_async {
1600 self.raw("async ");
1601 }
1602 if method.function.is_generator {
1603 self.raw("*");
1604 }
1605 }
1606 }
1607 self.emit_property_name(&method.name);
1608 self.emit_params_js(&method.function.parameters);
1609 self.raw(" ");
1610 self.emit_function_body_js(method.function.body.as_ref());
1611 }
1612
1613 fn emit_property_name(&mut self, name: &PropertyName) {
1614 match name {
1615 PropertyName::Identifier(ident) => self.emit_ident(ident),
1616 PropertyName::Private(private) => self.emit_token(private.data().token()),
1617 PropertyName::String(string) => self.emit_string(string),
1618 PropertyName::Number(number) => self.emit_token(number.data().token()),
1619 PropertyName::Computed(expression) => {
1620 self.raw("[");
1621 self.emit_expression_prec(expression, P_ASSIGN);
1622 self.raw("]");
1623 }
1624 PropertyName::Missing(_) => {
1625 self.diag_here(
1626 codes::MISSING_PROPERTY_NAME,
1627 "cannot emit a missing property name",
1628 );
1629 }
1630 }
1631 }
1632
1633 fn emit_call(&mut self, call: &CallExpression) {
1634 self.emit_expression_prec(&call.callee, P_CALL_MEMBER);
1635 if call.optional {
1636 self.raw("?.(");
1637 } else {
1638 self.raw("(");
1639 }
1640 self.emit_arguments(&call.arguments);
1641 self.raw(")");
1642 }
1643
1644 fn emit_new(&mut self, new: &NewExpression) {
1645 self.raw("new ");
1646 let callee = self.unwrap_expression(&new.callee);
1647 let wrap = matches!(callee.data(), Expression::Call(_)) || self.chain_has_optional(callee);
1648 if wrap {
1649 self.raw("(");
1650 self.emit_expression_prec(callee, 0);
1651 self.raw(")");
1652 } else {
1653 self.emit_expression_prec(callee, P_CALL_MEMBER);
1654 }
1655 self.raw("(");
1656 self.emit_arguments(&new.arguments);
1657 self.raw(")");
1658 }
1659
1660 fn emit_arguments(&mut self, arguments: &[CallArgument]) {
1661 for (index, argument) in arguments.iter().enumerate() {
1662 if index > 0 {
1663 self.raw(", ");
1664 }
1665 match argument {
1666 CallArgument::Expression(expression) => {
1667 self.emit_expression_prec(expression, P_ASSIGN);
1668 }
1669 CallArgument::Spread(spread) => {
1670 self.raw("...");
1671 self.emit_expression_prec(&spread.argument, P_ASSIGN);
1672 }
1673 CallArgument::Missing(_) => {
1674 self.diag_here(
1675 codes::MISSING_ELEMENT,
1676 "cannot emit a missing call argument",
1677 );
1678 }
1679 }
1680 }
1681 }
1682
1683 fn emit_member(&mut self, member: &MemberExpression) {
1684 let dotted = !matches!(member.property, MemberProperty::Computed(_));
1685 let numeric_object = dotted
1686 && matches!(
1687 self.unwrap_expression(&member.object).data(),
1688 Expression::Literal(Literal::Number(_))
1689 );
1690 if numeric_object {
1691 self.raw("(");
1692 self.emit_expression_prec(&member.object, 0);
1693 self.raw(")");
1694 } else {
1695 self.emit_expression_prec(&member.object, P_CALL_MEMBER);
1696 }
1697 match &member.property {
1698 MemberProperty::Named(name) => {
1699 self.raw(if member.optional { "?." } else { "." });
1700 self.emit_ident(name);
1701 }
1702 MemberProperty::Private(private) => {
1703 self.raw(if member.optional { "?." } else { "." });
1704 self.emit_token(private.data().token());
1705 }
1706 MemberProperty::Computed(expression) => {
1707 self.raw(if member.optional { "?.[" } else { "[" });
1708 self.emit_expression_prec(expression, 0);
1709 self.raw("]");
1710 }
1711 }
1712 }
1713
1714 fn emit_yield(&mut self, expression: &YieldExpression) {
1715 self.raw("yield");
1716 if expression.delegate {
1717 self.raw("*");
1718 }
1719 if let Some(argument) = &expression.argument {
1720 self.raw(" ");
1721 self.emit_expression_prec(argument, P_ASSIGN);
1722 }
1723 }
1724
1725 fn emit_unary(&mut self, unary: &UnaryExpression) {
1726 match unary.operator {
1727 UnaryOperator::Typeof => self.raw("typeof "),
1728 UnaryOperator::Void => self.raw("void "),
1729 UnaryOperator::Delete => self.raw("delete "),
1730 UnaryOperator::Plus => self.raw("+"),
1731 UnaryOperator::Minus => self.raw("-"),
1732 UnaryOperator::Not => self.raw("!"),
1733 UnaryOperator::BitNot => self.raw("~"),
1734 }
1735 if matches!(unary.operator, UnaryOperator::Plus | UnaryOperator::Minus)
1736 && self.needs_unary_space(&unary.argument)
1737 {
1738 self.raw(" ");
1739 }
1740 self.emit_expression_prec(&unary.argument, P_UNARY);
1741 }
1742
1743 fn needs_unary_space(&self, argument: &Expr) -> bool {
1744 match self.unwrap_expression(argument).data() {
1745 Expression::Unary(inner) => {
1746 matches!(inner.operator, UnaryOperator::Plus | UnaryOperator::Minus)
1747 }
1748 Expression::Update(inner) => inner.prefix,
1749 _ => false,
1750 }
1751 }
1752
1753 fn emit_update(&mut self, update: &UpdateExpression) {
1754 let operator = match update.operator {
1755 UpdateOperator::Increment => "++",
1756 UpdateOperator::Decrement => "--",
1757 };
1758 if update.prefix {
1759 self.raw(operator);
1760 self.emit_assignment_target(&update.argument);
1761 } else {
1762 self.emit_assignment_target(&update.argument);
1763 self.raw(operator);
1764 }
1765 }
1766
1767 fn emit_binary(&mut self, binary: &BinaryExpression) {
1768 let prec = binary_prec(binary.operator);
1769 if matches!(binary.operator, BinaryOperator::Exponentiate) {
1770 let left = self.unwrap_expression(&binary.left);
1771 if matches!(left.data(), Expression::Unary(_) | Expression::Await(_))
1772 || matches!(left.data(), Expression::Update(update) if update.prefix)
1773 {
1774 self.raw("(");
1775 self.emit_expression_prec(left, 0);
1776 self.raw(")");
1777 } else {
1778 self.emit_expression_prec(&binary.left, P_EXPONENT + 1);
1779 }
1780 self.raw(" ** ");
1781 self.emit_expression_prec(&binary.right, P_EXPONENT);
1782 } else {
1783 self.emit_expression_prec(&binary.left, prec);
1784 self.raw(" ");
1785 self.raw(binary_str(binary.operator));
1786 self.raw(" ");
1787 self.emit_expression_prec(&binary.right, prec + 1);
1788 }
1789 }
1790
1791 fn emit_logical(&mut self, logical: &LogicalExpression) {
1792 let prec = match logical.operator {
1793 LogicalOperator::And => P_LOGICAL_AND,
1794 LogicalOperator::Or => P_LOGICAL_OR,
1795 LogicalOperator::Nullish => P_NULLISH,
1796 };
1797 self.emit_logical_operand(&logical.left, logical.operator, prec, true);
1798 self.raw(" ");
1799 self.raw(logical_str(logical.operator));
1800 self.raw(" ");
1801 self.emit_logical_operand(&logical.right, logical.operator, prec, false);
1802 }
1803
1804 fn emit_logical_operand(
1805 &mut self,
1806 operand: &Expr,
1807 parent: LogicalOperator,
1808 prec: u8,
1809 is_left: bool,
1810 ) {
1811 if self.coalesce_mix(parent, operand) {
1812 self.raw("(");
1813 self.emit_expression_prec(operand, 0);
1814 self.raw(")");
1815 return;
1816 }
1817 let min_prec = if is_left { prec } else { prec + 1 };
1818 self.emit_expression_prec(operand, min_prec);
1819 }
1820
1821 fn coalesce_mix(&self, parent: LogicalOperator, operand: &Expr) -> bool {
1822 if let Expression::Logical(child) = self.unwrap_expression(operand).data() {
1823 let parent_nullish = matches!(parent, LogicalOperator::Nullish);
1824 let child_nullish = matches!(child.operator, LogicalOperator::Nullish);
1825 parent_nullish != child_nullish
1826 } else {
1827 false
1828 }
1829 }
1830
1831 fn emit_conditional(&mut self, conditional: &ConditionalExpression) {
1832 self.emit_expression_prec(&conditional.test, P_CONDITIONAL + 1);
1833 self.raw(" ? ");
1834 self.emit_expression_prec(&conditional.consequent, P_ASSIGN);
1835 self.raw(" : ");
1836 self.emit_expression_prec(&conditional.alternate, P_ASSIGN);
1837 }
1838
1839 fn emit_assignment(&mut self, assignment: &AssignmentExpression) {
1840 self.emit_assignment_target(&assignment.left);
1841 self.raw(" ");
1842 self.raw(assignment_str(assignment.operator));
1843 self.raw(" ");
1844 self.emit_expression_prec(&assignment.right, P_ASSIGN);
1845 }
1846
1847 fn emit_sequence(&mut self, sequence: &SequenceExpression) {
1848 for (index, expression) in sequence.expressions.iter().enumerate() {
1849 if index > 0 {
1850 self.raw(", ");
1851 }
1852 self.emit_expression_prec(expression, P_ASSIGN);
1853 }
1854 }
1855
1856 fn emit_assignment_target(&mut self, target: &AssignmentTargetNode) {
1859 match target.data() {
1860 AssignmentTarget::Identifier(ident) => self.emit_ident(ident),
1861 AssignmentTarget::Member(member) => {
1862 let dotted = !matches!(member.property, MemberProperty::Computed(_));
1863 let numeric_object = dotted
1864 && matches!(
1865 self.unwrap_expression(&member.object).data(),
1866 Expression::Literal(Literal::Number(_))
1867 );
1868 if numeric_object {
1869 self.raw("(");
1870 self.emit_expression_prec(&member.object, 0);
1871 self.raw(")");
1872 } else {
1873 self.emit_expression_prec(&member.object, P_CALL_MEMBER);
1874 }
1875 match &member.property {
1876 MemberProperty::Named(name) => {
1877 self.raw(".");
1878 self.emit_ident(name);
1879 }
1880 MemberProperty::Private(private) => {
1881 self.raw(".");
1882 self.emit_token(private.data().token());
1883 }
1884 MemberProperty::Computed(expression) => {
1885 self.raw("[");
1886 self.emit_expression_prec(expression, 0);
1887 self.raw("]");
1888 }
1889 }
1890 }
1891 AssignmentTarget::Object(pattern) => {
1892 self.raw("{");
1893 for (index, property) in pattern.properties.iter().enumerate() {
1894 if index > 0 {
1895 self.raw(", ");
1896 } else {
1897 self.raw(" ");
1898 }
1899 self.emit_assignment_object_property(property);
1900 }
1901 if pattern.properties.is_empty() {
1902 self.raw("}");
1903 } else {
1904 self.raw(" }");
1905 }
1906 }
1907 AssignmentTarget::Array(pattern) => {
1908 self.raw("[");
1909 for (index, element) in pattern.elements.iter().enumerate() {
1910 if index > 0 {
1911 self.raw(", ");
1912 }
1913 match element {
1914 AssignmentArrayElement::Target(target) => {
1915 self.emit_assignment_target(target)
1916 }
1917 AssignmentArrayElement::Elision => {}
1918 AssignmentArrayElement::Missing(_) => {
1919 self.diag_here(codes::MISSING_TARGET, "cannot emit a missing target");
1920 }
1921 }
1922 }
1923 if matches!(
1924 pattern.elements.last(),
1925 Some(AssignmentArrayElement::Elision)
1926 ) {
1927 self.raw(",");
1928 }
1929 self.raw("]");
1930 }
1931 AssignmentTarget::Missing(_) => {
1932 self.diag_here(
1933 codes::MISSING_TARGET,
1934 "cannot emit a missing assignment target",
1935 );
1936 }
1937 }
1938 }
1939
1940 fn emit_assignment_object_property(&mut self, property: &AssignmentObjectProperty) {
1941 let shorthand = property.initializer.is_none()
1942 && self.target_matches_name(&property.name, &property.target);
1943 if shorthand {
1944 self.emit_property_name(&property.name);
1945 } else {
1946 self.emit_property_name(&property.name);
1947 self.raw(": ");
1948 self.emit_assignment_target(&property.target);
1949 }
1950 if let Some(initializer) = &property.initializer {
1951 self.raw(" = ");
1952 self.emit_expression_prec(initializer, P_ASSIGN);
1953 }
1954 }
1955
1956 fn emit_pattern(&mut self, pattern: &Pattern) {
1957 match pattern.data() {
1958 BindingPattern::Identifier(ident) => self.emit_ident(ident),
1959 BindingPattern::Object(object) => {
1960 if object.properties.is_empty() {
1961 self.raw("{}");
1962 return;
1963 }
1964 self.raw("{ ");
1965 for (index, property) in object.properties.iter().enumerate() {
1966 if index > 0 {
1967 self.raw(", ");
1968 }
1969 self.emit_object_binding_property(property);
1970 }
1971 self.raw(" }");
1972 }
1973 BindingPattern::Array(array) => {
1974 self.raw("[");
1975 for (index, element) in array.elements.iter().enumerate() {
1976 if index > 0 {
1977 self.raw(", ");
1978 }
1979 match element {
1980 ArrayBindingElement::Binding(binding) => self.emit_pattern(binding),
1981 ArrayBindingElement::Elision => {}
1982 ArrayBindingElement::Missing(_) => {
1983 self.diag_here(codes::MISSING_BINDING, "cannot emit a missing binding");
1984 }
1985 }
1986 }
1987 if matches!(array.elements.last(), Some(ArrayBindingElement::Elision)) {
1988 self.raw(",");
1989 }
1990 self.raw("]");
1991 }
1992 BindingPattern::Rest(rest) => {
1993 self.raw("...");
1994 self.emit_pattern(&rest.argument);
1995 }
1996 BindingPattern::Assignment(assignment) => {
1997 self.emit_pattern(&assignment.left);
1998 self.raw(" = ");
1999 self.emit_expression_prec(&assignment.right, P_ASSIGN);
2000 }
2001 BindingPattern::Missing(_) => {
2002 self.diag_here(
2003 codes::MISSING_BINDING,
2004 "cannot emit a missing binding pattern",
2005 );
2006 }
2007 }
2008 }
2009
2010 fn emit_object_binding_property(&mut self, property: &ObjectBindingProperty) {
2011 if let BindingPattern::Rest(rest) = property.binding.data() {
2012 self.raw("...");
2013 self.emit_pattern(&rest.argument);
2014 return;
2015 }
2016 let shorthand = self.binding_matches_name(&property.name, &property.binding);
2017 if shorthand {
2018 self.emit_property_name(&property.name);
2019 } else {
2020 self.emit_property_name(&property.name);
2021 self.raw(": ");
2022 self.emit_pattern(&property.binding);
2023 }
2024 if let Some(initializer) = &property.initializer {
2025 self.raw(" = ");
2026 self.emit_expression_prec(initializer, P_ASSIGN);
2027 }
2028 }
2029
2030 fn module_name_matches_ident(&self, name: &ModuleExportName, ident: &IdentifierNode) -> bool {
2033 match name {
2034 ModuleExportName::Identifier(imported) => self.same_ident_text(imported, ident),
2035 _ => false,
2036 }
2037 }
2038
2039 fn module_names_match(&self, left: &ModuleExportName, right: &ModuleExportName) -> bool {
2040 match (left, right) {
2041 (ModuleExportName::Identifier(a), ModuleExportName::Identifier(b)) => {
2042 self.same_ident_text(a, b)
2043 }
2044 _ => false,
2045 }
2046 }
2047
2048 fn target_matches_name(&self, name: &PropertyName, target: &AssignmentTargetNode) -> bool {
2049 if let (PropertyName::Identifier(a), AssignmentTarget::Identifier(b)) =
2050 (name, target.data())
2051 {
2052 self.same_ident_text(a, b)
2053 } else {
2054 false
2055 }
2056 }
2057
2058 fn binding_matches_name(&self, name: &PropertyName, binding: &Pattern) -> bool {
2059 if let (PropertyName::Identifier(a), BindingPattern::Identifier(b)) = (name, binding.data())
2060 {
2061 self.same_ident_text(a, b)
2062 } else {
2063 false
2064 }
2065 }
2066
2067 fn same_ident_text(&self, left: &IdentifierNode, right: &IdentifierNode) -> bool {
2068 match (
2069 self.text(left.data().token()),
2070 self.text(right.data().token()),
2071 ) {
2072 (Some(a), Some(b)) => a == b,
2073 _ => false,
2074 }
2075 }
2076
2077 fn emit_module_export_name(&mut self, name: &ModuleExportName) {
2078 match name {
2079 ModuleExportName::Identifier(ident) => self.emit_ident(ident),
2080 ModuleExportName::String(string) => self.emit_string(string),
2081 ModuleExportName::Missing(_) => {
2082 self.diag_here(
2083 codes::MISSING_NAME,
2084 "cannot emit a missing module export name",
2085 );
2086 }
2087 }
2088 }
2089
2090 fn emit_entity_name(&mut self, name: &EntityName) {
2091 match name {
2092 EntityName::Identifier(ident) => self.emit_ident(ident),
2093 EntityName::Qualified { left, right } => {
2094 self.emit_entity_name(left);
2095 self.raw(".");
2096 self.emit_ident(right);
2097 }
2098 EntityName::Missing(_) => {
2099 self.diag_here(codes::MISSING_NAME, "cannot emit a missing entity name");
2100 }
2101 }
2102 }
2103
2104 fn unwrap_expression<'e>(&self, expression: &'e Expr) -> &'e Expr {
2107 match expression.data() {
2108 Expression::Parenthesized(inner) => self.unwrap_expression(inner),
2109 Expression::As(as_expr) => self.unwrap_expression(&as_expr.expression),
2110 Expression::Satisfies(satisfies) => self.unwrap_expression(&satisfies.expression),
2111 Expression::TypeAssertion(assertion) => self.unwrap_expression(&assertion.expression),
2112 Expression::NonNull(non_null) => self.unwrap_expression(&non_null.expression),
2113 _ => expression,
2114 }
2115 }
2116
2117 fn chain_has_optional(&self, expression: &Expr) -> bool {
2118 match expression.data() {
2119 Expression::Member(member) => {
2120 member.optional || self.chain_has_optional(&member.object)
2121 }
2122 Expression::Call(call) => call.optional || self.chain_has_optional(&call.callee),
2123 Expression::NonNull(non_null) => self.chain_has_optional(&non_null.expression),
2124 Expression::Parenthesized(inner) => self.chain_has_optional(inner),
2125 Expression::As(as_expr) => self.chain_has_optional(&as_expr.expression),
2126 Expression::Satisfies(satisfies) => self.chain_has_optional(&satisfies.expression),
2127 Expression::TypeAssertion(assertion) => self.chain_has_optional(&assertion.expression),
2128 _ => false,
2129 }
2130 }
2131
2132 fn leads_with_bad_token(&self, expression: &Expr, objects_only: bool) -> bool {
2135 match expression.data() {
2136 Expression::Object(_) => true,
2137 Expression::Function(_) | Expression::Class(_) => !objects_only,
2138 Expression::Binary(binary) => self.leads_with_bad_token(&binary.left, objects_only),
2139 Expression::Logical(logical) => self.leads_with_bad_token(&logical.left, objects_only),
2140 Expression::Conditional(conditional) => {
2141 self.leads_with_bad_token(&conditional.test, objects_only)
2142 }
2143 Expression::Assignment(assignment) => self.target_leads_with_object(&assignment.left),
2144 Expression::Sequence(sequence) => sequence
2145 .expressions
2146 .first()
2147 .is_some_and(|first| self.leads_with_bad_token(first, objects_only)),
2148 Expression::Call(call) => self.leads_with_bad_token(&call.callee, objects_only),
2149 Expression::Member(member) => self.leads_with_bad_token(&member.object, objects_only),
2150 Expression::TaggedTemplate(tagged) => {
2151 self.leads_with_bad_token(&tagged.tag, objects_only)
2152 }
2153 Expression::Update(update) => {
2154 !update.prefix && self.target_leads_with_object(&update.argument)
2155 }
2156 Expression::NonNull(non_null) => {
2157 self.leads_with_bad_token(&non_null.expression, objects_only)
2158 }
2159 Expression::As(as_expr) => self.leads_with_bad_token(&as_expr.expression, objects_only),
2160 Expression::Satisfies(satisfies) => {
2161 self.leads_with_bad_token(&satisfies.expression, objects_only)
2162 }
2163 Expression::TypeAssertion(assertion) => {
2164 self.leads_with_bad_token(&assertion.expression, objects_only)
2165 }
2166 Expression::Parenthesized(inner) => self.leads_with_bad_token(inner, objects_only),
2167 _ => false,
2168 }
2169 }
2170
2171 fn target_leads_with_object(&self, target: &AssignmentTargetNode) -> bool {
2172 match target.data() {
2173 AssignmentTarget::Object(_) => true,
2174 AssignmentTarget::Member(member) => self.leads_with_bad_token(&member.object, false),
2175 _ => false,
2176 }
2177 }
2178
2179 fn emit_declaration(&mut self, statement: &Stmt) -> bool {
2184 let previous = self.anchor;
2185 self.anchor = statement.range();
2186 let emitted = match statement.data() {
2187 Statement::Import(import) => self.emit_import(import, true),
2188 Statement::ImportEquals(import) => {
2189 self.emit_import_equals_decl(import);
2190 true
2191 }
2192 Statement::Export(export) => self.emit_export_decl(export),
2193 Statement::Variable(declaration) => {
2194 self.emit_variable_decl(declaration);
2195 true
2196 }
2197 Statement::Function(function) => {
2198 self.emit_declare_prefix();
2199 self.emit_function_signature_decl(&function.function);
2200 true
2201 }
2202 Statement::Class(class) => {
2203 self.emit_declare_prefix();
2204 self.emit_class_core_decl(class);
2205 true
2206 }
2207 Statement::Interface(interface) => {
2208 self.emit_interface_decl(interface);
2209 true
2210 }
2211 Statement::TypeAlias(alias) => {
2212 self.emit_type_alias_decl(alias);
2213 true
2214 }
2215 Statement::Enum(declaration) => {
2216 self.emit_enum_decl(declaration);
2217 true
2218 }
2219 Statement::Namespace(namespace) => {
2220 self.emit_namespace_decl(namespace);
2221 true
2222 }
2223 Statement::Declare(inner) => self.emit_declaration(inner),
2224 Statement::Missing(_) => {
2225 self.diag_here(
2226 codes::MISSING_STATEMENT,
2227 "cannot emit a missing statement node",
2228 );
2229 false
2230 }
2231 _ => false,
2232 };
2233 self.anchor = previous;
2234 emitted
2235 }
2236
2237 fn decl_statement_emits(&self, statement: &Stmt) -> bool {
2238 matches!(
2239 statement.data(),
2240 Statement::Import(_)
2241 | Statement::ImportEquals(_)
2242 | Statement::Variable(_)
2243 | Statement::Function(_)
2244 | Statement::Class(_)
2245 | Statement::Interface(_)
2246 | Statement::TypeAlias(_)
2247 | Statement::Enum(_)
2248 | Statement::Namespace(_)
2249 | Statement::Declare(_)
2250 )
2251 }
2252
2253 fn emit_declare_prefix(&mut self) {
2254 if self.decl_ambient && !self.decl_in_export {
2255 self.raw("declare ");
2256 }
2257 }
2258
2259 fn emit_import_equals_decl(&mut self, import: &ImportEqualsDeclaration) {
2260 self.emit_declare_prefix();
2261 self.raw("import ");
2262 if import.is_type_only {
2263 self.raw("type ");
2264 }
2265 self.emit_ident(&import.local);
2266 self.raw(" = ");
2267 match &import.reference {
2268 ExternalModuleReference::Require(source) => {
2269 self.raw("require(");
2270 self.emit_string(source);
2271 self.raw(")");
2272 }
2273 ExternalModuleReference::Qualified(name) => self.emit_entity_name(name),
2274 ExternalModuleReference::Missing(_) => {
2275 self.diag_here(
2276 codes::MISSING_NAME,
2277 "cannot emit a missing module reference",
2278 );
2279 }
2280 }
2281 self.raw(";");
2282 }
2283
2284 fn emit_export_decl(&mut self, export: &ExportDeclaration) -> bool {
2285 match export {
2286 ExportDeclaration::Named(ExportNamedDeclaration::Declaration(inner)) => {
2287 if !self.decl_statement_emits(inner) {
2288 return false;
2289 }
2290 self.raw("export ");
2291 self.decl_in_export = true;
2292 let emitted = self.emit_declaration(inner);
2293 self.decl_in_export = false;
2294 emitted
2295 }
2296 ExportDeclaration::Named(ExportNamedDeclaration::Specifiers {
2297 type_only,
2298 specifiers,
2299 source,
2300 attributes,
2301 }) => {
2302 self.raw("export ");
2303 if *type_only {
2304 self.raw("type ");
2305 }
2306 if specifiers.is_empty() {
2307 self.raw("{}");
2308 } else {
2309 self.raw("{ ");
2310 for (index, specifier) in specifiers.iter().enumerate() {
2311 if index > 0 {
2312 self.raw(", ");
2313 }
2314 self.emit_export_specifier(specifier.data(), !*type_only);
2315 }
2316 self.raw(" }");
2317 }
2318 if let Some(source) = source {
2319 self.raw(" from ");
2320 self.emit_string(source);
2321 if let Some(attributes) = attributes {
2322 self.emit_import_attributes(attributes);
2323 }
2324 }
2325 self.raw(";");
2326 true
2327 }
2328 ExportDeclaration::All(all) => {
2329 self.raw("export ");
2330 if all.type_only {
2331 self.raw("type ");
2332 }
2333 self.raw("* ");
2334 if let Some(name) = &all.exported {
2335 self.raw("as ");
2336 self.emit_module_export_name(name);
2337 self.raw(" ");
2338 }
2339 self.raw("from ");
2340 self.emit_string(&all.source);
2341 if let Some(attributes) = &all.attributes {
2342 self.emit_import_attributes(attributes);
2343 }
2344 self.raw(";");
2345 true
2346 }
2347 ExportDeclaration::Default(default) => match &default.value {
2348 ExportDefaultValue::Function(function) => {
2349 self.raw("export default ");
2350 self.emit_function_signature_decl(function);
2351 true
2352 }
2353 ExportDefaultValue::Class(class) => {
2354 self.raw("export default ");
2355 self.emit_class_core_decl(class);
2356 true
2357 }
2358 ExportDefaultValue::Expression(expression) => {
2359 self.raw("export default ");
2360 self.emit_expression_prec(expression, P_ASSIGN);
2361 self.raw(";");
2362 true
2363 }
2364 ExportDefaultValue::Missing(_) => {
2365 self.diag_here(
2366 codes::MISSING_EXPRESSION,
2367 "cannot emit a missing default export",
2368 );
2369 false
2370 }
2371 },
2372 ExportDeclaration::Assignment(expression) => {
2373 self.raw("export = ");
2374 self.emit_expression_prec(expression, P_ASSIGN);
2375 self.raw(";");
2376 true
2377 }
2378 }
2379 }
2380
2381 fn emit_variable_decl(&mut self, declaration: &VariableDeclaration) {
2382 self.emit_declare_prefix();
2383 self.raw(variable_kind_str(declaration.kind));
2384 self.raw(" ");
2385 for (index, declarator) in declaration.declarations.iter().enumerate() {
2386 if index > 0 {
2387 self.raw(", ");
2388 }
2389 let declarator = declarator.data();
2390 self.emit_pattern(&declarator.binding);
2391 if let Some(annotation) = &declarator.type_annotation {
2392 self.raw(": ");
2393 self.emit_type(&annotation.data().type_node);
2394 }
2395 }
2396 self.raw(";");
2397 }
2398
2399 fn emit_function_signature_decl(&mut self, function: &FunctionLike) {
2400 self.raw("function");
2401 if let Some(name) = &function.name {
2402 self.raw(" ");
2403 self.emit_ident(name);
2404 }
2405 self.emit_type_parameters(&function.type_parameters);
2406 self.emit_params_decl(&function.parameters);
2407 if let Some(return_type) = &function.return_type {
2408 self.raw(": ");
2409 self.emit_type(&return_type.data().type_node);
2410 }
2411 self.raw(";");
2412 }
2413
2414 fn emit_params_decl(&mut self, parameters: &[ParameterNode]) {
2415 self.raw("(");
2416 for (index, parameter) in parameters.iter().enumerate() {
2417 if index > 0 {
2418 self.raw(", ");
2419 }
2420 let parameter = parameter.data();
2421 if let Some(accessibility) = parameter.modifiers.accessibility {
2422 self.raw(accessibility_str(accessibility));
2423 self.raw(" ");
2424 }
2425 if parameter.modifiers.is_readonly {
2426 self.raw("readonly ");
2427 }
2428 self.emit_pattern(¶meter.binding);
2429 if parameter.optional {
2430 self.raw("?");
2431 }
2432 if let Some(annotation) = ¶meter.type_annotation {
2433 self.raw(": ");
2434 self.emit_type(&annotation.data().type_node);
2435 }
2436 }
2437 self.raw(")");
2438 }
2439
2440 fn emit_class_core_decl(&mut self, class: &ClassDeclaration) {
2441 if class.modifiers.is_abstract {
2442 self.raw("abstract ");
2443 }
2444 self.raw("class");
2445 if let Some(name) = &class.name {
2446 self.raw(" ");
2447 self.emit_ident(name);
2448 }
2449 self.emit_type_parameters(&class.type_parameters);
2450 if let Some(heritage) = &class.extends {
2451 self.raw(" extends ");
2452 self.emit_expression_prec(&heritage.expression, P_CALL_MEMBER);
2453 self.emit_type_arguments(&heritage.type_arguments);
2454 }
2455 if !class.implements.is_empty() {
2456 self.raw(" implements ");
2457 for (index, interface) in class.implements.iter().enumerate() {
2458 if index > 0 {
2459 self.raw(", ");
2460 }
2461 self.emit_type(interface);
2462 }
2463 }
2464 self.raw(" ");
2465 self.emit_class_body_decl(&class.members);
2466 }
2467
2468 fn emit_class_body_decl(&mut self, members: &[ClassMemberNode]) {
2469 self.raw("{");
2470 let has = members
2471 .iter()
2472 .any(|member| self.class_member_emits_decl(member.data()));
2473 if has {
2474 self.newline();
2475 self.indent += 1;
2476 }
2477 for member in members {
2478 if self.emit_class_member_decl(member.data()) {
2479 self.newline();
2480 }
2481 }
2482 if has {
2483 self.indent -= 1;
2484 }
2485 self.raw("}");
2486 }
2487
2488 fn class_member_emits_decl(&self, member: &ClassMember) -> bool {
2489 !matches!(
2490 member,
2491 ClassMember::StaticBlock(_) | ClassMember::Missing(_)
2492 )
2493 }
2494
2495 fn emit_class_member_decl(&mut self, member: &ClassMember) -> bool {
2496 match member {
2497 ClassMember::Constructor(constructor) => {
2498 if let Some(accessibility) = constructor.modifiers.accessibility {
2499 self.raw(accessibility_str(accessibility));
2500 self.raw(" ");
2501 }
2502 self.raw("constructor");
2503 self.emit_params_decl(&constructor.parameters);
2504 self.raw(";");
2505 true
2506 }
2507 ClassMember::Method(method) => {
2508 self.emit_member_modifiers_decl(&method.modifiers);
2509 match method.modifier {
2510 PropertyModifier::Get => self.raw("get "),
2511 PropertyModifier::Set => self.raw("set "),
2512 PropertyModifier::None => {}
2513 }
2514 self.emit_property_name(&method.name);
2515 if method.optional {
2516 self.raw("?");
2517 }
2518 self.emit_type_parameters(&method.function.type_parameters);
2519 self.emit_params_decl(&method.function.parameters);
2520 if let Some(return_type) = &method.function.return_type {
2521 self.raw(": ");
2522 self.emit_type(&return_type.data().type_node);
2523 }
2524 self.raw(";");
2525 true
2526 }
2527 ClassMember::Property(property) => {
2528 self.emit_member_modifiers_decl(&property.modifiers);
2529 self.emit_property_name(&property.name);
2530 if property.optional {
2531 self.raw("?");
2532 }
2533 if let Some(annotation) = &property.type_annotation {
2534 self.raw(": ");
2535 self.emit_type(&annotation.data().type_node);
2536 }
2537 self.raw(";");
2538 true
2539 }
2540 ClassMember::AutoAccessor(accessor) => {
2541 self.emit_member_modifiers_decl(&accessor.modifiers);
2542 self.raw("accessor ");
2543 self.emit_property_name(&accessor.name);
2544 if let Some(annotation) = &accessor.type_annotation {
2545 self.raw(": ");
2546 self.emit_type(&annotation.data().type_node);
2547 }
2548 self.raw(";");
2549 true
2550 }
2551 ClassMember::IndexSignature(signature) => {
2552 if signature.readonly {
2553 self.raw("readonly ");
2554 }
2555 self.raw("[");
2556 self.emit_params_decl_inner(&signature.parameters);
2557 self.raw("]: ");
2558 self.emit_type(&signature.type_annotation.data().type_node);
2559 self.raw(";");
2560 true
2561 }
2562 ClassMember::StaticBlock(_) => false,
2563 ClassMember::Missing(_) => {
2564 self.diag_here(codes::MISSING_MEMBER, "cannot emit a missing class member");
2565 false
2566 }
2567 }
2568 }
2569
2570 fn emit_params_decl_inner(&mut self, parameters: &[ParameterNode]) {
2571 for (index, parameter) in parameters.iter().enumerate() {
2572 if index > 0 {
2573 self.raw(", ");
2574 }
2575 let parameter = parameter.data();
2576 self.emit_pattern(¶meter.binding);
2577 if let Some(annotation) = ¶meter.type_annotation {
2578 self.raw(": ");
2579 self.emit_type(&annotation.data().type_node);
2580 }
2581 }
2582 }
2583
2584 fn emit_member_modifiers_decl(&mut self, modifiers: &DeclarationModifiers) {
2585 if let Some(accessibility) = modifiers.accessibility {
2586 self.raw(accessibility_str(accessibility));
2587 self.raw(" ");
2588 }
2589 if modifiers.is_static {
2590 self.raw("static ");
2591 }
2592 if modifiers.is_abstract {
2593 self.raw("abstract ");
2594 }
2595 if modifiers.is_readonly {
2596 self.raw("readonly ");
2597 }
2598 }
2599
2600 fn emit_interface_decl(&mut self, interface: &InterfaceDeclaration) {
2601 self.raw("interface ");
2602 self.emit_ident(&interface.name);
2603 self.emit_type_parameters(&interface.type_parameters);
2604 if !interface.extends.is_empty() {
2605 self.raw(" extends ");
2606 for (index, reference) in interface.extends.iter().enumerate() {
2607 if index > 0 {
2608 self.raw(", ");
2609 }
2610 self.emit_type_reference(reference);
2611 }
2612 }
2613 self.raw(" ");
2614 self.emit_type_members_block(&interface.members);
2615 }
2616
2617 fn emit_type_alias_decl(&mut self, alias: &TypeAliasDeclaration) {
2618 self.raw("type ");
2619 self.emit_ident(&alias.name);
2620 self.emit_type_parameters(&alias.type_parameters);
2621 self.raw(" = ");
2622 self.emit_type(&alias.type_node);
2623 self.raw(";");
2624 }
2625
2626 fn emit_enum_decl(&mut self, declaration: &EnumDeclaration) {
2627 self.emit_declare_prefix();
2628 if declaration.is_const {
2629 self.raw("const ");
2630 }
2631 self.raw("enum ");
2632 self.emit_ident(&declaration.name);
2633 self.raw(" ");
2634 if declaration.members.is_empty() {
2635 self.raw("{}");
2636 return;
2637 }
2638 self.raw("{");
2639 self.newline();
2640 self.indent += 1;
2641 let count = declaration.members.len();
2642 for (index, member) in declaration.members.iter().enumerate() {
2643 let member = member.data();
2644 self.emit_property_name(&member.name);
2645 if let Some(initializer) = &member.initializer {
2646 self.raw(" = ");
2647 self.emit_expression_prec(initializer, P_ASSIGN);
2648 }
2649 if index + 1 < count {
2650 self.raw(",");
2651 }
2652 self.newline();
2653 }
2654 self.indent -= 1;
2655 self.raw("}");
2656 }
2657
2658 fn emit_namespace_decl(&mut self, namespace: &NamespaceDeclaration) {
2659 self.emit_declare_prefix();
2660 self.raw("namespace ");
2661 self.emit_ident(&namespace.name);
2662 self.raw(" {");
2663 let body = namespace.body.data();
2664 if body.statements.is_empty() {
2665 self.raw("}");
2666 return;
2667 }
2668 self.newline();
2669 self.indent += 1;
2670 let saved_ambient = self.decl_ambient;
2671 self.decl_ambient = false;
2672 for statement in &body.statements {
2673 if self.emit_declaration(statement) {
2674 self.newline();
2675 }
2676 }
2677 self.decl_ambient = saved_ambient;
2678 self.indent -= 1;
2679 self.raw("}");
2680 }
2681
2682 fn emit_type_parameters(&mut self, parameters: &Option<TypeParameterList>) {
2685 let Some(list) = parameters else {
2686 return;
2687 };
2688 if list.parameters.is_empty() {
2689 return;
2690 }
2691 self.raw("<");
2692 for (index, parameter) in list.parameters.iter().enumerate() {
2693 if index > 0 {
2694 self.raw(", ");
2695 }
2696 self.emit_type_parameter(parameter.data());
2697 }
2698 self.raw(">");
2699 }
2700
2701 fn emit_type_parameter(&mut self, parameter: &TypeParameter) {
2702 match parameter.variance {
2703 Variance::In => self.raw("in "),
2704 Variance::Out => self.raw("out "),
2705 Variance::InOut => self.raw("in out "),
2706 Variance::Invariant => {}
2707 }
2708 self.emit_ident(¶meter.name);
2709 if let Some(constraint) = ¶meter.constraint {
2710 self.raw(" extends ");
2711 self.emit_type(constraint);
2712 }
2713 if let Some(default) = ¶meter.default {
2714 self.raw(" = ");
2715 self.emit_type(default);
2716 }
2717 }
2718
2719 fn emit_type_arguments(&mut self, arguments: &Option<TypeArgumentList>) {
2720 let Some(list) = arguments else {
2721 return;
2722 };
2723 if list.arguments.is_empty() {
2724 return;
2725 }
2726 self.raw("<");
2727 for (index, argument) in list.arguments.iter().enumerate() {
2728 if index > 0 {
2729 self.raw(", ");
2730 }
2731 self.emit_type(argument);
2732 }
2733 self.raw(">");
2734 }
2735
2736 fn emit_type_reference(&mut self, reference: &TypeReference) {
2737 self.emit_entity_name(&reference.name);
2738 self.emit_type_arguments(&reference.type_arguments);
2739 }
2740
2741 fn emit_type(&mut self, ty: &Ty) {
2742 let previous = self.anchor;
2743 self.anchor = ty.range();
2744 match ty.data() {
2745 TypeNode::Keyword(keyword) => self.raw(keyword_type_str(*keyword)),
2746 TypeNode::Literal(literal) => self.emit_type_literal(literal),
2747 TypeNode::Reference(reference) => self.emit_type_reference(reference),
2748 TypeNode::Union(members) => self.emit_union(members),
2749 TypeNode::Intersection(members) => self.emit_intersection(members),
2750 TypeNode::Array(element) => {
2751 self.emit_type_postfix_operand(element);
2752 self.raw("[]");
2753 }
2754 TypeNode::Tuple(tuple) => self.emit_tuple(tuple),
2755 TypeNode::Object(object) => self.emit_object_type(object),
2756 TypeNode::Function(function) => self.emit_function_type(function),
2757 TypeNode::Constructor(constructor) => {
2758 if constructor.is_abstract {
2759 self.raw("abstract ");
2760 }
2761 self.raw("new ");
2762 self.emit_function_type_body(&constructor.function);
2763 }
2764 TypeNode::Query(query) => {
2765 self.raw("typeof ");
2766 self.emit_entity_name(&query.name);
2767 self.emit_type_arguments(&query.type_arguments);
2768 }
2769 TypeNode::Operator { operator, operand } => {
2770 self.raw(type_operator_str(*operator));
2771 self.raw(" ");
2772 self.emit_type_operator_operand(operand);
2773 }
2774 TypeNode::IndexedAccess(indexed) => {
2775 self.emit_type_postfix_operand(&indexed.object_type);
2776 self.raw("[");
2777 self.emit_type(&indexed.index_type);
2778 self.raw("]");
2779 }
2780 TypeNode::Conditional(conditional) => {
2781 self.emit_type(&conditional.check_type);
2782 self.raw(" extends ");
2783 self.emit_type(&conditional.extends_type);
2784 self.raw(" ? ");
2785 self.emit_type(&conditional.true_type);
2786 self.raw(" : ");
2787 self.emit_type(&conditional.false_type);
2788 }
2789 TypeNode::Mapped(mapped) => self.emit_mapped_type(mapped),
2790 TypeNode::Infer(infer) => {
2791 self.raw("infer ");
2792 self.emit_ident(&infer.parameter.data().name);
2793 if let Some(constraint) = &infer.parameter.data().constraint {
2794 self.raw(" extends ");
2795 self.emit_type(constraint);
2796 }
2797 }
2798 TypeNode::Import(import) => {
2799 self.raw("import(");
2800 self.emit_string(&import.argument);
2801 self.raw(")");
2802 if let Some(qualifier) = &import.qualifier {
2803 self.raw(".");
2804 self.emit_entity_name(qualifier);
2805 }
2806 self.emit_type_arguments(&import.type_arguments);
2807 }
2808 TypeNode::TemplateLiteral(template) => self.emit_template_literal_type(template),
2809 TypeNode::Parenthesized(inner) => self.emit_type(inner),
2810 TypeNode::This => self.raw("this"),
2811 TypeNode::Predicate(predicate) => self.emit_type_predicate(predicate),
2812 TypeNode::Missing(_) => {
2813 self.diag_here(codes::MISSING_TYPE, "cannot emit a missing type node");
2814 self.raw("any");
2815 }
2816 }
2817 self.anchor = previous;
2818 }
2819
2820 fn emit_type_literal(&mut self, literal: &TypeLiteral) {
2821 match literal {
2822 TypeLiteral::String(node) => self.emit_token(node.data().token()),
2823 TypeLiteral::Number(node) => self.emit_token(node.data().token()),
2824 TypeLiteral::BigInt(node) => self.emit_token(node.data().token()),
2825 TypeLiteral::Boolean(node) => self.emit_token(node.data().token()),
2826 TypeLiteral::Null(node) => match self.text(node.data().token()) {
2827 Some(text) if !text.is_empty() => self.raw(text),
2828 _ => self.raw("null"),
2829 },
2830 TypeLiteral::Unary { operator, operand } => {
2831 self.raw(unary_operator_str(*operator));
2832 self.emit_type(operand);
2833 }
2834 }
2835 }
2836
2837 fn emit_union(&mut self, members: &[Ty]) {
2838 for (index, member) in members.iter().enumerate() {
2839 if index > 0 {
2840 self.raw(" | ");
2841 }
2842 if is_low_precedence_type(self.unwrap_type(member)) {
2843 self.raw("(");
2844 self.emit_type(member);
2845 self.raw(")");
2846 } else {
2847 self.emit_type(member);
2848 }
2849 }
2850 }
2851
2852 fn emit_intersection(&mut self, members: &[Ty]) {
2853 for (index, member) in members.iter().enumerate() {
2854 if index > 0 {
2855 self.raw(" & ");
2856 }
2857 let inner = self.unwrap_type(member);
2858 if is_low_precedence_type(inner) || matches!(inner.data(), TypeNode::Union(_)) {
2859 self.raw("(");
2860 self.emit_type(member);
2861 self.raw(")");
2862 } else {
2863 self.emit_type(member);
2864 }
2865 }
2866 }
2867
2868 fn emit_type_postfix_operand(&mut self, ty: &Ty) {
2869 let inner = self.unwrap_type(ty);
2870 let wrap = is_low_precedence_type(inner)
2871 || matches!(
2872 inner.data(),
2873 TypeNode::Union(_) | TypeNode::Intersection(_) | TypeNode::Operator { .. }
2874 );
2875 if wrap {
2876 self.raw("(");
2877 self.emit_type(ty);
2878 self.raw(")");
2879 } else {
2880 self.emit_type(ty);
2881 }
2882 }
2883
2884 fn emit_type_operator_operand(&mut self, ty: &Ty) {
2885 let inner = self.unwrap_type(ty);
2886 if is_low_precedence_type(inner)
2887 || matches!(inner.data(), TypeNode::Union(_) | TypeNode::Intersection(_))
2888 {
2889 self.raw("(");
2890 self.emit_type(ty);
2891 self.raw(")");
2892 } else {
2893 self.emit_type(ty);
2894 }
2895 }
2896
2897 fn emit_tuple(&mut self, tuple: &TupleType) {
2898 if tuple.readonly {
2899 self.raw("readonly ");
2900 }
2901 self.raw("[");
2902 for (index, element) in tuple.elements.iter().enumerate() {
2903 if index > 0 {
2904 self.raw(", ");
2905 }
2906 if element.rest {
2907 self.raw("...");
2908 }
2909 if let Some(name) = &element.name {
2910 self.emit_ident(name);
2911 if element.optional {
2912 self.raw("?");
2913 }
2914 self.raw(": ");
2915 self.emit_type(&element.type_node);
2916 } else {
2917 self.emit_type(&element.type_node);
2918 if element.optional {
2919 self.raw("?");
2920 }
2921 }
2922 }
2923 self.raw("]");
2924 }
2925
2926 fn emit_object_type(&mut self, object: &ObjectType) {
2927 if object.members.is_empty() {
2928 self.raw("{}");
2929 return;
2930 }
2931 self.raw("{ ");
2932 for (index, member) in object.members.iter().enumerate() {
2933 if index > 0 {
2934 self.raw(" ");
2935 }
2936 self.emit_type_member(member.data());
2937 }
2938 self.raw(" }");
2939 }
2940
2941 fn emit_type_members_block(&mut self, members: &[TypeMemberNode]) {
2942 if members.is_empty() {
2943 self.raw("{}");
2944 return;
2945 }
2946 self.raw("{");
2947 self.newline();
2948 self.indent += 1;
2949 for member in members {
2950 self.emit_type_member(member.data());
2951 self.newline();
2952 }
2953 self.indent -= 1;
2954 self.raw("}");
2955 }
2956
2957 fn emit_type_member(&mut self, member: &TypeMember) {
2958 match member {
2959 TypeMember::Property(property) => {
2960 if property.readonly {
2961 self.raw("readonly ");
2962 }
2963 self.emit_property_name(&property.name);
2964 if property.optional {
2965 self.raw("?");
2966 }
2967 if let Some(annotation) = &property.type_annotation {
2968 self.raw(": ");
2969 self.emit_type(&annotation.data().type_node);
2970 }
2971 self.raw(";");
2972 }
2973 TypeMember::Method(method) => {
2974 self.emit_property_name(&method.name);
2975 if method.optional {
2976 self.raw("?");
2977 }
2978 self.emit_function_type_body(&method.function);
2979 self.raw(";");
2980 }
2981 TypeMember::Call(call) => {
2982 self.emit_function_type_body(&call.function);
2983 self.raw(";");
2984 }
2985 TypeMember::Construct(construct) => {
2986 self.raw("new ");
2987 self.emit_function_type_body(&construct.function.function);
2988 self.raw(";");
2989 }
2990 TypeMember::Index(index) => {
2991 if index.readonly {
2992 self.raw("readonly ");
2993 }
2994 self.raw("[");
2995 self.emit_function_type_parameters(&index.parameters);
2996 self.raw("]: ");
2997 self.emit_type(&index.type_annotation.data().type_node);
2998 self.raw(";");
2999 }
3000 TypeMember::Missing(_) => {
3001 self.diag_here(codes::MISSING_MEMBER, "cannot emit a missing type member");
3002 }
3003 }
3004 }
3005
3006 fn emit_function_type(&mut self, function: &FunctionType) {
3007 self.emit_function_type_body_arrow(function);
3008 }
3009
3010 fn emit_function_type_body_arrow(&mut self, function: &FunctionType) {
3011 self.emit_type_parameters(&function.type_parameters);
3012 self.raw("(");
3013 self.emit_function_type_parameters(&function.parameters);
3014 self.raw(") => ");
3015 self.emit_type(&function.return_type);
3016 }
3017
3018 fn emit_function_type_body(&mut self, function: &FunctionType) {
3019 self.emit_type_parameters(&function.type_parameters);
3020 self.raw("(");
3021 self.emit_function_type_parameters(&function.parameters);
3022 self.raw("): ");
3023 self.emit_type(&function.return_type);
3024 }
3025
3026 fn emit_function_type_parameters(&mut self, parameters: &[FunctionTypeParameter]) {
3027 for (index, parameter) in parameters.iter().enumerate() {
3028 if index > 0 {
3029 self.raw(", ");
3030 }
3031 if parameter.rest {
3032 self.raw("...");
3033 }
3034 self.emit_ident(¶meter.name);
3035 if parameter.optional {
3036 self.raw("?");
3037 }
3038 self.raw(": ");
3039 self.emit_type(¶meter.type_annotation.data().type_node);
3040 }
3041 }
3042
3043 fn emit_mapped_type(&mut self, mapped: &MappedType) {
3044 self.raw("{ ");
3045 match mapped.readonly_modifier {
3046 MappedModifier::Preserve => {}
3047 MappedModifier::Add => self.raw("readonly "),
3048 MappedModifier::Remove => self.raw("-readonly "),
3049 }
3050 self.raw("[");
3051 self.emit_ident(&mapped.parameter.data().name);
3052 self.raw(" in ");
3053 if let Some(constraint) = &mapped.parameter.data().constraint {
3054 self.emit_type(constraint);
3055 }
3056 if let Some(name_type) = &mapped.name_type {
3057 self.raw(" as ");
3058 self.emit_type(name_type);
3059 }
3060 self.raw("]");
3061 match mapped.optional_modifier {
3062 MappedModifier::Preserve => {}
3063 MappedModifier::Add => self.raw("?"),
3064 MappedModifier::Remove => self.raw("-?"),
3065 }
3066 if let Some(value_type) = &mapped.value_type {
3067 self.raw(": ");
3068 self.emit_type(value_type);
3069 }
3070 self.raw("; }");
3071 }
3072
3073 fn emit_template_literal_type(&mut self, template: &TemplateLiteralType) {
3074 if template.elements.is_empty() {
3075 return;
3076 }
3077 self.emit_token(template.elements[0].data().token());
3078 for (index, ty) in template.types.iter().enumerate() {
3079 self.emit_type(ty);
3080 if let Some(element) = template.elements.get(index + 1) {
3081 self.emit_token(element.data().token());
3082 }
3083 }
3084 }
3085
3086 fn emit_type_predicate(&mut self, predicate: &TypePredicate) {
3087 if predicate.asserts {
3088 self.raw("asserts ");
3089 }
3090 self.emit_entity_name(&predicate.parameter_name);
3091 if let Some(ty) = &predicate.type_node {
3092 self.raw(" is ");
3093 self.emit_type(ty);
3094 }
3095 }
3096
3097 fn unwrap_type<'t>(&self, ty: &'t Ty) -> &'t Ty {
3098 match ty.data() {
3099 TypeNode::Parenthesized(inner) => self.unwrap_type(inner),
3100 _ => ty,
3101 }
3102 }
3103}
3104
3105fn is_parameter_property(parameter: &Parameter) -> bool {
3108 parameter.modifiers.accessibility.is_some()
3109 || parameter.modifiers.is_readonly
3110 || parameter.modifiers.is_override
3111}
3112
3113fn numeric_literal_value(expression: &Expr) -> Option<Option<i64>> {
3116 match expression.data() {
3117 Expression::Literal(Literal::Number(_)) => Some(None),
3118 Expression::Unary(unary)
3119 if matches!(unary.operator, UnaryOperator::Plus | UnaryOperator::Minus)
3120 && matches!(
3121 unary.argument.data(),
3122 Expression::Literal(Literal::Number(_))
3123 ) =>
3124 {
3125 Some(None)
3126 }
3127 Expression::Parenthesized(inner) => numeric_literal_value(inner),
3128 _ => None,
3129 }
3130}
3131
3132const fn variable_kind_str(kind: VariableKind) -> &'static str {
3133 match kind {
3134 VariableKind::Var => "var",
3135 VariableKind::Let => "let",
3136 VariableKind::Const => "const",
3137 VariableKind::Using => "using",
3138 VariableKind::AwaitUsing => "await using",
3139 }
3140}
3141
3142const fn accessibility_str(accessibility: Accessibility) -> &'static str {
3143 match accessibility {
3144 Accessibility::Public => "public",
3145 Accessibility::Protected => "protected",
3146 Accessibility::Private => "private",
3147 }
3148}
3149
3150const fn binary_prec(operator: BinaryOperator) -> u8 {
3151 match operator {
3152 BinaryOperator::BitOr => P_BIT_OR,
3153 BinaryOperator::BitXor => P_BIT_XOR,
3154 BinaryOperator::BitAnd => P_BIT_AND,
3155 BinaryOperator::Equal
3156 | BinaryOperator::NotEqual
3157 | BinaryOperator::StrictEqual
3158 | BinaryOperator::StrictNotEqual => P_EQUALITY,
3159 BinaryOperator::LessThan
3160 | BinaryOperator::LessThanOrEqual
3161 | BinaryOperator::GreaterThan
3162 | BinaryOperator::GreaterThanOrEqual
3163 | BinaryOperator::In
3164 | BinaryOperator::Instanceof => P_RELATIONAL,
3165 BinaryOperator::LeftShift
3166 | BinaryOperator::SignedRightShift
3167 | BinaryOperator::UnsignedRightShift => P_SHIFT,
3168 BinaryOperator::Add | BinaryOperator::Subtract => P_ADDITIVE,
3169 BinaryOperator::Multiply | BinaryOperator::Divide | BinaryOperator::Remainder => {
3170 P_MULTIPLICATIVE
3171 }
3172 BinaryOperator::Exponentiate => P_EXPONENT,
3173 }
3174}
3175
3176const fn binary_str(operator: BinaryOperator) -> &'static str {
3177 match operator {
3178 BinaryOperator::Add => "+",
3179 BinaryOperator::Subtract => "-",
3180 BinaryOperator::Multiply => "*",
3181 BinaryOperator::Divide => "/",
3182 BinaryOperator::Remainder => "%",
3183 BinaryOperator::Exponentiate => "**",
3184 BinaryOperator::LeftShift => "<<",
3185 BinaryOperator::SignedRightShift => ">>",
3186 BinaryOperator::UnsignedRightShift => ">>>",
3187 BinaryOperator::LessThan => "<",
3188 BinaryOperator::LessThanOrEqual => "<=",
3189 BinaryOperator::GreaterThan => ">",
3190 BinaryOperator::GreaterThanOrEqual => ">=",
3191 BinaryOperator::In => "in",
3192 BinaryOperator::Instanceof => "instanceof",
3193 BinaryOperator::Equal => "==",
3194 BinaryOperator::NotEqual => "!=",
3195 BinaryOperator::StrictEqual => "===",
3196 BinaryOperator::StrictNotEqual => "!==",
3197 BinaryOperator::BitAnd => "&",
3198 BinaryOperator::BitXor => "^",
3199 BinaryOperator::BitOr => "|",
3200 }
3201}
3202
3203const fn logical_str(operator: LogicalOperator) -> &'static str {
3204 match operator {
3205 LogicalOperator::And => "&&",
3206 LogicalOperator::Or => "||",
3207 LogicalOperator::Nullish => "??",
3208 }
3209}
3210
3211const fn assignment_str(operator: AssignmentOperator) -> &'static str {
3212 match operator {
3213 AssignmentOperator::Assign => "=",
3214 AssignmentOperator::AddAssign => "+=",
3215 AssignmentOperator::SubtractAssign => "-=",
3216 AssignmentOperator::MultiplyAssign => "*=",
3217 AssignmentOperator::DivideAssign => "/=",
3218 AssignmentOperator::RemainderAssign => "%=",
3219 AssignmentOperator::ExponentiateAssign => "**=",
3220 AssignmentOperator::LeftShiftAssign => "<<=",
3221 AssignmentOperator::SignedRightShiftAssign => ">>=",
3222 AssignmentOperator::UnsignedRightShiftAssign => ">>>=",
3223 AssignmentOperator::BitAndAssign => "&=",
3224 AssignmentOperator::BitXorAssign => "^=",
3225 AssignmentOperator::BitOrAssign => "|=",
3226 AssignmentOperator::LogicalAndAssign => "&&=",
3227 AssignmentOperator::LogicalOrAssign => "||=",
3228 AssignmentOperator::NullishAssign => "??=",
3229 }
3230}
3231
3232const fn unary_operator_str(operator: UnaryOperator) -> &'static str {
3233 match operator {
3234 UnaryOperator::Plus => "+",
3235 UnaryOperator::Minus => "-",
3236 UnaryOperator::Not => "!",
3237 UnaryOperator::BitNot => "~",
3238 UnaryOperator::Typeof => "typeof ",
3239 UnaryOperator::Void => "void ",
3240 UnaryOperator::Delete => "delete ",
3241 }
3242}
3243
3244const fn keyword_type_str(keyword: KeywordType) -> &'static str {
3245 match keyword {
3246 KeywordType::Any => "any",
3247 KeywordType::Unknown => "unknown",
3248 KeywordType::Never => "never",
3249 KeywordType::Void => "void",
3250 KeywordType::Undefined => "undefined",
3251 KeywordType::Null => "null",
3252 KeywordType::Boolean => "boolean",
3253 KeywordType::Number => "number",
3254 KeywordType::BigInt => "bigint",
3255 KeywordType::String => "string",
3256 KeywordType::Symbol => "symbol",
3257 KeywordType::Object => "object",
3258 KeywordType::Intrinsic => "intrinsic",
3259 }
3260}
3261
3262const fn type_operator_str(operator: TypeOperator) -> &'static str {
3263 match operator {
3264 TypeOperator::Keyof => "keyof",
3265 TypeOperator::Unique => "unique",
3266 TypeOperator::Readonly => "readonly",
3267 }
3268}
3269
3270fn is_low_precedence_type(ty: &Ty) -> bool {
3271 matches!(
3272 ty.data(),
3273 TypeNode::Function(_)
3274 | TypeNode::Constructor(_)
3275 | TypeNode::Conditional(_)
3276 | TypeNode::Infer(_)
3277 )
3278}
3279
3280#[cfg(test)]
3281mod tests {
3282 use super::*;
3283 use crate::source::{ScriptKind, Utf16Pos};
3284 use std::sync::Arc;
3285
3286 struct Builder {
3290 text: String,
3291 len: usize,
3292 }
3293
3294 impl Builder {
3295 fn new() -> Self {
3296 Self {
3297 text: String::new(),
3298 len: 0,
3299 }
3300 }
3301
3302 fn range(start: usize, end: usize) -> TextRange {
3303 TextRange::new(Utf16Pos::new(start), Utf16Pos::new(end)).expect("ordered range")
3304 }
3305
3306 fn token(&mut self, kind: TokenKind, lexeme: &str) -> Token {
3307 let start = self.len;
3308 self.text.push_str(lexeme);
3309 self.len += lexeme.encode_utf16().count();
3310 Token::new(kind, Self::range(start, self.len))
3311 }
3312
3313 fn ident(&mut self, name: &str) -> IdentifierNode {
3314 let token = self.token(TokenKind::Identifier, name);
3315 Node::new(NodeId::new(0), token.range(), Identifier::new(token))
3316 }
3317
3318 fn ident_expr(&mut self, name: &str) -> Expr {
3319 let ident = self.ident(name);
3320 let range = ident.range();
3321 Node::new(NodeId::new(0), range, Expression::Identifier(ident))
3322 }
3323
3324 fn number(&mut self, literal: &str) -> Expr {
3325 let token = self.token(TokenKind::NumericLiteral, literal);
3326 let node = Node::new(NodeId::new(0), token.range(), NumericLiteral::new(token));
3327 let range = node.range();
3328 Node::new(
3329 NodeId::new(0),
3330 range,
3331 Expression::Literal(Literal::Number(node)),
3332 )
3333 }
3334
3335 fn string(&mut self, literal: &str) -> StringLiteralNode {
3336 let token = self.token(TokenKind::StringLiteral, literal);
3337 Node::new(NodeId::new(0), token.range(), StringLiteral::new(token))
3338 }
3339
3340 fn finish(self, statements: Vec<Stmt>) -> SourceFile {
3341 let source = Arc::new(SourceText::new(self.text));
3342 let len = source.len_utf16();
3343 let full = TextRange::new(Utf16Pos::ZERO, len).expect("range");
3344 let eof = Token::new(
3345 TokenKind::EndOfFile,
3346 TextRange::new(len, len).expect("range"),
3347 );
3348 SourceFile::new(
3349 NodeId::new(0),
3350 SourceId::new(0),
3351 ScriptKind::TypeScript,
3352 full,
3353 source,
3354 Vec::new(),
3355 statements,
3356 eof,
3357 Vec::new(),
3358 )
3359 }
3360 }
3361
3362 fn dummy() -> TextRange {
3363 TextRange::new(Utf16Pos::ZERO, Utf16Pos::ZERO).expect("range")
3364 }
3365
3366 fn expr(data: Expression) -> Expr {
3367 Node::new(NodeId::new(0), dummy(), data)
3368 }
3369
3370 fn stmt(data: Statement) -> Stmt {
3371 Node::new(NodeId::new(0), dummy(), data)
3372 }
3373
3374 fn expr_stmt(expression: Expr) -> Stmt {
3375 stmt(Statement::Expression(ExpressionStatement {
3376 expression: Box::new(expression),
3377 }))
3378 }
3379
3380 fn binary(operator: BinaryOperator, left: Expr, right: Expr) -> Expr {
3381 expr(Expression::Binary(BinaryExpression {
3382 operator,
3383 left: Box::new(left),
3384 right: Box::new(right),
3385 }))
3386 }
3387
3388 fn emit_js(file: &SourceFile) -> EmitOutput {
3389 emit(file, EmitOptions::javascript())
3390 }
3391
3392 #[test]
3393 fn multiplication_binds_tighter_than_addition() {
3394 let mut b = Builder::new();
3395 let a = b.ident_expr("a");
3396 let bb = b.ident_expr("b");
3397 let c = b.ident_expr("c");
3398 let tree = binary(
3400 BinaryOperator::Add,
3401 a,
3402 binary(BinaryOperator::Multiply, bb, c),
3403 );
3404 let file = b.finish(vec![expr_stmt(tree)]);
3405 assert_eq!(emit_js(&file).code, "a + b * c;\n");
3406 }
3407
3408 #[test]
3409 fn lower_precedence_left_operand_is_parenthesized() {
3410 let mut b = Builder::new();
3411 let a = b.ident_expr("a");
3412 let bb = b.ident_expr("b");
3413 let c = b.ident_expr("c");
3414 let tree = binary(
3416 BinaryOperator::Multiply,
3417 binary(BinaryOperator::Add, a, bb),
3418 c,
3419 );
3420 let file = b.finish(vec![expr_stmt(tree)]);
3421 assert_eq!(emit_js(&file).code, "(a + b) * c;\n");
3422 }
3423
3424 #[test]
3425 fn exponent_is_right_associative_and_forces_left_grouping() {
3426 let mut b = Builder::new();
3427 let a = b.ident_expr("a");
3428 let bb = b.ident_expr("b");
3429 let c = b.ident_expr("c");
3430 let left_grouped = binary(
3432 BinaryOperator::Exponentiate,
3433 binary(BinaryOperator::Exponentiate, a, bb),
3434 c,
3435 );
3436 let file = b.finish(vec![expr_stmt(left_grouped)]);
3437 assert_eq!(emit_js(&file).code, "(a ** b) ** c;\n");
3438 }
3439
3440 #[test]
3441 fn unary_left_of_exponent_is_parenthesized() {
3442 let mut b = Builder::new();
3443 let a = b.ident_expr("a");
3444 let bb = b.ident_expr("b");
3445 let neg = expr(Expression::Unary(UnaryExpression {
3446 operator: UnaryOperator::Minus,
3447 argument: Box::new(a),
3448 }));
3449 let tree = binary(BinaryOperator::Exponentiate, neg, bb);
3450 let file = b.finish(vec![expr_stmt(tree)]);
3451 assert_eq!(emit_js(&file).code, "(-a) ** b;\n");
3452 }
3453
3454 #[test]
3455 fn nullish_and_logical_or_require_parentheses_when_mixed() {
3456 let mut b = Builder::new();
3457 let a = b.ident_expr("a");
3458 let bb = b.ident_expr("b");
3459 let c = b.ident_expr("c");
3460 let or = expr(Expression::Logical(LogicalExpression {
3462 operator: LogicalOperator::Or,
3463 left: Box::new(a),
3464 right: Box::new(bb),
3465 }));
3466 let tree = expr(Expression::Logical(LogicalExpression {
3467 operator: LogicalOperator::Nullish,
3468 left: Box::new(or),
3469 right: Box::new(c),
3470 }));
3471 let file = b.finish(vec![expr_stmt(tree)]);
3472 assert_eq!(emit_js(&file).code, "(a || b) ?? c;\n");
3473 }
3474
3475 #[test]
3476 fn object_literal_expression_statement_is_parenthesized() {
3477 let b = Builder::new();
3478 let object = expr(Expression::Object(ObjectLiteral {
3479 members: Vec::new(),
3480 }));
3481 let file = b.finish(vec![expr_stmt(object)]);
3482 assert_eq!(emit_js(&file).code, "({});\n");
3483 }
3484
3485 #[test]
3486 fn arrow_object_body_is_parenthesized() {
3487 let b = Builder::new();
3488 let object = expr(Expression::Object(ObjectLiteral {
3489 members: Vec::new(),
3490 }));
3491 let arrow = expr(Expression::Arrow(ArrowFunction {
3492 is_async: false,
3493 type_parameters: None,
3494 parameters: Vec::new(),
3495 return_type: None,
3496 body: FunctionBody::Expression(Box::new(object)),
3497 }));
3498 let file = b.finish(vec![expr_stmt(arrow)]);
3499 assert_eq!(emit_js(&file).code, "() => ({});\n");
3500 }
3501
3502 #[test]
3503 fn type_annotation_is_erased_in_javascript() {
3504 let mut b = Builder::new();
3505 let name = b.ident("x");
3506 let init = b.number("1");
3507 let annotation = Node::new(
3508 NodeId::new(0),
3509 dummy(),
3510 TypeAnnotation {
3511 type_node: Box::new(Node::new(
3512 NodeId::new(0),
3513 dummy(),
3514 TypeNode::Keyword(KeywordType::Number),
3515 )),
3516 },
3517 );
3518 let binding = Node::new(
3519 NodeId::new(0),
3520 name.range(),
3521 BindingPattern::Identifier(name),
3522 );
3523 let declarator = Node::new(
3524 NodeId::new(0),
3525 dummy(),
3526 VariableDeclarator {
3527 binding,
3528 definite: false,
3529 type_annotation: Some(annotation),
3530 initializer: Some(Box::new(init)),
3531 },
3532 );
3533 let declaration = stmt(Statement::Variable(VariableDeclaration {
3534 kind: VariableKind::Let,
3535 declarations: vec![declarator],
3536 }));
3537 let file = b.finish(vec![declaration]);
3538 assert_eq!(emit_js(&file).code, "let x = 1;\n");
3539 }
3540
3541 #[test]
3542 fn as_expression_is_erased_but_keeps_needed_parentheses() {
3543 let mut b = Builder::new();
3544 let a = b.ident_expr("a");
3545 let bb = b.ident_expr("b");
3546 let c = b.ident_expr("c");
3547 let as_expr = expr(Expression::As(AsExpression {
3549 expression: Box::new(binary(BinaryOperator::Add, a, bb)),
3550 type_node: Some(Box::new(Node::new(
3551 NodeId::new(0),
3552 dummy(),
3553 TypeNode::Keyword(KeywordType::Any),
3554 ))),
3555 }));
3556 let tree = binary(BinaryOperator::Multiply, as_expr, c);
3557 let file = b.finish(vec![expr_stmt(tree)]);
3558 assert_eq!(emit_js(&file).code, "(a + b) * c;\n");
3559 }
3560
3561 #[test]
3562 fn newline_policy_uses_configured_terminator() {
3563 let mut b = Builder::new();
3564 let first = expr_stmt(b.ident_expr("a"));
3565 let second = expr_stmt(b.ident_expr("b"));
3566 let file = b.finish(vec![first, second]);
3567 let output = emit(&file, EmitOptions::javascript().with_newline(Newline::CrLf));
3568 assert_eq!(output.code, "a;\r\nb;\r\n");
3569 }
3570
3571 #[test]
3572 fn missing_expression_reports_stable_diagnostic() {
3573 let b = Builder::new();
3574 let missing = expr(Expression::Missing(MissingNode::new(
3575 NodeKind::IdentifierExpression,
3576 )));
3577 let file = b.finish(vec![expr_stmt(missing)]);
3578 let output = emit_js(&file);
3579 assert_eq!(output.code, "void 0;\n");
3580 assert_eq!(output.diagnostics.len(), 1);
3581 assert_eq!(output.diagnostics[0].code(), codes::MISSING_EXPRESSION);
3582 assert!(output.has_errors());
3583 }
3584
3585 #[test]
3586 fn enum_lowers_to_runtime_object_with_reverse_mapping() {
3587 let mut b = Builder::new();
3588 let enum_name = b.ident("E");
3589 let member_a = Node::new(
3590 NodeId::new(0),
3591 dummy(),
3592 EnumMember {
3593 name: PropertyName::Identifier(b.ident("A")),
3594 initializer: None,
3595 },
3596 );
3597 let member_b = Node::new(
3598 NodeId::new(0),
3599 dummy(),
3600 EnumMember {
3601 name: PropertyName::Identifier(b.ident("B")),
3602 initializer: None,
3603 },
3604 );
3605 let declaration = stmt(Statement::Enum(EnumDeclaration {
3606 is_const: false,
3607 name: enum_name,
3608 members: vec![member_a, member_b],
3609 }));
3610 let file = b.finish(vec![declaration]);
3611 let expected = "var E;\n(function (E) {\n E[E[\"A\"] = 0] = \"A\";\n E[E[\"B\"] = 1] = \"B\";\n})(E || (E = {}));\n";
3612 assert_eq!(emit_js(&file).code, expected);
3613 }
3614
3615 #[test]
3616 fn enum_string_member_has_no_reverse_mapping() {
3617 let mut b = Builder::new();
3618 let enum_name = b.ident("E");
3619 let value = b.string("\"hi\"");
3620 let member = Node::new(
3621 NodeId::new(0),
3622 dummy(),
3623 EnumMember {
3624 name: PropertyName::Identifier(b.ident("A")),
3625 initializer: Some(Box::new(expr(Expression::Literal(Literal::String(value))))),
3626 },
3627 );
3628 let declaration = stmt(Statement::Enum(EnumDeclaration {
3629 is_const: false,
3630 name: enum_name,
3631 members: vec![member],
3632 }));
3633 let file = b.finish(vec![declaration]);
3634 let expected = "var E;\n(function (E) {\n E[\"A\"] = \"hi\";\n})(E || (E = {}));\n";
3635 assert_eq!(emit_js(&file).code, expected);
3636 }
3637
3638 #[test]
3639 fn namespace_reports_unlowered_diagnostic_in_javascript() {
3640 let mut b = Builder::new();
3641 let name = b.ident("N");
3642 let body = Node::new(
3643 NodeId::new(0),
3644 dummy(),
3645 Block {
3646 statements: Vec::new(),
3647 },
3648 );
3649 let declaration = stmt(Statement::Namespace(NamespaceDeclaration { name, body }));
3650 let file = b.finish(vec![declaration]);
3651 let output = emit_js(&file);
3652 assert_eq!(output.code, "");
3653 assert_eq!(output.diagnostics.len(), 1);
3654 assert_eq!(output.diagnostics[0].code(), codes::NAMESPACE_UNLOWERED);
3655 }
3656
3657 #[test]
3658 fn parameter_property_is_lowered_to_constructor_assignment() {
3659 let mut b = Builder::new();
3660 let class_name = b.ident("C");
3661 let param_name = b.ident("x");
3662 let binding = Node::new(
3663 NodeId::new(0),
3664 param_name.range(),
3665 BindingPattern::Identifier(param_name),
3666 );
3667 let parameter = Node::new(
3668 NodeId::new(0),
3669 dummy(),
3670 Parameter {
3671 decorators: Vec::new(),
3672 modifiers: ParameterModifiers {
3673 accessibility: Some(Accessibility::Private),
3674 is_readonly: false,
3675 is_override: false,
3676 },
3677 binding,
3678 optional: false,
3679 type_annotation: None,
3680 initializer: None,
3681 },
3682 );
3683 let constructor = Node::new(
3684 NodeId::new(0),
3685 dummy(),
3686 ClassMember::Constructor(ConstructorDeclaration {
3687 modifiers: DeclarationModifiers::default(),
3688 parameters: vec![parameter],
3689 body: Node::new(
3690 NodeId::new(0),
3691 dummy(),
3692 Block {
3693 statements: Vec::new(),
3694 },
3695 ),
3696 }),
3697 );
3698 let class = stmt(Statement::Class(ClassDeclaration {
3699 decorators: Vec::new(),
3700 modifiers: DeclarationModifiers::default(),
3701 name: Some(class_name),
3702 type_parameters: None,
3703 extends: None,
3704 implements: Vec::new(),
3705 members: vec![constructor],
3706 }));
3707 let file = b.finish(vec![class]);
3708 let expected = "class C {\n constructor(x) {\n this.x = x;\n }\n}\n";
3709 assert_eq!(emit_js(&file).code, expected);
3710 }
3711
3712 #[test]
3713 fn declaration_mode_prints_type_alias_and_erases_bodies() {
3714 let mut b = Builder::new();
3715 let alias_name = b.ident("Id");
3716 let alias = stmt(Statement::TypeAlias(TypeAliasDeclaration {
3717 name: alias_name,
3718 type_parameters: None,
3719 type_node: Box::new(Node::new(
3720 NodeId::new(0),
3721 dummy(),
3722 TypeNode::Keyword(KeywordType::Number),
3723 )),
3724 }));
3725 let file = b.finish(vec![alias]);
3726 let output = emit(&file, EmitOptions::declaration());
3727 assert_eq!(output.code, "type Id = number;\n");
3728 }
3729
3730 #[test]
3731 fn declaration_mode_emits_function_signature_without_body() {
3732 let mut b = Builder::new();
3733 let function_name = b.ident("f");
3734 let function = stmt(Statement::Function(FunctionDeclaration {
3735 function: FunctionLike {
3736 decorators: Vec::new(),
3737 name: Some(function_name),
3738 is_async: false,
3739 is_generator: false,
3740 type_parameters: None,
3741 parameters: Vec::new(),
3742 return_type: Some(Node::new(
3743 NodeId::new(0),
3744 dummy(),
3745 TypeAnnotation {
3746 type_node: Box::new(Node::new(
3747 NodeId::new(0),
3748 dummy(),
3749 TypeNode::Keyword(KeywordType::Void),
3750 )),
3751 },
3752 )),
3753 body: None,
3754 },
3755 }));
3756 let file = b.finish(vec![function]);
3757 let output = emit(&file, EmitOptions::declaration());
3758 assert_eq!(output.code, "declare function f(): void;\n");
3759 }
3760
3761 #[test]
3762 fn union_type_parenthesizes_function_members() {
3763 let mut b = Builder::new();
3764 let alias_name = b.ident("U");
3765 let func_type = Node::new(
3766 NodeId::new(0),
3767 dummy(),
3768 TypeNode::Function(FunctionType {
3769 type_parameters: None,
3770 parameters: Vec::new(),
3771 return_type: Box::new(Node::new(
3772 NodeId::new(0),
3773 dummy(),
3774 TypeNode::Keyword(KeywordType::Void),
3775 )),
3776 }),
3777 );
3778 let number = Node::new(
3779 NodeId::new(0),
3780 dummy(),
3781 TypeNode::Keyword(KeywordType::Number),
3782 );
3783 let union = Node::new(
3784 NodeId::new(0),
3785 dummy(),
3786 TypeNode::Union(vec![func_type, number]),
3787 );
3788 let alias = stmt(Statement::TypeAlias(TypeAliasDeclaration {
3789 name: alias_name,
3790 type_parameters: None,
3791 type_node: Box::new(union),
3792 }));
3793 let file = b.finish(vec![alias]);
3794 let output = emit(&file, EmitOptions::declaration());
3795 assert_eq!(output.code, "type U = (() => void) | number;\n");
3796 }
3797
3798 #[test]
3799 fn optional_call_and_member_chain_round_trips() {
3800 let mut b = Builder::new();
3801 let object = b.ident_expr("a");
3802 let member = expr(Expression::Member(MemberExpression {
3803 object: Box::new(object),
3804 property: MemberProperty::Named(b.ident("b")),
3805 optional: true,
3806 }));
3807 let call = expr(Expression::Call(CallExpression {
3808 callee: Box::new(member),
3809 optional: true,
3810 type_arguments: None,
3811 arguments: Vec::new(),
3812 }));
3813 let file = b.finish(vec![expr_stmt(call)]);
3814 assert_eq!(emit_js(&file).code, "a?.b?.();\n");
3815 }
3816
3817 #[test]
3818 fn conditional_test_lower_precedence_gets_parentheses() {
3819 let mut b = Builder::new();
3820 let bb = b.ident_expr("b");
3821 let c = b.ident_expr("c");
3822 let d = b.ident_expr("d");
3823 let assign = expr(Expression::Assignment(AssignmentExpression {
3825 operator: AssignmentOperator::Assign,
3826 left: Node::new(
3827 NodeId::new(0),
3828 dummy(),
3829 AssignmentTarget::Identifier(b.ident("a2")),
3830 ),
3831 right: Box::new(bb),
3832 }));
3833 let conditional = expr(Expression::Conditional(ConditionalExpression {
3834 test: Box::new(assign),
3835 consequent: Box::new(c),
3836 alternate: Box::new(d),
3837 }));
3838 let file = b.finish(vec![expr_stmt(conditional)]);
3839 assert_eq!(emit_js(&file).code, "(a2 = b) ? c : d;\n");
3840 }
3841
3842 #[test]
3843 fn export_type_reexport_with_source_erased_in_js() {
3844 let mut b = Builder::new();
3845 let specifier = Node::new(
3846 NodeId::new(0),
3847 dummy(),
3848 ExportSpecifier {
3849 mode: ExportSpecifierMode::TypeOnly,
3850 local: ModuleExportName::Identifier(b.ident("A")),
3851 exported: ModuleExportName::Identifier(b.ident("A")),
3852 },
3853 );
3854 let export_stmt = stmt(Statement::Export(ExportDeclaration::Named(
3855 ExportNamedDeclaration::Specifiers {
3856 type_only: false,
3857 specifiers: vec![specifier],
3858 source: Some(b.string("\"./mod\"")),
3859 attributes: None,
3860 },
3861 )));
3862 let file = b.finish(vec![export_stmt]);
3863 assert_eq!(emit_js(&file).code, "");
3864 }
3865
3866 #[test]
3867 fn mixed_type_and_value_reexport_retains_value_exports() {
3868 let mut b = Builder::new();
3869 let type_spec = Node::new(
3870 NodeId::new(0),
3871 dummy(),
3872 ExportSpecifier {
3873 mode: ExportSpecifierMode::TypeOnly,
3874 local: ModuleExportName::Identifier(b.ident("A")),
3875 exported: ModuleExportName::Identifier(b.ident("A")),
3876 },
3877 );
3878 let val_spec = Node::new(
3879 NodeId::new(0),
3880 dummy(),
3881 ExportSpecifier {
3882 mode: ExportSpecifierMode::Value,
3883 local: ModuleExportName::Identifier(b.ident("B")),
3884 exported: ModuleExportName::Identifier(b.ident("B")),
3885 },
3886 );
3887 let export_stmt = stmt(Statement::Export(ExportDeclaration::Named(
3888 ExportNamedDeclaration::Specifiers {
3889 type_only: false,
3890 specifiers: vec![type_spec, val_spec],
3891 source: Some(b.string("\"./mod\"")),
3892 attributes: None,
3893 },
3894 )));
3895 let file = b.finish(vec![export_stmt]);
3896 assert_eq!(emit_js(&file).code, "export { B } from \"./mod\";\n");
3897 }
3898}