espolar 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,85 +2,134 @@
2
2
  const EXPRESSIONS_PRECEDENCE = {
3
3
  ArrayPattern: 20,
4
4
  ObjectPattern: 20,
5
- ArrayExpression: 20,
6
- TaggedTemplateExpression: 20,
7
- ThisExpression: 20,
8
- Identifier: 20,
9
- TemplateLiteral: 20,
10
- Super: 20,
11
- SequenceExpression: 20,
12
- MemberExpression: 19,
13
- MetaProperty: 19,
14
- CallExpression: 19,
15
- ChainExpression: 19,
16
- ImportExpression: 19,
17
- NewExpression: 19,
5
+ ParenthesizedExpression: 18,
6
+ ThisExpression: 18,
7
+ Super: 18,
8
+ Identifier: 18,
9
+ PrivateIdentifier: 18,
18
10
  Literal: 18,
19
- TSSatisfiesExpression: 18,
20
- TSInstantiationExpression: 18,
21
- TSNonNullExpression: 18,
22
- TSTypeAssertion: 18,
23
- AwaitExpression: 17,
24
- ClassExpression: 17,
25
- FunctionExpression: 17,
26
- ObjectExpression: 17,
27
- UnaryExpression: 16,
28
- UpdateExpression: 16,
29
- TSAsExpression: 15,
30
- BinaryExpression: 14,
31
- LogicalExpression: 13,
32
- ConditionalExpression: 4,
33
- ArrowFunctionExpression: 3,
34
- AssignmentExpression: 3,
11
+ ClassExpression: 18,
12
+ FunctionExpression: 18,
13
+ ObjectExpression: 18,
14
+ ArrayExpression: 18,
15
+ TemplateLiteral: 18,
16
+ JSXElement: 18,
17
+ JSXFragment: 18,
18
+ MetaProperty: 17,
19
+ MemberExpression: 17,
20
+ TSNonNullExpression: 17,
21
+ ChainExpression: 17,
22
+ NewExpression: 17,
23
+ CallExpression: 17,
24
+ TaggedTemplateExpression: 17,
25
+ ImportExpression: 17,
26
+ TSInstantiationExpression: 16.5,
27
+ UpdateExpression: 15,
28
+ UnaryExpression: 14,
29
+ AwaitExpression: 14,
30
+ TSTypeAssertion: 14,
31
+ BinaryExpression: 13,
32
+ TSAsExpression: 9,
33
+ TSSatisfiesExpression: 9,
34
+ LogicalExpression: 4,
35
+ AssignmentExpression: 2,
36
+ ConditionalExpression: 2,
35
37
  YieldExpression: 2,
36
- RestElement: 1
38
+ ArrowFunctionExpression: 2,
39
+ SpreadElement: 2,
40
+ SequenceExpression: 1
37
41
  };
38
42
  const OPERATOR_PRECEDENCE = {
39
- "||": 2,
40
- "&&": 3,
41
- "??": 4,
42
- "|": 5,
43
- "^": 6,
44
- "&": 7,
45
- "==": 8,
46
- "!=": 8,
47
- "===": 8,
48
- "!==": 8,
43
+ "**": 13,
44
+ "*": 12,
45
+ "%": 12,
46
+ "/": 12,
47
+ "+": 11,
48
+ "-": 11,
49
+ "<<": 10,
50
+ ">>": 10,
51
+ ">>>": 10,
49
52
  "<": 9,
50
53
  ">": 9,
51
54
  "<=": 9,
52
55
  ">=": 9,
53
56
  in: 9,
54
57
  instanceof: 9,
55
- "<<": 10,
56
- ">>": 10,
57
- ">>>": 10,
58
- "+": 11,
59
- "-": 11,
60
- "*": 12,
61
- "%": 12,
62
- "/": 12,
63
- "**": 13
58
+ "==": 8,
59
+ "!=": 8,
60
+ "===": 8,
61
+ "!==": 8,
62
+ "&": 7,
63
+ "^": 6,
64
+ "|": 5,
65
+ "&&": 4,
66
+ "??": 3,
67
+ "||": 3
68
+ };
69
+ const ASSOCIATIVE = {
70
+ [EXPRESSIONS_PRECEDENCE.MemberExpression]: "left",
71
+ [EXPRESSIONS_PRECEDENCE.UpdateExpression]: "left",
72
+ [EXPRESSIONS_PRECEDENCE.UnaryExpression]: "right",
73
+ [OPERATOR_PRECEDENCE["**"]]: "right",
74
+ [OPERATOR_PRECEDENCE["*"]]: "left",
75
+ [OPERATOR_PRECEDENCE["+"]]: "left",
76
+ [OPERATOR_PRECEDENCE["<"]]: "left",
77
+ [OPERATOR_PRECEDENCE["==="]]: "left",
78
+ [OPERATOR_PRECEDENCE["&"]]: "left",
79
+ [OPERATOR_PRECEDENCE["^"]]: "left",
80
+ [OPERATOR_PRECEDENCE["|"]]: "left",
81
+ [OPERATOR_PRECEDENCE["&&"]]: "left",
82
+ [OPERATOR_PRECEDENCE["||"]]: "left",
83
+ [EXPRESSIONS_PRECEDENCE.AssignmentExpression]: "right"
64
84
  };
