esrap 2.2.11 → 2.2.13
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/package.json +1 -1
- package/src/languages/ts/index.js +255 -152
package/package.json
CHANGED
|
@@ -511,23 +511,11 @@ export default (options = {}) => {
|
|
|
511
511
|
// // Avoids confusion in `for` loops initializers
|
|
512
512
|
// chunks.write('(');
|
|
513
513
|
// }
|
|
514
|
-
|
|
515
|
-
context.write('(');
|
|
516
|
-
context.visit(node.left);
|
|
517
|
-
context.write(')');
|
|
518
|
-
} else {
|
|
519
|
-
context.visit(node.left);
|
|
520
|
-
}
|
|
514
|
+
maybe_wrap(context, node.left, operand_needs_wrap(node.left, node, false));
|
|
521
515
|
|
|
522
516
|
context.write(` ${node.operator} `);
|
|
523
517
|
|
|
524
|
-
|
|
525
|
-
context.write('(');
|
|
526
|
-
context.visit(node.right);
|
|
527
|
-
context.write(')');
|
|
528
|
-
} else {
|
|
529
|
-
context.visit(node.right);
|
|
530
|
-
}
|
|
518
|
+
maybe_wrap(context, node.right, operand_needs_wrap(node.right, node, true));
|
|
531
519
|
},
|
|
532
520
|
|
|
533
521
|
/**
|
|
@@ -575,17 +563,11 @@ export default (options = {}) => {
|
|
|
575
563
|
write_keyword(context, node, 'new', ' ');
|
|
576
564
|
}
|
|
577
565
|
|
|
578
|
-
const
|
|
566
|
+
const wrap =
|
|
567
|
+
node.callee.type === 'ChainExpression' ||
|
|
579
568
|
EXPRESSIONS_PRECEDENCE[node.callee.type] < EXPRESSIONS_PRECEDENCE.CallExpression ||
|
|
580
569
|
(node.type === 'NewExpression' && has_call_expression(node.callee));
|
|
581
|
-
|
|
582
|
-
if (needs_parens) {
|
|
583
|
-
context.write('(');
|
|
584
|
-
context.visit(node.callee);
|
|
585
|
-
context.write(')');
|
|
586
|
-
} else {
|
|
587
|
-
context.visit(node.callee);
|
|
588
|
-
}
|
|
570
|
+
maybe_wrap(context, node.callee, wrap);
|
|
589
571
|
|
|
590
572
|
if (/** @type {TSESTree.CallExpression} */ (node).optional) {
|
|
591
573
|
context.write('?.');
|
|
@@ -671,12 +653,25 @@ export default (options = {}) => {
|
|
|
671
653
|
|
|
672
654
|
if (node.id) {
|
|
673
655
|
context.visit(node.id);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
if (node.typeParameters) {
|
|
659
|
+
context.visit(node.typeParameters);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
if (node.id || node.typeParameters) {
|
|
674
663
|
context.write(' ');
|
|
675
664
|
}
|
|
676
665
|
|
|
677
666
|
if (node.superClass) {
|
|
678
667
|
context.write('extends ');
|
|
668
|
+
// the `extends` clause is a LeftHandSideExpression; anything lower (a
|
|
669
|
+
// logical/binary/conditional/etc.) must be parenthesized
|
|
670
|
+
const wrap_super =
|
|
671
|
+
EXPRESSIONS_PRECEDENCE[node.superClass.type] < EXPRESSIONS_PRECEDENCE.NewExpression;
|
|
672
|
+
if (wrap_super) context.write('(');
|
|
679
673
|
context.visit(node.superClass);
|
|
674
|
+
if (wrap_super) context.write(')');
|
|
680
675
|
|
|
681
676
|
// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
|
|
682
677
|
var type_arguments = node.superTypeParameters ?? node.superTypeArguments;
|
|
@@ -813,6 +808,12 @@ export default (options = {}) => {
|
|
|
813
808
|
context.visit(node.key);
|
|
814
809
|
if (node.computed) context.write(']');
|
|
815
810
|
|
|
811
|
+
// optional method (`m?()`)
|
|
812
|
+
if (node.optional) context.write('?');
|
|
813
|
+
|
|
814
|
+
// @ts-expect-error `typeParameters` lives on the method node, not its value
|
|
815
|
+
if (node.typeParameters) context.visit(node.typeParameters);
|
|
816
|
+
|
|
816
817
|
context.write('(');
|
|
817
818
|
sequence(
|
|
818
819
|
context,
|
|
@@ -845,6 +846,8 @@ export default (options = {}) => {
|
|
|
845
846
|
|
|
846
847
|
const kw = create_keyword_write(context, node, field_modifiers_keywords_map_ok);
|
|
847
848
|
|
|
849
|
+
if (node.declare) kw('declare ');
|
|
850
|
+
|
|
848
851
|
if (node.accessibility) {
|
|
849
852
|
kw(node.accessibility + ' ');
|
|
850
853
|
}
|
|
@@ -862,6 +865,10 @@ export default (options = {}) => {
|
|
|
862
865
|
kw('static ');
|
|
863
866
|
}
|
|
864
867
|
|
|
868
|
+
if (node.override) kw('override ');
|
|
869
|
+
|
|
870
|
+
if (node.readonly) kw('readonly ');
|
|
871
|
+
|
|
865
872
|
if (
|
|
866
873
|
// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
|
|
867
874
|
node.accessor ||
|
|
@@ -879,6 +886,10 @@ export default (options = {}) => {
|
|
|
879
886
|
context.visit(node.key);
|
|
880
887
|
}
|
|
881
888
|
|
|
889
|
+
// `x?: T` (optional) / `x!: T` (definite assignment)
|
|
890
|
+
if (node.optional) context.write('?');
|
|
891
|
+
else if (node.definite) context.write('!');
|
|
892
|
+
|
|
882
893
|
if (node.typeAnnotation) {
|
|
883
894
|
if (node.type === 'AccessorProperty' || node.type === 'TSAbstractAccessorProperty') {
|
|
884
895
|
context.visit(node.typeAnnotation);
|
|
@@ -926,7 +937,6 @@ export default (options = {}) => {
|
|
|
926
937
|
}
|
|
927
938
|
|
|
928
939
|
context.write('(');
|
|
929
|
-
|
|
930
940
|
sequence(
|
|
931
941
|
context,
|
|
932
942
|
// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
|
|
@@ -953,7 +963,6 @@ export default (options = {}) => {
|
|
|
953
963
|
if (node.typeParameters) context.visit(node.typeParameters);
|
|
954
964
|
|
|
955
965
|
context.write('(');
|
|
956
|
-
|
|
957
966
|
sequence(
|
|
958
967
|
context,
|
|
959
968
|
// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
|
|
@@ -964,8 +973,9 @@ export default (options = {}) => {
|
|
|
964
973
|
null,
|
|
965
974
|
false
|
|
966
975
|
);
|
|
976
|
+
context.write(')');
|
|
967
977
|
|
|
968
|
-
context.write('
|
|
978
|
+
context.write(' => ');
|
|
969
979
|
|
|
970
980
|
// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
|
|
971
981
|
context.visit(node.typeAnnotation?.typeAnnotation ?? node.returnType?.typeAnnotation);
|
|
@@ -1011,13 +1021,7 @@ export default (options = {}) => {
|
|
|
1011
1021
|
|
|
1012
1022
|
context.write(' => ');
|
|
1013
1023
|
|
|
1014
|
-
|
|
1015
|
-
context.write('(');
|
|
1016
|
-
context.visit(node.body);
|
|
1017
|
-
context.write(')');
|
|
1018
|
-
} else {
|
|
1019
|
-
context.visit(node.body);
|
|
1020
|
-
}
|
|
1024
|
+
maybe_wrap(context, node.body, arrow_concise_body_needs_wrap(node.body));
|
|
1021
1025
|
},
|
|
1022
1026
|
|
|
1023
1027
|
AssignmentExpression(node, context) {
|
|
@@ -1076,13 +1080,9 @@ export default (options = {}) => {
|
|
|
1076
1080
|
ClassExpression: shared['ClassDeclaration|ClassExpression'],
|
|
1077
1081
|
|
|
1078
1082
|
ConditionalExpression(node, context) {
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
context.write('(');
|
|
1083
|
-
context.visit(node.test);
|
|
1084
|
-
context.write(')');
|
|
1085
|
-
}
|
|
1083
|
+
const wrap =
|
|
1084
|
+
EXPRESSIONS_PRECEDENCE[node.test.type] <= EXPRESSIONS_PRECEDENCE.ConditionalExpression;
|
|
1085
|
+
maybe_wrap(context, node.test, wrap);
|
|
1086
1086
|
|
|
1087
1087
|
const consequent = context.new();
|
|
1088
1088
|
const alternate = context.new();
|
|
@@ -1130,7 +1130,14 @@ export default (options = {}) => {
|
|
|
1130
1130
|
|
|
1131
1131
|
Decorator(node, context) {
|
|
1132
1132
|
context.write('@');
|
|
1133
|
+
// a decorator must be an identifier/member/call (or parenthesized); anything
|
|
1134
|
+
// else (ternary, logical, assignment, unary, `as`, optional chain…) needs wrapping
|
|
1135
|
+
const wrap =
|
|
1136
|
+
/** @type {string} */ (node.expression.type) === 'ChainExpression' ||
|
|
1137
|
+
EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.CallExpression;
|
|
1138
|
+
if (wrap) context.write('(');
|
|
1133
1139
|
context.visit(node.expression);
|
|
1140
|
+
if (wrap) context.write(')');
|
|
1134
1141
|
context.newline();
|
|
1135
1142
|
},
|
|
1136
1143
|
|
|
@@ -1240,20 +1247,9 @@ export default (options = {}) => {
|
|
|
1240
1247
|
},
|
|
1241
1248
|
|
|
1242
1249
|
ExpressionStatement(node, context) {
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
node.expression.left.type === 'ObjectPattern') ||
|
|
1247
|
-
node.expression.type === 'FunctionExpression'
|
|
1248
|
-
) {
|
|
1249
|
-
// is an AssignmentExpression to an ObjectPattern
|
|
1250
|
-
context.write('(');
|
|
1251
|
-
context.visit(node.expression);
|
|
1252
|
-
context.write(');');
|
|
1253
|
-
return;
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
context.visit(node.expression);
|
|
1250
|
+
// would otherwise be parsed as a block / function / class declaration
|
|
1251
|
+
const wrap = leads_with_curly_or_keyword(node.expression);
|
|
1252
|
+
maybe_wrap(context, node.expression, wrap);
|
|
1257
1253
|
context.write(';');
|
|
1258
1254
|
},
|
|
1259
1255
|
|
|
@@ -1289,6 +1285,9 @@ export default (options = {}) => {
|
|
|
1289
1285
|
let name = node.name;
|
|
1290
1286
|
context.write(name, node);
|
|
1291
1287
|
|
|
1288
|
+
// optional parameters (`a?: T`) carry `optional` on the identifier
|
|
1289
|
+
if (node.optional) context.write('?');
|
|
1290
|
+
|
|
1292
1291
|
if (node.typeAnnotation) context.visit(node.typeAnnotation);
|
|
1293
1292
|
},
|
|
1294
1293
|
|
|
@@ -1436,13 +1435,10 @@ export default (options = {}) => {
|
|
|
1436
1435
|
LogicalExpression: shared['BinaryExpression|LogicalExpression'],
|
|
1437
1436
|
|
|
1438
1437
|
MemberExpression(node, context) {
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
} else {
|
|
1444
|
-
context.visit(node.object);
|
|
1445
|
-
}
|
|
1438
|
+
const wrap =
|
|
1439
|
+
node.object.type === 'ChainExpression' ||
|
|
1440
|
+
EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression;
|
|
1441
|
+
maybe_wrap(context, node.object, wrap);
|
|
1446
1442
|
|
|
1447
1443
|
if (node.computed) {
|
|
1448
1444
|
if (node.optional) {
|
|
@@ -1483,9 +1479,7 @@ export default (options = {}) => {
|
|
|
1483
1479
|
|
|
1484
1480
|
// @ts-expect-error this isn't a real node type, but Acorn produces it
|
|
1485
1481
|
ParenthesizedExpression(node, context) {
|
|
1486
|
-
context.
|
|
1487
|
-
context.visit(node.expression);
|
|
1488
|
-
context.write(')');
|
|
1482
|
+
maybe_wrap(context, node.expression, true);
|
|
1489
1483
|
},
|
|
1490
1484
|
|
|
1491
1485
|
PrivateIdentifier(node, context) {
|
|
@@ -1634,7 +1628,12 @@ export default (options = {}) => {
|
|
|
1634
1628
|
},
|
|
1635
1629
|
|
|
1636
1630
|
TaggedTemplateExpression(node, context) {
|
|
1637
|
-
|
|
1631
|
+
// the tag is a LeftHandSideExpression; a lower-precedence tag (logical,
|
|
1632
|
+
// conditional, arrow, `as`, unary…) or an optional chain must be wrapped
|
|
1633
|
+
const wrap =
|
|
1634
|
+
/** @type {string} */ (node.tag.type) === 'ChainExpression' ||
|
|
1635
|
+
EXPRESSIONS_PRECEDENCE[node.tag.type] < EXPRESSIONS_PRECEDENCE.CallExpression;
|
|
1636
|
+
maybe_wrap(context, node.tag, wrap);
|
|
1638
1637
|
context.visit(node.quasi);
|
|
1639
1638
|
},
|
|
1640
1639
|
|
|
@@ -1707,15 +1706,19 @@ export default (options = {}) => {
|
|
|
1707
1706
|
|
|
1708
1707
|
if (node.operator.length > 1) {
|
|
1709
1708
|
context.write(' ');
|
|
1709
|
+
} else if (
|
|
1710
|
+
(node.operator === '+' || node.operator === '-') &&
|
|
1711
|
+
((node.argument.type === 'UnaryExpression' && node.argument.operator === node.operator) ||
|
|
1712
|
+
(node.argument.type === 'UpdateExpression' &&
|
|
1713
|
+
node.argument.prefix &&
|
|
1714
|
+
node.argument.operator[0] === node.operator))
|
|
1715
|
+
) {
|
|
1716
|
+
context.write(' ');
|
|
1710
1717
|
}
|
|
1711
1718
|
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
context.write(')');
|
|
1716
|
-
} else {
|
|
1717
|
-
context.visit(node.argument);
|
|
1718
|
-
}
|
|
1719
|
+
const wrap =
|
|
1720
|
+
EXPRESSIONS_PRECEDENCE[node.argument.type] < EXPRESSIONS_PRECEDENCE.UnaryExpression;
|
|
1721
|
+
maybe_wrap(context, node.argument, wrap);
|
|
1719
1722
|
},
|
|
1720
1723
|
|
|
1721
1724
|
UpdateExpression(node, context) {
|
|
@@ -1883,7 +1886,9 @@ export default (options = {}) => {
|
|
|
1883
1886
|
},
|
|
1884
1887
|
|
|
1885
1888
|
TSPropertySignature(node, context) {
|
|
1889
|
+
if (node.computed) context.write('[');
|
|
1886
1890
|
context.visit(node.key);
|
|
1891
|
+
if (node.computed) context.write(']');
|
|
1887
1892
|
if (node.optional) context.write('?');
|
|
1888
1893
|
if (node.typeAnnotation) context.visit(node.typeAnnotation);
|
|
1889
1894
|
},
|
|
@@ -1951,13 +1956,9 @@ export default (options = {}) => {
|
|
|
1951
1956
|
context.write('<');
|
|
1952
1957
|
context.visit(node.typeAnnotation);
|
|
1953
1958
|
context.write('>');
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
context.write(')');
|
|
1958
|
-
} else {
|
|
1959
|
-
context.visit(node.expression);
|
|
1960
|
-
}
|
|
1959
|
+
const wrap =
|
|
1960
|
+
EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSTypeAssertion;
|
|
1961
|
+
maybe_wrap(context, node.expression, wrap);
|
|
1961
1962
|
},
|
|
1962
1963
|
|
|
1963
1964
|
TSTypeParameterInstantiation(node, context) {
|
|
@@ -1979,6 +1980,11 @@ export default (options = {}) => {
|
|
|
1979
1980
|
},
|
|
1980
1981
|
|
|
1981
1982
|
TSTypeParameter(node, context) {
|
|
1983
|
+
// modifiers: `const T`, `in T` / `out T` (variance)
|
|
1984
|
+
if (node.const) context.write('const ');
|
|
1985
|
+
if (node.in) context.write('in ');
|
|
1986
|
+
if (node.out) context.write('out ');
|
|
1987
|
+
|
|
1982
1988
|
if (node.name && node.name.type) context.visit(node.name);
|
|
1983
1989
|
// @ts-expect-error type mismatch TSESTree and acorn-typescript?
|
|
1984
1990
|
else context.write(node.name, node);
|
|
@@ -1995,19 +2001,14 @@ export default (options = {}) => {
|
|
|
1995
2001
|
},
|
|
1996
2002
|
|
|
1997
2003
|
TSTypePredicate(node, context) {
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
context.visit(node.typeAnnotation);
|
|
2002
|
-
}
|
|
2004
|
+
// `asserts` precedes the parameter name; `is <type>` follows it. Forms:
|
|
2005
|
+
// `x is T`, `asserts x is T`, `asserts x`
|
|
2006
|
+
if (node.asserts) context.write('asserts ');
|
|
2003
2007
|
|
|
2004
|
-
if (node.
|
|
2005
|
-
context.write(' asserts ');
|
|
2006
|
-
} else {
|
|
2007
|
-
context.write(' is ');
|
|
2008
|
-
}
|
|
2008
|
+
if (node.parameterName) context.visit(node.parameterName);
|
|
2009
2009
|
|
|
2010
2010
|
if (node.typeAnnotation) {
|
|
2011
|
+
context.write(' is ');
|
|
2011
2012
|
context.visit(node.typeAnnotation.typeAnnotation);
|
|
2012
2013
|
}
|
|
2013
2014
|
},
|
|
@@ -2045,7 +2046,16 @@ export default (options = {}) => {
|
|
|
2045
2046
|
},
|
|
2046
2047
|
|
|
2047
2048
|
TSMappedType(node, context) {
|
|
2048
|
-
context.write('{
|
|
2049
|
+
context.write('{');
|
|
2050
|
+
|
|
2051
|
+
// `readonly` / `+readonly` / `-readonly` modifier
|
|
2052
|
+
if (node.readonly) {
|
|
2053
|
+
context.write(
|
|
2054
|
+
node.readonly === '-' ? '-readonly ' : node.readonly === '+' ? '+readonly ' : 'readonly '
|
|
2055
|
+
);
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
context.write('[');
|
|
2049
2059
|
|
|
2050
2060
|
const legacy_type_parameter = node.typeParameter;
|
|
2051
2061
|
const key = node.key ?? legacy_type_parameter?.name;
|
|
@@ -2062,8 +2072,19 @@ export default (options = {}) => {
|
|
|
2062
2072
|
context.visit(constraint);
|
|
2063
2073
|
}
|
|
2064
2074
|
|
|
2075
|
+
// `as` key remapping
|
|
2076
|
+
if (node.nameType) {
|
|
2077
|
+
context.write(' as ');
|
|
2078
|
+
context.visit(node.nameType);
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2065
2081
|
context.write(']');
|
|
2066
2082
|
|
|
2083
|
+
// `?` / `+?` / `-?` optionality modifier
|
|
2084
|
+
if (node.optional) {
|
|
2085
|
+
context.write(node.optional === '-' ? '-?' : node.optional === '+' ? '+?' : '?');
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2067
2088
|
if (node.typeAnnotation) {
|
|
2068
2089
|
context.write(': ');
|
|
2069
2090
|
context.visit(node.typeAnnotation);
|
|
@@ -2073,10 +2094,11 @@ export default (options = {}) => {
|
|
|
2073
2094
|
},
|
|
2074
2095
|
|
|
2075
2096
|
TSMethodSignature(node, context) {
|
|
2097
|
+
if (node.computed) context.write('[');
|
|
2076
2098
|
context.visit(node.key);
|
|
2099
|
+
if (node.computed) context.write(']');
|
|
2077
2100
|
|
|
2078
2101
|
context.write('(');
|
|
2079
|
-
|
|
2080
2102
|
sequence(
|
|
2081
2103
|
context,
|
|
2082
2104
|
// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
|
|
@@ -2190,16 +2212,9 @@ export default (options = {}) => {
|
|
|
2190
2212
|
|
|
2191
2213
|
TSAsExpression(node, context) {
|
|
2192
2214
|
if (node.expression) {
|
|
2193
|
-
const
|
|
2215
|
+
const wrap =
|
|
2194
2216
|
EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSAsExpression;
|
|
2195
|
-
|
|
2196
|
-
if (needs_parens) {
|
|
2197
|
-
context.write('(');
|
|
2198
|
-
context.visit(node.expression);
|
|
2199
|
-
context.write(')');
|
|
2200
|
-
} else {
|
|
2201
|
-
context.visit(node.expression);
|
|
2202
|
-
}
|
|
2217
|
+
maybe_wrap(context, node.expression, wrap);
|
|
2203
2218
|
}
|
|
2204
2219
|
context.write(' as ');
|
|
2205
2220
|
context.visit(node.typeAnnotation);
|
|
@@ -2239,21 +2254,24 @@ export default (options = {}) => {
|
|
|
2239
2254
|
context.visit(node.id);
|
|
2240
2255
|
}
|
|
2241
2256
|
|
|
2242
|
-
|
|
2243
|
-
|
|
2257
|
+
// a qualified name (`namespace A.B.C`) is represented as nested
|
|
2258
|
+
// `TSModuleDeclaration`s whose body is the next name part, not a block
|
|
2259
|
+
let body = /** @type {any} */ (node.body);
|
|
2260
|
+
while (body && body.type === 'TSModuleDeclaration') {
|
|
2261
|
+
context.write('.');
|
|
2262
|
+
context.visit(body.id);
|
|
2263
|
+
body = body.body;
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
if (!body) return;
|
|
2267
|
+
context.visit(body);
|
|
2244
2268
|
},
|
|
2245
2269
|
|
|
2246
2270
|
TSNonNullExpression(node, context) {
|
|
2247
2271
|
// operator expressions can't take a postfix `!` directly: `(0 as number)!`, `(await x)!`
|
|
2248
|
-
|
|
2249
|
-
EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSNonNullExpression
|
|
2250
|
-
)
|
|
2251
|
-
context.write('(');
|
|
2252
|
-
context.visit(node.expression);
|
|
2253
|
-
context.write(')');
|
|
2254
|
-
} else {
|
|
2255
|
-
context.visit(node.expression);
|
|
2256
|
-
}
|
|
2272
|
+
const wrap =
|
|
2273
|
+
EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSNonNullExpression;
|
|
2274
|
+
maybe_wrap(context, node.expression, wrap);
|
|
2257
2275
|
context.write('!');
|
|
2258
2276
|
},
|
|
2259
2277
|
|
|
@@ -2287,24 +2305,15 @@ export default (options = {}) => {
|
|
|
2287
2305
|
|
|
2288
2306
|
//@ts-expect-error I don't know why, but this is relied upon in the tests, but doesn't exist in the TSESTree types
|
|
2289
2307
|
TSParenthesizedType(node, context) {
|
|
2290
|
-
context.
|
|
2291
|
-
context.visit(node.typeAnnotation);
|
|
2292
|
-
context.write(')');
|
|
2308
|
+
maybe_wrap(context, node.typeAnnotation, true);
|
|
2293
2309
|
},
|
|
2294
2310
|
|
|
2295
2311
|
TSSatisfiesExpression(node, context) {
|
|
2296
2312
|
if (node.expression) {
|
|
2297
|
-
const
|
|
2313
|
+
const wrap =
|
|
2298
2314
|
EXPRESSIONS_PRECEDENCE[node.expression.type] <
|
|
2299
2315
|
EXPRESSIONS_PRECEDENCE.TSSatisfiesExpression;
|
|
2300
|
-
|
|
2301
|
-
if (needs_parens) {
|
|
2302
|
-
context.write('(');
|
|
2303
|
-
context.visit(node.expression);
|
|
2304
|
-
context.write(')');
|
|
2305
|
-
} else {
|
|
2306
|
-
context.visit(node.expression);
|
|
2307
|
-
}
|
|
2316
|
+
maybe_wrap(context, node.expression, wrap);
|
|
2308
2317
|
}
|
|
2309
2318
|
context.write(' satisfies ');
|
|
2310
2319
|
context.visit(node.typeAnnotation);
|
|
@@ -2364,7 +2373,7 @@ function arrow_concise_body_needs_wrap(body) {
|
|
|
2364
2373
|
* @param {boolean} is_right
|
|
2365
2374
|
* @returns
|
|
2366
2375
|
*/
|
|
2367
|
-
function
|
|
2376
|
+
function operand_needs_wrap(node, parent, is_right) {
|
|
2368
2377
|
if (node.type === 'PrivateIdentifier') return false;
|
|
2369
2378
|
|
|
2370
2379
|
if (!is_right && (node.type === 'TSAsExpression' || node.type === 'TSSatisfiesExpression')) {
|
|
@@ -2383,42 +2392,46 @@ function needs_parens(node, parent, is_right) {
|
|
|
2383
2392
|
return true;
|
|
2384
2393
|
}
|
|
2385
2394
|
|
|
2395
|
+
// `**` can't take a unary/await/assertion left operand: `-2 ** 2`, `await x ** 2`,
|
|
2396
|
+
// `<T>x ** 2` are syntax errors
|
|
2397
|
+
const unary_base_of_pow =
|
|
2398
|
+
!is_right &&
|
|
2399
|
+
parent.operator === '**' &&
|
|
2400
|
+
(node.type === 'UnaryExpression' ||
|
|
2401
|
+
node.type === 'AwaitExpression' ||
|
|
2402
|
+
node.type === 'TSTypeAssertion');
|
|
2403
|
+
if (unary_base_of_pow) return true;
|
|
2404
|
+
|
|
2386
2405
|
const precedence = EXPRESSIONS_PRECEDENCE[node.type];
|
|
2387
2406
|
const parent_precedence = EXPRESSIONS_PRECEDENCE[parent.type];
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
(!is_right && precedence === 15 && parent_precedence === 14 && parent.operator === '**') ||
|
|
2393
|
-
precedence < parent_precedence
|
|
2394
|
-
);
|
|
2395
|
-
}
|
|
2396
|
-
|
|
2397
|
-
if (precedence !== 12 && precedence !== 14) {
|
|
2398
|
-
// Not a `LogicalExpression` or `BinaryExpression`
|
|
2399
|
-
return false;
|
|
2400
|
-
}
|
|
2401
|
-
|
|
2402
|
-
if (
|
|
2403
|
-
/** @type {TSESTree.BinaryExpression} */ (node).operator === '**' &&
|
|
2404
|
-
parent.operator === '**'
|
|
2405
|
-
) {
|
|
2406
|
-
// Exponentiation operator has right-to-left associativity
|
|
2407
|
+
if (precedence !== parent_precedence) return precedence < parent_precedence;
|
|
2408
|
+
const operator = /** @type {TSESTree.BinaryExpression} */ (node).operator;
|
|
2409
|
+
if (operator === '**' && parent.operator === '**') {
|
|
2410
|
+
// exponentiation is right-associative
|
|
2407
2411
|
return !is_right;
|
|
2408
2412
|
}
|
|
2409
2413
|
|
|
2410
2414
|
if (is_right) {
|
|
2411
|
-
//
|
|
2412
|
-
return
|
|
2413
|
-
OPERATOR_PRECEDENCE[/** @type {TSESTree.BinaryExpression} */ (node).operator] <=
|
|
2414
|
-
OPERATOR_PRECEDENCE[parent.operator]
|
|
2415
|
-
);
|
|
2415
|
+
// parentheses are needed when both operators have the same precedence
|
|
2416
|
+
return OPERATOR_PRECEDENCE[operator] <= OPERATOR_PRECEDENCE[parent.operator];
|
|
2416
2417
|
}
|
|
2417
2418
|
|
|
2418
|
-
return
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2419
|
+
return OPERATOR_PRECEDENCE[operator] < OPERATOR_PRECEDENCE[parent.operator];
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
/**
|
|
2423
|
+
* @param {Context} context
|
|
2424
|
+
* @param {TSESTree.Node} node
|
|
2425
|
+
* @param {boolean} wrap
|
|
2426
|
+
*/
|
|
2427
|
+
function maybe_wrap(context, node, wrap) {
|
|
2428
|
+
if (wrap) {
|
|
2429
|
+
context.write('(');
|
|
2430
|
+
context.visit(node);
|
|
2431
|
+
context.write(')');
|
|
2432
|
+
} else {
|
|
2433
|
+
context.visit(node);
|
|
2434
|
+
}
|
|
2422
2435
|
}
|
|
2423
2436
|
|
|
2424
2437
|
/** @param {TSESTree.Node} node */
|
|
@@ -2432,6 +2445,96 @@ function has_call_expression(node) {
|
|
|
2432
2445
|
return false;
|
|
2433
2446
|
}
|
|
2434
2447
|
}
|
|
2448
|
+
return false;
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
/**
|
|
2452
|
+
* True when printing `node` as an expression statement would begin with `{`,
|
|
2453
|
+
* `function`, or `class` — which the parser would misread as a block, function
|
|
2454
|
+
* declaration, or class declaration. Walks the left spine following the same
|
|
2455
|
+
* parenthesization the visitors apply, so it stops as soon as a child position
|
|
2456
|
+
* would already be wrapped.
|
|
2457
|
+
* @param {TSESTree.Node} node
|
|
2458
|
+
* @returns {boolean}
|
|
2459
|
+
*/
|
|
2460
|
+
function leads_with_curly_or_keyword(node) {
|
|
2461
|
+
while (node) {
|
|
2462
|
+
switch (node.type) {
|
|
2463
|
+
case 'ObjectExpression':
|
|
2464
|
+
case 'ObjectPattern':
|
|
2465
|
+
case 'FunctionExpression':
|
|
2466
|
+
case 'ClassExpression':
|
|
2467
|
+
return true;
|
|
2468
|
+
|
|
2469
|
+
case 'BinaryExpression':
|
|
2470
|
+
case 'LogicalExpression':
|
|
2471
|
+
if (operand_needs_wrap(node.left, node, false)) return false;
|
|
2472
|
+
node = node.left;
|
|
2473
|
+
continue;
|
|
2474
|
+
|
|
2475
|
+
case 'AssignmentExpression':
|
|
2476
|
+
node = node.left;
|
|
2477
|
+
continue;
|
|
2478
|
+
|
|
2479
|
+
case 'ConditionalExpression':
|
|
2480
|
+
if (
|
|
2481
|
+
EXPRESSIONS_PRECEDENCE[node.test.type] <= EXPRESSIONS_PRECEDENCE.ConditionalExpression
|
|
2482
|
+
) {
|
|
2483
|
+
return false;
|
|
2484
|
+
}
|
|
2485
|
+
node = node.test;
|
|
2486
|
+
continue;
|
|
2487
|
+
|
|
2488
|
+
case 'MemberExpression':
|
|
2489
|
+
if (
|
|
2490
|
+
/** @type {string} */ (node.object.type) === 'ChainExpression' ||
|
|
2491
|
+
EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression
|
|
2492
|
+
) {
|
|
2493
|
+
return false;
|
|
2494
|
+
}
|
|
2495
|
+
node = node.object;
|
|
2496
|
+
continue;
|
|
2497
|
+
|
|
2498
|
+
case 'CallExpression':
|
|
2499
|
+
if (
|
|
2500
|
+
/** @type {string} */ (node.callee.type) === 'ChainExpression' ||
|
|
2501
|
+
EXPRESSIONS_PRECEDENCE[node.callee.type] < EXPRESSIONS_PRECEDENCE.CallExpression
|
|
2502
|
+
) {
|
|
2503
|
+
return false;
|
|
2504
|
+
}
|
|
2505
|
+
node = node.callee;
|
|
2506
|
+
continue;
|
|
2507
|
+
|
|
2508
|
+
case 'TaggedTemplateExpression':
|
|
2509
|
+
if (
|
|
2510
|
+
/** @type {string} */ (node.tag.type) === 'ChainExpression' ||
|
|
2511
|
+
EXPRESSIONS_PRECEDENCE[node.tag.type] < EXPRESSIONS_PRECEDENCE.CallExpression
|
|
2512
|
+
) {
|
|
2513
|
+
return false;
|
|
2514
|
+
}
|
|
2515
|
+
node = node.tag;
|
|
2516
|
+
continue;
|
|
2517
|
+
|
|
2518
|
+
case 'UpdateExpression':
|
|
2519
|
+
if (node.prefix) return false;
|
|
2520
|
+
node = node.argument;
|
|
2521
|
+
continue;
|
|
2522
|
+
|
|
2523
|
+
case 'TSAsExpression':
|
|
2524
|
+
case 'TSSatisfiesExpression':
|
|
2525
|
+
case 'TSNonNullExpression':
|
|
2526
|
+
node = node.expression;
|
|
2527
|
+
continue;
|
|
2528
|
+
|
|
2529
|
+
// a sequence expression always prints its own wrapping parens
|
|
2530
|
+
case 'SequenceExpression':
|
|
2531
|
+
return false;
|
|
2532
|
+
|
|
2533
|
+
default:
|
|
2534
|
+
return false;
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
return false;
|
|
2435
2538
|
}
|
|
2436
2539
|
|
|
2437
2540
|
/**
|