85
+ function getPrecedence(node) {
86
+ if (node.type === "BinaryExpression" || node.type === "LogicalExpression") return OPERATOR_PRECEDENCE[node.operator] ?? EXPRESSIONS_PRECEDENCE[node.type];
87
+ return EXPRESSIONS_PRECEDENCE[node.type] ?? 20;
88
+ }
89
+ /**
90
+ * Check whether the operand of a Binary/Logical/AssignmentExpression needs parentheses.
91
+ * @param node
92
+ * @param parent
93
+ * @param where
94
+ * @returns
95
+ */
96
+ function operandOfBinaryExprNeedsParens(node, parent, where) {
97
+ if (where === "left" && (node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression") && parent.type === "BinaryExpression") return parent.operator === "&" || parent.operator === "|";
98
+ if (node.type === "LogicalExpression" && parent.type === "LogicalExpression" && parent.operator === "??" !== (node.operator === "??")) return true;
99
+ const precedence = getPrecedence(node);
100
+ const parentPrecedence = getPrecedence(parent);
101
+ if (parent.type === "BinaryExpression" && parent.operator === "**" && precedence === EXPRESSIONS_PRECEDENCE.UnaryExpression) return true;
102
+ if (precedence !== parentPrecedence) return precedence < parentPrecedence;
103
+ if (precedence === EXPRESSIONS_PRECEDENCE.MemberExpression && node.type === "ChainExpression") return true;
104
+ if (parent.type === "NewExpression" && !validUnparenthesizedNewOperand(node)) return true;
105
+ return (ASSOCIATIVE[precedence] ?? "left") !== where;
106
+ }
107
+ /**
108
+ * A valid unparenthesized `new` operand must be a member chain
109
+ * which not contains a CallExpression
110
+ */
111
+ function validUnparenthesizedNewOperand(node) {
112
+ let cur = node;
113
+ while (true) if (cur.type === "CallExpression") return false;
114
+ else if (cur.type === "TSNonNullExpression") cur = cur.expression;
115
+ else if (cur.type === "MemberExpression") cur = cur.object;
116
+ else if (cur.type === "TaggedTemplateExpression") cur = cur.tag;
117
+ else if (cur.type === "MetaProperty" || cur.type === "NewExpression" || cur.type === "ImportExpression") return true;
118
+ else return cur !== node;
119
+ }
120
+ function operandOfUnaryExprNeedsParens(node) {
121
+ return EXPRESSIONS_PRECEDENCE[node.type] < EXPRESSIONS_PRECEDENCE.UnaryExpression;
122
+ }
123
+ function expectAssignmentExprNeedsParen(node) {
124
+ return EXPRESSIONS_PRECEDENCE[node.type] < EXPRESSIONS_PRECEDENCE.AssignmentExpression;
125
+ }
126
+ function expectLHSExprNeedsParen(node) {
127
+ return EXPRESSIONS_PRECEDENCE[node.type] < EXPRESSIONS_PRECEDENCE.MemberExpression;
128
+ }
65
129
  function commentNeedsNewline(comment) {
66
130
  if (comment.type === "Line") return true;
67
131
  return comment.value.includes("\n");
68
132
  }
69
- function needsParens(node, parent, isRight) {
70
- if (node.type === "PrivateIdentifier" || node.type === "Identifier" || node.type === "Super") return false;
71
- if (node.type === "LogicalExpression" && parent.type === "LogicalExpression" && parent.operator === "??" !== (node.operator === "??")) return true;
72
- const precedence = EXPRESSIONS_PRECEDENCE[node.type] ?? 20;
73
- const parentPrecedence = EXPRESSIONS_PRECEDENCE[parent.type] ?? 20;
74
- if (precedence !== parentPrecedence) {
75
- if (!isRight && precedence === 15 && parentPrecedence === 14 && parent.operator === "**") return false;
76
- return precedence < parentPrecedence;
77
- }
78
- if (precedence !== 13 && precedence !== 14) return false;
79
- const nodeOp = node.operator;
80
- if (nodeOp === "**" && parent.operator === "**") return !isRight;
81
- if (isRight) return OPERATOR_PRECEDENCE[nodeOp] <= OPERATOR_PRECEDENCE[parent.operator];
82
- return OPERATOR_PRECEDENCE[nodeOp] < OPERATOR_PRECEDENCE[parent.operator];
83
- }
84
133
  function arrowConciseBodyNeedsWrap(body) {
85
134
  if (body.type === "BlockStatement") return false;
86
135
  switch (body.type) {
@@ -238,11 +287,47 @@ const defaultPrinters = {
238
287
  TSIntrinsicKeyword: printKeywordType
239
288
  };
240
289
  function printProgram(program, context) {
241
- context.writeNodeListWithSourceGaps(program.body, "\n");
290
+ context.writeNodeListWithNewLineSep(program.body);
291
+ }
292
+ function canStartExpressionStatement(node) {
293
+ let lhs;
294
+ switch (node.type) {
295
+ default: return true;
296
+ case "ObjectExpression":
297
+ case "FunctionExpression":
298
+ case "ClassExpression":
299
+ case "ObjectPattern": return false;
300
+ case "AssignmentExpression":
301
+ case "LogicalExpression":
302
+ case "BinaryExpression":
303
+ lhs = node.left;
304
+ break;
305
+ case "TSAsExpression":
306
+ case "TSSatisfiesExpression":
307
+ case "TSNonNullExpression":
308
+ lhs = node.expression;
309
+ break;
310
+ case "CallExpression":
311
+ lhs = node.callee;
312
+ break;
313
+ case "MemberExpression":
314
+ lhs = node.object;
315
+ break;
316
+ case "TaggedTemplateExpression":
317
+ lhs = node.tag;
318
+ break;
319
+ case "ConditionalExpression":
320
+ lhs = node.test;
321
+ break;
322
+ case "SequenceExpression": return canStartExpressionStatement(node.expressions[0]);
323
+ case "UpdateExpression": return canStartExpressionStatement(node.argument);
324
+ case "ChainExpression": return canStartExpressionStatement(node.expression);
325
+ }
326
+ return operandOfBinaryExprNeedsParens(lhs, node, "left") || canStartExpressionStatement(lhs);
242
327
  }
243
328
  function printExpressionStatement(statement, context) {
244
329
  const expr = statement.expression;
245
- if (expr.type === "ObjectExpression" || expr.type === "FunctionExpression" || expr.type === "AssignmentExpression" && expr.left.type === "ObjectPattern") {
330
+ if (!canStartExpressionStatement(expr)) {
246
331
  context.write("(");
247
332
  context.writeNode(expr);
248
333
  context.write(");");
@@ -266,7 +351,11 @@ function printVariableDeclarator(declarator, context) {
266
351
  if (declarator.definite === true) context.write("!");
267
352
  if (declarator.init) {
268
353
  context.write(" = ");
269
- context.writeNode(declarator.init);
354
+ if (expectAssignmentExprNeedsParen(declarator.init)) {
355
+ context.write("(");
356
+ context.writeNode(declarator.init);
357
+ context.write(")");
358
+ } else context.writeNode(declarator.init);
270
359
  }
271
360
  }
272
361
  function printBlockStatement(block, context) {
@@ -274,7 +363,7 @@ function printBlockStatement(block, context) {
274
363
  context.write("{");
275
364
  if (body.length > 0) {
276
365
  context.write("\n");
277
- context.writeNodeListWithSourceGaps(body, "\n");
366
+ context.writeNodeListWithNewLineSep(body);
278
367
  context.write("\n");
279
368
  }
280
369
  context.write("}");
@@ -443,12 +532,14 @@ function printLiteral(literal, context) {
443
532
  function printUnaryExpression(expr, context) {
444
533
  context.write(expr.operator);
445
534
  if (expr.operator.length > 1) context.write(" ");
446
- const argPrec = EXPRESSIONS_PRECEDENCE[expr.argument.type];
447
- if (argPrec != null && argPrec < EXPRESSIONS_PRECEDENCE.UnaryExpression) {
535
+ if (operandOfUnaryExprNeedsParens(expr.argument)) {
448
536
  context.write("(");
449
537
  context.writeNode(expr.argument);
450
538
  context.write(")");
451
- } else context.writeNode(expr.argument);
539
+ } else {
540
+ if (expr.operator.length === 1 && (expr.argument.type === "UnaryExpression" || expr.argument.type === "UpdateExpression") && expr.argument.operator.startsWith(expr.operator)) context.write(" ");
541
+ context.writeNode(expr.argument);
542
+ }
452
543
  }
453
544
  function printUpdateExpression(expr, context) {
454
545
  if (expr.prefix === true) {
@@ -465,7 +556,7 @@ function printUpdateExpression(expr, context) {
465
556
  function printBinaryExpression(expression, context) {
466
557
  const left = expression.left;
467
558
  const right = expression.right;
468
- if (needsParens(left, expression, false)) {
559
+ if (operandOfBinaryExprNeedsParens(left, expression, "left")) {
469
560
  context.write("(");
470
561
  context.writeNode(left);
471
562
  context.write(")");
@@ -473,14 +564,14 @@ function printBinaryExpression(expression, context) {
473
564
  context.write(" ");
474
565
  context.write(String(expression.operator));
475
566
  context.write(" ");
476
- if (needsParens(right, expression, true)) {
567
+ if (operandOfBinaryExprNeedsParens(right, expression, "right")) {
477
568
  context.write("(");
478
569
  context.writeNode(right);
479
570
  context.write(")");
480
571
  } else context.writeNode(right);
481
572
  }
482
573
  function printConditionalExpression(expr, context) {
483
- if ((EXPRESSIONS_PRECEDENCE[expr.test.type] ?? 20) <= EXPRESSIONS_PRECEDENCE.ConditionalExpression) {
574
+ if (operandOfBinaryExprNeedsParens(expr.test, expr, "left")) {
484
575
  context.write("(");
485
576
  context.writeNode(expr.test);
486
577
  context.write(")");
@@ -488,39 +579,39 @@ function printConditionalExpression(expr, context) {
488
579
  context.write(" ? ");
489
580
  context.writeNode(expr.consequent);
490
581
  context.write(" : ");
491
- context.writeNode(expr.alternate);
582
+ if (operandOfBinaryExprNeedsParens(expr.alternate, expr, "right")) {
583
+ context.write("(");
584
+ context.writeNode(expr.alternate);
585
+ context.write(")");
586
+ } else context.writeNode(expr.alternate);
492
587
  }
493
588
  function printYieldExpression(expr, context) {
494
589
  context.write(expr.delegate === true ? "yield*" : "yield");
495
590
  if (expr.argument) {
496
591
  context.write(" ");
497
- const needsParensASi = (context.options.getLeadingComments?.(expr.argument))?.some((c) => commentNeedsNewline(c)) ?? false;
498
- if (needsParensASi) context.write("(");
499
- context.writeNode(expr.argument);
500
- if (needsParensASi) context.write(")");
592
+ if (((context.options.getLeadingComments?.(expr.argument))?.some((c) => commentNeedsNewline(c)) ?? false) || expectAssignmentExprNeedsParen(expr.argument)) {
593
+ context.write("(");
594
+ context.writeNode(expr.argument);
595
+ context.write(")");
596
+ } else context.writeNode(expr.argument);
501
597
  }
502
598
  }
503
599
  function printAwaitExpression(expr, context) {
504
600
  context.write("await");
505
- if (expr.argument) {
506
- const argPrec = EXPRESSIONS_PRECEDENCE[expr.argument.type];
507
- if (argPrec != null && argPrec < EXPRESSIONS_PRECEDENCE.AwaitExpression) {
508
- context.write(" (");
509
- context.writeNode(expr.argument);
510
- context.write(")");
511
- } else {
512
- context.write(" ");
513
- context.writeNode(expr.argument);
514
- }
601
+ if (expr.argument) if (operandOfUnaryExprNeedsParens(expr.argument)) {
602
+ context.write(" (");
603
+ context.writeNode(expr.argument);
604
+ context.write(")");
605
+ } else {
606
+ context.write(" ");
607
+ context.writeNode(expr.argument);
515
608
  }
516
609
  }
517
610
  function printSequenceExpression(expr, context) {
518
- context.write("(");
519
611
  context.writeNodeList(expr.expressions, ", ");
520
- context.write(")");
521
612
  }
522
613
  function printCallExpression(expression, context) {
523
- if ((EXPRESSIONS_PRECEDENCE[expression.callee.type] ?? 20) < EXPRESSIONS_PRECEDENCE.CallExpression) {
614
+ if (operandOfBinaryExprNeedsParens(expression.callee, expression, "left")) {
524
615
  context.write("(");
525
616
  context.writeNode(expression.callee);
526
617
  context.write(")");
@@ -530,12 +621,12 @@ function printCallExpression(expression, context) {
530
621
  const parenRange = context.options.experimentalGetLeftParenSourceRange?.(expression);
531
622
  if (parenRange) context.writeMapped("(", parenRange.start, parenRange.end);
532
623
  else context.write("(");
533
- context.writeNodeList(expression.arguments, ", ");
624
+ context.writeExpressionListWithCommaSep(expression.arguments);
534
625
  context.write(")");
535
626
  }
536
627
  function printNewExpression(expression, context) {
537
628
  context.write("new ");
538
- if ((EXPRESSIONS_PRECEDENCE[expression.callee.type] ?? 20) < EXPRESSIONS_PRECEDENCE.NewExpression || hasCallExpression(expression.callee)) {
629
+ if (operandOfBinaryExprNeedsParens(expression.callee, expression, "left")) {
539
630
  context.write("(");
540
631
  context.writeNode(expression.callee);
541
632
  context.write(")");
@@ -544,23 +635,14 @@ function printNewExpression(expression, context) {
544
635
  const parenRange = context.options.experimentalGetLeftParenSourceRange?.(expression);
545
636
  if (parenRange) context.writeMapped("(", parenRange.start, parenRange.end);
546
637
  else context.write("(");
547
- context.writeNodeList(expression.arguments, ", ");
638
+ context.writeExpressionListWithCommaSep(expression.arguments);
548
639
  context.write(")");
549
640
  }
550
- function hasCallExpression(node) {
551
- let cur = node;
552
- while (cur) {
553
- if (cur.type === "CallExpression") return true;
554
- if (cur.type === "MemberExpression") cur = cur.object;
555
- else return false;
556
- }
557
- return false;
558
- }
559
641
  function printChainExpression(expression, context) {
560
642
  context.writeNode(expression.expression);
561
643
  }
562
644
  function printMemberExpression(expression, context) {
563
- if ((EXPRESSIONS_PRECEDENCE[expression.object.type] ?? 20) < EXPRESSIONS_PRECEDENCE.MemberExpression) {
645
+ if (operandOfBinaryExprNeedsParens(expression.object, expression, "left")) {
564
646
  context.write("(");
565
647
  context.writeNode(expression.object);
566
648
  context.write(")");
@@ -587,7 +669,7 @@ function printObjectPattern(pattern, context) {
587
669
  }
588
670
  function printArrayExpression(array, context) {
589
671
  context.write("[");
590
- context.writeNodeList(array.elements, ", ");
672
+ context.writeExpressionListWithCommaSep(array.elements);
591
673
  context.write("]");
592
674
  }
593
675
  function printArrayPattern(pattern, context) {
@@ -635,7 +717,11 @@ function printProperty(property, context) {
635
717
  }
636
718
  function printSpreadElement(spread, context) {
637
719
  context.write("...");
638
- context.writeNode(spread.argument);
720
+ if (expectAssignmentExprNeedsParen(spread.argument)) {
721
+ context.write("(");
722
+ context.writeNode(spread.argument);
723
+ context.write(")");
724
+ } else context.writeNode(spread.argument);
639
725
  }
640
726
  function printRestElement(rest, context) {
641
727
  context.write("...");
@@ -660,7 +746,12 @@ function printTemplateLiteral(node, context) {
660
746
  context.write("`");
661
747
  }
662
748
  function printTaggedTemplateExpression(node, context) {
663
- context.writeNode(node.tag);
749
+ if (operandOfBinaryExprNeedsParens(node.tag, node, "left")) {
750
+ context.write("(");
751
+ context.writeNode(node.tag);
752
+ context.write(")");
753
+ } else context.writeNode(node.tag);
754
+ if (node.typeArguments) context.writeNode(node.typeArguments);
664
755
  context.writeNode(node.quasi);
665
756
  }
666
757
  function printThisExpression(_node, context) {
@@ -735,7 +826,11 @@ function printClass(node, context) {
735
826
  }
736
827
  if (node.superClass) {
737
828
  context.write("extends ");
738
- context.writeNode(node.superClass);
829
+ if (expectLHSExprNeedsParen(node.superClass)) {
830
+ context.write("(");
831
+ context.writeNode(node.superClass);
832
+ context.write(")");
833
+ } else context.writeNode(node.superClass);
739
834
  if (node.superTypeArguments) context.writeNode(node.superTypeArguments);
740
835
  else if (node.superTypeParameters) context.writeNode(node.superTypeParameters);
741
836
  }
@@ -751,7 +846,7 @@ function printClassBody(node, context) {
751
846
  const body = node.body;
752
847
  if (body.length > 0) {
753
848
  context.write("\n");
754
- context.writeNodeListWithSourceGaps(body, "\n");
849
+ context.writeNodeListWithNewLineSep(body);
755
850
  context.write("\n");
756
851
  }
757
852
  context.write("}");
@@ -761,14 +856,28 @@ function printStaticBlock(node, context) {
761
856
  const body = node.body;
762
857
  if (body.length > 0) {
763
858
  context.write("\n");
764
- context.writeNodeListWithSourceGaps(body, "\n");
859
+ context.writeNodeListWithNewLineSep(body);
765
860
  context.write("\n");
766
861
  }
767
862
  context.write("}");
768
863
  }
864
+ function validUnparenthesizedDecorator(node) {
865
+ let current = node;
866
+ if (current.type === "CallExpression") current = current.callee;
867
+ if (current.type === "TSInstantiationExpression") current = current.expression;
868
+ while (true) if (current.type === "Identifier") return true;
869
+ else if (current.type === "MemberExpression") {
870
+ if (current.computed) return false;
871
+ current = current.object;
872
+ } else return false;
873
+ }
769
874
  function printDecorator(node, context) {
770
875
  context.write("@");
771
- context.writeNode(node.expression);
876
+ if (!validUnparenthesizedDecorator(node.expression)) {
877
+ context.write("(");
878
+ context.writeNode(node.expression);
879
+ context.write(")");
880
+ } else context.writeNode(node.expression);
772
881
  context.write("\n");
773
882
  }
774
883
  function printPropertyDefinition(node, context) {
@@ -933,7 +1042,7 @@ function printExportSpecifier(node, context) {
933
1042
  }
934
1043
  }
935
1044
  function printTSAsExpression(expression, context) {
936
- if ((EXPRESSIONS_PRECEDENCE[expression.expression.type] ?? 20) < EXPRESSIONS_PRECEDENCE.TSAsExpression) {
1045
+ if (operandOfBinaryExprNeedsParens(expression.expression, expression, "left")) {
937
1046
  context.write("(");
938
1047
  context.writeNode(expression.expression);
939
1048
  context.write(")");
@@ -942,7 +1051,7 @@ function printTSAsExpression(expression, context) {
942
1051
  context.writeNode(expression.typeAnnotation);
943
1052
  }
944
1053
  function printTSSatisfiesExpression(expression, context) {
945
- if ((EXPRESSIONS_PRECEDENCE[expression.expression.type] ?? 20) < EXPRESSIONS_PRECEDENCE.TSSatisfiesExpression) {
1054
+ if (operandOfBinaryExprNeedsParens(expression.expression, expression, "left")) {
946
1055
  context.write("(");
947
1056
  context.writeNode(expression.expression);
948
1057
  context.write(")");
@@ -954,14 +1063,18 @@ function printTSTypeAssertion(expression, context) {
954
1063
  context.write("<");
955
1064
  context.writeNode(expression.typeAnnotation);
956
1065
  context.write(">");
957
- if ((EXPRESSIONS_PRECEDENCE[expression.expression.type] ?? 20) < EXPRESSIONS_PRECEDENCE.TSTypeAssertion) {
1066
+ if (operandOfUnaryExprNeedsParens(expression.expression)) {
958
1067
  context.write("(");
959
1068
  context.writeNode(expression.expression);
960
1069
  context.write(")");
961
1070
  } else context.writeNode(expression.expression);
962
1071
  }
963
1072
  function printTSNonNullExpression(expression, context) {
964
- context.writeNode(expression.expression);
1073
+ if (operandOfBinaryExprNeedsParens(expression.expression, expression, "left")) {
1074
+ context.write("(");
1075
+ context.writeNode(expression.expression);
1076
+ context.write(")");
1077
+ } else context.writeNode(expression.expression);
965
1078
  context.write("!");
966
1079
  }
967
1080
  function printTSTypeAnnotation(annotation, context) {
@@ -1155,7 +1268,12 @@ function printTSTypeQuery(node, context) {
1155
1268
  context.writeNode(node.exprName);
1156
1269
  }
1157
1270
  function printTSMappedType(node, context) {
1158
- context.write("{ [");
1271
+ context.write("{ ");
1272
+ if (node.readonly) {
1273
+ if (typeof node.readonly === "string") context.write(node.readonly);
1274
+ context.write("readonly ");
1275
+ }
1276
+ context.write("[");
1159
1277
  const legacyTp = node.typeParameter;
1160
1278
  const key = node.key ?? legacyTp?.name;
1161
1279
  const constraint = node.constraint ?? legacyTp?.constraint;
@@ -1165,7 +1283,15 @@ function printTSMappedType(node, context) {
1165
1283
  context.write(" in ");
1166
1284
  context.writeNode(constraint);
1167
1285
  }
1286
+ if (node.nameType) {
1287
+ context.write(" as ");
1288
+ context.writeNode(node.nameType);
1289
+ }
1168
1290
  context.write("]");
1291
+ if (node.optional) {
1292
+ if (typeof node.optional === "string") context.write(node.optional);
1293
+ context.write("?");
1294
+ }
1169
1295
  if (node.typeAnnotation) {
1170
1296
  context.write(": ");
1171
1297
  context.writeNode(node.typeAnnotation);
@@ -1262,14 +1388,20 @@ function printTSModuleDeclaration(node, context) {
1262
1388
  context.write(String(kind) + " ");
1263
1389
  context.writeNode(node.id);
1264
1390
  }
1265
- if (node.body) {
1266
- if (node.body.type === "TSModuleBlock") context.write(" ");
1267
- context.writeNode(node.body);
1391
+ let body = node.body;
1392
+ while (body?.type === "TSModuleDeclaration") {
1393
+ context.write(".");
1394
+ context.writeNode(body.id);
1395
+ body = body.body;
1396
+ }
1397
+ if (body) {
1398
+ context.write(" ");
1399
+ context.writeNode(body);
1268
1400
  }
1269
1401
  }
1270
1402
  function printTSModuleBlock(node, context) {
1271
1403
  context.write("{\n");
1272
- context.writeNodeListWithSourceGaps(node.body, "\n");
1404
+ context.writeNodeListWithNewLineSep(node.body);
1273
1405
  context.write("\n}");
1274
1406
  }
1275
1407
  function printTSDeclareFunction(node, context) {
@@ -1304,7 +1436,11 @@ function printTSNamespaceExportDeclaration(node, context) {
1304
1436
  context.write(";");
1305
1437
  }
1306
1438
  function printTSInstantiationExpression(node, context) {
1307
- context.writeNode(node.expression);
1439
+ if (operandOfBinaryExprNeedsParens(node.expression, node, "left")) {
1440
+ context.write("(");
1441
+ context.writeNode(node.expression);
1442
+ context.write(")");
1443
+ } else context.writeNode(node.expression);
1308
1444
  context.writeNode(node.typeArguments);
1309
1445
  }
1310
1446
  function printTSParenthesizedType(node, context) {
@@ -1320,6 +1456,13 @@ function writeOptionalTypeAnnotation(node, context) {
1320
1456
  if (node.optional === true) context.write("?");
1321
1457
  if (node.typeAnnotation) context.writeNode(node.typeAnnotation);
1322
1458
  }
1459
+ function writeComment(comment, context) {
1460
+ if (comment.type === "Line") context.write("//" + comment.value + "\n");
1461
+ else {
1462
+ context.write("/*" + comment.value + "*/");
1463
+ if (comment.value.includes("\n")) context.write("\n");
1464
+ }
1465
+ }
1323
1466
  //#endregion
1324
1467
  //#region src/mappings.ts
1325
1468
  function getNodeRange(node) {
@@ -1368,13 +1511,6 @@ function toVolarMapping(mapping) {
1368
1511
  }
1369
1512
  //#endregion
1370
1513
  //#region src/printer.ts
1371
- function writeComment(context, comment) {
1372
- if (comment.type === "Line") context.write("//" + comment.value + "\n");
1373
- else {
1374
- context.write("/*" + comment.value + "*/");
1375
- if (comment.value.includes("\n")) context.write("\n");
1376
- }
1377
- }
1378
1514
  function print(node, options) {
1379
1515
  const context = createPrinterContext(options);
1380
1516
  context.writeNode(node);
@@ -1441,12 +1577,12 @@ function createPrinterContext(options) {
1441
1577
  const printer = printers[node.type];
1442
1578
  if (!printer) throw new Error(`No printer registered for node type ${node.type}`);
1443
1579
  const leadingComments = options.getLeadingComments?.(node);
1444
- if (leadingComments) for (const c of leadingComments) writeComment(context, c);
1580
+ if (leadingComments) for (const comment of leadingComments) writeComment(comment, context);
1445
1581
  const generatedStart = generatedOffset;
1446
1582
  printer(node, context);
1447
1583
  const generatedEnd = generatedOffset;
1448
1584
  const trailingComments = options.getTrailingComments?.(node);
1449
- if (trailingComments) for (const c of trailingComments) writeComment(context, c);
1585
+ if (trailingComments) for (const comment of trailingComments) writeComment(comment, context);
1450
1586
  const lastMappingGeneratedEnd = mappings.at(-1)?.generatedEnd ?? 0;
1451
1587
  if (range && lastMappingGeneratedEnd <= generatedStart) appendMapping(range, generatedStart, generatedEnd, getMappingData(node));
1452
1588
  },
@@ -1462,14 +1598,30 @@ function createPrinterContext(options) {
1462
1598
  needsSeparator = true;
1463
1599
  }
1464
1600
  },
1465
- writeNodeListWithSourceGaps(nodes, fallbackSeparator) {
1601
+ writeExpressionListWithCommaSep(nodes) {
1602
+ let needsSeparator = false;
1603
+ for (const node of nodes) {
1604
+ if (!node) {
1605
+ if (needsSeparator) context.write(", ");
1606
+ continue;
1607
+ }
1608
+ if (needsSeparator) context.write(", ");
1609
+ if (expectAssignmentExprNeedsParen(node)) {
1610
+ context.write("(");
1611
+ context.writeNode(node);
1612
+ context.write(")");
1613
+ } else context.writeNode(node);
1614
+ needsSeparator = true;
1615
+ }
1616
+ },
1617
+ writeNodeListWithNewLineSep(nodes) {
1466
1618
  let lastRangeEnd;
1467
1619
  let wroteNode = false;
1468
1620
  for (const node of nodes) {
1469
1621
  if (!node) continue;
1470
1622
  const range = getNodeRange(node);
1471
1623
  if (wroteNode) if (lastRangeEnd !== void 0 && range && range.start >= lastRangeEnd) context.writeSource(lastRangeEnd, range.start, getMappingData(null));
1472
- else context.write(fallbackSeparator);
1624
+ else context.write("\n");
1473
1625
  context.writeNode(node);
1474
1626
  wroteNode = true;
1475
1627
  if (range) lastRangeEnd = range.end;