esrap 2.2.12 → 2.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/package.json +1 -1
- package/src/languages/ts/index.js +245 -42
- package/src/languages/types.d.ts +8 -0
- package/types/index.d.ts +16 -0
- package/types/index.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -484,20 +484,50 @@ export default (options = {}) => {
|
|
|
484
484
|
}
|
|
485
485
|
}
|
|
486
486
|
|
|
487
|
+
const boundary_tokens = options.boundaryTokens === true;
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* A one-character synthetic token node so structural tokens (`(`, `[`, `{`,
|
|
491
|
+
* unary operators, …) written where a node's SOURCE span begins or ends get a
|
|
492
|
+
* sourcemap anchor. Without it, everything up to the next mapped token is
|
|
493
|
+
* attributed to the PREVIOUS token's source position — `write(content, node)`
|
|
494
|
+
* only maps tokens written with a node, and these boundary characters belong
|
|
495
|
+
* to no written token. Opt-in (`boundaryTokens`): denser maps, byte-identical
|
|
496
|
+
* output.
|
|
497
|
+
* @param {{ line: number, column: number } | undefined} pos
|
|
498
|
+
* @param {number} [length]
|
|
499
|
+
*/
|
|
500
|
+
function token_at(pos, length = 1) {
|
|
501
|
+
if (!boundary_tokens) return undefined;
|
|
502
|
+
if (!pos) return undefined;
|
|
503
|
+
return /** @type {any} */ ({
|
|
504
|
+
loc: { start: pos, end: { line: pos.line, column: pos.column + length } }
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/** @param {{ line: number, column: number } | undefined} pos */
|
|
509
|
+
function token_before(pos) {
|
|
510
|
+
if (!boundary_tokens) return undefined;
|
|
511
|
+
if (!pos || pos.column === 0) return undefined;
|
|
512
|
+
return /** @type {any} */ ({
|
|
513
|
+
loc: { start: { line: pos.line, column: pos.column - 1 }, end: pos }
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
|
|
487
517
|
const shared = {
|
|
488
518
|
/**
|
|
489
519
|
* @param {TSESTree.ArrayExpression | TSESTree.ArrayPattern} node
|
|
490
520
|
* @param {Context} context
|
|
491
521
|
*/
|
|
492
522
|
'ArrayExpression|ArrayPattern': (node, context) => {
|
|
493
|
-
context.write('[');
|
|
523
|
+
context.write('[', token_at(node.loc?.start));
|
|
494
524
|
sequence(
|
|
495
525
|
context,
|
|
496
526
|
/** @type {TSESTree.Node[]} */ (node.elements),
|
|
497
527
|
node.loc?.end ?? null,
|
|
498
528
|
false
|
|
499
529
|
);
|
|
500
|
-
context.write(']');
|
|
530
|
+
context.write(']', token_before(node.loc?.end));
|
|
501
531
|
},
|
|
502
532
|
|
|
503
533
|
/**
|
|
@@ -631,7 +661,7 @@ export default (options = {}) => {
|
|
|
631
661
|
join.write(' ');
|
|
632
662
|
}
|
|
633
663
|
|
|
634
|
-
context.write(')');
|
|
664
|
+
context.write(')', token_before(node.loc?.end));
|
|
635
665
|
},
|
|
636
666
|
|
|
637
667
|
/**
|
|
@@ -653,12 +683,25 @@ export default (options = {}) => {
|
|
|
653
683
|
|
|
654
684
|
if (node.id) {
|
|
655
685
|
context.visit(node.id);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
if (node.typeParameters) {
|
|
689
|
+
context.visit(node.typeParameters);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
if (node.id || node.typeParameters) {
|
|
656
693
|
context.write(' ');
|
|
657
694
|
}
|
|
658
695
|
|
|
659
696
|
if (node.superClass) {
|
|
660
697
|
context.write('extends ');
|
|
698
|
+
// the `extends` clause is a LeftHandSideExpression; anything lower (a
|
|
699
|
+
// logical/binary/conditional/etc.) must be parenthesized
|
|
700
|
+
const wrap_super =
|
|
701
|
+
EXPRESSIONS_PRECEDENCE[node.superClass.type] < EXPRESSIONS_PRECEDENCE.NewExpression;
|
|
702
|
+
if (wrap_super) context.write('(');
|
|
661
703
|
context.visit(node.superClass);
|
|
704
|
+
if (wrap_super) context.write(')');
|
|
662
705
|
|
|
663
706
|
// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
|
|
664
707
|
var type_arguments = node.superTypeParameters ?? node.superTypeArguments;
|
|
@@ -791,9 +834,15 @@ export default (options = {}) => {
|
|
|
791
834
|
|
|
792
835
|
if (node.value.generator) context.write('*');
|
|
793
836
|
|
|
794
|
-
if (node.computed) context.write('[');
|
|
837
|
+
if (node.computed) context.write('[', token_before(node.key.loc?.start));
|
|
795
838
|
context.visit(node.key);
|
|
796
|
-
if (node.computed) context.write(']');
|
|
839
|
+
if (node.computed) context.write(']', token_at(node.key.loc?.end));
|
|
840
|
+
|
|
841
|
+
// optional method (`m?()`)
|
|
842
|
+
if (node.optional) context.write('?');
|
|
843
|
+
|
|
844
|
+
// @ts-expect-error `typeParameters` lives on the method node, not its value
|
|
845
|
+
if (node.typeParameters) context.visit(node.typeParameters);
|
|
797
846
|
|
|
798
847
|
context.write('(');
|
|
799
848
|
sequence(
|
|
@@ -827,6 +876,8 @@ export default (options = {}) => {
|
|
|
827
876
|
|
|
828
877
|
const kw = create_keyword_write(context, node, field_modifiers_keywords_map_ok);
|
|
829
878
|
|
|
879
|
+
if (node.declare) kw('declare ');
|
|
880
|
+
|
|
830
881
|
if (node.accessibility) {
|
|
831
882
|
kw(node.accessibility + ' ');
|
|
832
883
|
}
|
|
@@ -844,6 +895,10 @@ export default (options = {}) => {
|
|
|
844
895
|
kw('static ');
|
|
845
896
|
}
|
|
846
897
|
|
|
898
|
+
if (node.override) kw('override ');
|
|
899
|
+
|
|
900
|
+
if (node.readonly) kw('readonly ');
|
|
901
|
+
|
|
847
902
|
if (
|
|
848
903
|
// @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
|
|
849
904
|
node.accessor ||
|
|
@@ -854,13 +909,17 @@ export default (options = {}) => {
|
|
|
854
909
|
}
|
|
855
910
|
|
|
856
911
|
if (node.computed) {
|
|
857
|
-
context.write('[');
|
|
912
|
+
context.write('[', token_before(node.key.loc?.start));
|
|
858
913
|
context.visit(node.key);
|
|
859
|
-
context.write(']');
|
|
914
|
+
context.write(']', token_at(node.key.loc?.end));
|
|
860
915
|
} else {
|
|
861
916
|
context.visit(node.key);
|
|
862
917
|
}
|
|
863
918
|
|
|
919
|
+
// `x?: T` (optional) / `x!: T` (definite assignment)
|
|
920
|
+
if (node.optional) context.write('?');
|
|
921
|
+
else if (node.definite) context.write('!');
|
|
922
|
+
|
|
864
923
|
if (node.typeAnnotation) {
|
|
865
924
|
if (node.type === 'AccessorProperty' || node.type === 'TSAbstractAccessorProperty') {
|
|
866
925
|
context.visit(node.typeAnnotation);
|
|
@@ -1101,7 +1160,14 @@ export default (options = {}) => {
|
|
|
1101
1160
|
|
|
1102
1161
|
Decorator(node, context) {
|
|
1103
1162
|
context.write('@');
|
|
1163
|
+
// a decorator must be an identifier/member/call (or parenthesized); anything
|
|
1164
|
+
// else (ternary, logical, assignment, unary, `as`, optional chain…) needs wrapping
|
|
1165
|
+
const wrap =
|
|
1166
|
+
/** @type {string} */ (node.expression.type) === 'ChainExpression' ||
|
|
1167
|
+
EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.CallExpression;
|
|
1168
|
+
if (wrap) context.write('(');
|
|
1104
1169
|
context.visit(node.expression);
|
|
1170
|
+
if (wrap) context.write(')');
|
|
1105
1171
|
context.newline();
|
|
1106
1172
|
},
|
|
1107
1173
|
|
|
@@ -1211,12 +1277,8 @@ export default (options = {}) => {
|
|
|
1211
1277
|
},
|
|
1212
1278
|
|
|
1213
1279
|
ExpressionStatement(node, context) {
|
|
1214
|
-
//
|
|
1215
|
-
const wrap =
|
|
1216
|
-
node.expression.type === 'ObjectExpression' ||
|
|
1217
|
-
(node.expression.type === 'AssignmentExpression' &&
|
|
1218
|
-
node.expression.left.type === 'ObjectPattern') ||
|
|
1219
|
-
node.expression.type === 'FunctionExpression';
|
|
1280
|
+
// would otherwise be parsed as a block / function / class declaration
|
|
1281
|
+
const wrap = leads_with_curly_or_keyword(node.expression);
|
|
1220
1282
|
maybe_wrap(context, node.expression, wrap);
|
|
1221
1283
|
context.write(';');
|
|
1222
1284
|
},
|
|
@@ -1253,7 +1315,9 @@ export default (options = {}) => {
|
|
|
1253
1315
|
let name = node.name;
|
|
1254
1316
|
context.write(name, node);
|
|
1255
1317
|
|
|
1318
|
+
// optional parameters (`a?: T`) carry `optional` on the identifier
|
|
1256
1319
|
if (node.optional) context.write('?');
|
|
1320
|
+
|
|
1257
1321
|
if (node.typeAnnotation) context.visit(node.typeAnnotation);
|
|
1258
1322
|
},
|
|
1259
1323
|
|
|
@@ -1412,7 +1476,7 @@ export default (options = {}) => {
|
|
|
1412
1476
|
}
|
|
1413
1477
|
context.write('[');
|
|
1414
1478
|
context.visit(node.property);
|
|
1415
|
-
context.write(']');
|
|
1479
|
+
context.write(']', token_before(node.loc?.end));
|
|
1416
1480
|
} else {
|
|
1417
1481
|
context.write(node.optional ? '?.' : '.');
|
|
1418
1482
|
context.visit(node.property);
|
|
@@ -1430,22 +1494,28 @@ export default (options = {}) => {
|
|
|
1430
1494
|
NewExpression: shared['CallExpression|NewExpression'],
|
|
1431
1495
|
|
|
1432
1496
|
ObjectExpression(node, context) {
|
|
1433
|
-
context.write('{');
|
|
1497
|
+
context.write('{', token_at(node.loc?.start));
|
|
1434
1498
|
sequence(context, node.properties, node.loc?.end ?? null, true);
|
|
1435
|
-
context.write('}');
|
|
1499
|
+
context.write('}', token_before(node.loc?.end));
|
|
1436
1500
|
},
|
|
1437
1501
|
|
|
1438
1502
|
ObjectPattern(node, context) {
|
|
1439
|
-
context.write('{');
|
|
1503
|
+
context.write('{', token_at(node.loc?.start));
|
|
1440
1504
|
sequence(context, node.properties, node.loc?.end ?? null, true);
|
|
1441
|
-
context.write('}');
|
|
1505
|
+
context.write('}', token_before(node.loc?.end));
|
|
1442
1506
|
|
|
1443
1507
|
if (node.typeAnnotation) context.visit(node.typeAnnotation);
|
|
1444
1508
|
},
|
|
1445
1509
|
|
|
1446
1510
|
// @ts-expect-error this isn't a real node type, but Acorn produces it
|
|
1447
1511
|
ParenthesizedExpression(node, context) {
|
|
1448
|
-
|
|
1512
|
+
if (node.loc) {
|
|
1513
|
+
context.write('(', token_at(node.loc.start));
|
|
1514
|
+
context.visit(node.expression);
|
|
1515
|
+
context.write(')', token_before(node.loc.end));
|
|
1516
|
+
} else {
|
|
1517
|
+
maybe_wrap(context, node.expression, true);
|
|
1518
|
+
}
|
|
1449
1519
|
},
|
|
1450
1520
|
|
|
1451
1521
|
PrivateIdentifier(node, context) {
|
|
@@ -1479,9 +1549,9 @@ export default (options = {}) => {
|
|
|
1479
1549
|
if (node.kind !== 'init') kw(node.kind + ' ');
|
|
1480
1550
|
if (node.value.async) kw('async ');
|
|
1481
1551
|
if (node.value.generator) context.write('*');
|
|
1482
|
-
if (node.computed) context.write('[');
|
|
1552
|
+
if (node.computed) context.write('[', token_before(node.key.loc?.start));
|
|
1483
1553
|
context.visit(node.key);
|
|
1484
|
-
if (node.computed) context.write(']');
|
|
1554
|
+
if (node.computed) context.write(']', token_at(node.key.loc?.end));
|
|
1485
1555
|
context.write('(');
|
|
1486
1556
|
sequence(
|
|
1487
1557
|
context,
|
|
@@ -1496,12 +1566,17 @@ export default (options = {}) => {
|
|
|
1496
1566
|
context.write(' ');
|
|
1497
1567
|
context.visit(node.value.body);
|
|
1498
1568
|
} else {
|
|
1499
|
-
if (node.computed) context.write('[');
|
|
1569
|
+
if (node.computed) context.write('[', token_before(node.key.loc?.start));
|
|
1500
1570
|
if (node.kind === 'get' || node.kind === 'set') {
|
|
1501
1571
|
write_keyword(context, node, node.kind, ' ');
|
|
1502
1572
|
}
|
|
1503
1573
|
context.visit(node.key);
|
|
1504
|
-
|
|
1574
|
+
if (node.computed) {
|
|
1575
|
+
context.write(']', token_at(node.key.loc?.end));
|
|
1576
|
+
context.write(': ');
|
|
1577
|
+
} else {
|
|
1578
|
+
context.write(': ');
|
|
1579
|
+
}
|
|
1505
1580
|
context.visit(node.value);
|
|
1506
1581
|
}
|
|
1507
1582
|
},
|
|
@@ -1594,7 +1669,12 @@ export default (options = {}) => {
|
|
|
1594
1669
|
},
|
|
1595
1670
|
|
|
1596
1671
|
TaggedTemplateExpression(node, context) {
|
|
1597
|
-
|
|
1672
|
+
// the tag is a LeftHandSideExpression; a lower-precedence tag (logical,
|
|
1673
|
+
// conditional, arrow, `as`, unary…) or an optional chain must be wrapped
|
|
1674
|
+
const wrap =
|
|
1675
|
+
/** @type {string} */ (node.tag.type) === 'ChainExpression' ||
|
|
1676
|
+
EXPRESSIONS_PRECEDENCE[node.tag.type] < EXPRESSIONS_PRECEDENCE.CallExpression;
|
|
1677
|
+
maybe_wrap(context, node.tag, wrap);
|
|
1598
1678
|
context.visit(node.quasi);
|
|
1599
1679
|
},
|
|
1600
1680
|
|
|
@@ -1663,7 +1743,7 @@ export default (options = {}) => {
|
|
|
1663
1743
|
},
|
|
1664
1744
|
|
|
1665
1745
|
UnaryExpression(node, context) {
|
|
1666
|
-
context.write(node.operator);
|
|
1746
|
+
context.write(node.operator, token_at(node.loc?.start, node.operator.length));
|
|
1667
1747
|
|
|
1668
1748
|
if (node.operator.length > 1) {
|
|
1669
1749
|
context.write(' ');
|
|
@@ -1847,7 +1927,9 @@ export default (options = {}) => {
|
|
|
1847
1927
|
},
|
|
1848
1928
|
|
|
1849
1929
|
TSPropertySignature(node, context) {
|
|
1930
|
+
if (node.computed) context.write('[', token_before(node.key.loc?.start));
|
|
1850
1931
|
context.visit(node.key);
|
|
1932
|
+
if (node.computed) context.write(']', token_at(node.key.loc?.end));
|
|
1851
1933
|
if (node.optional) context.write('?');
|
|
1852
1934
|
if (node.typeAnnotation) context.visit(node.typeAnnotation);
|
|
1853
1935
|
},
|
|
@@ -1939,6 +2021,11 @@ export default (options = {}) => {
|
|
|
1939
2021
|
},
|
|
1940
2022
|
|
|
1941
2023
|
TSTypeParameter(node, context) {
|
|
2024
|
+
// modifiers: `const T`, `in T` / `out T` (variance)
|
|
2025
|
+
if (node.const) context.write('const ');
|
|
2026
|
+
if (node.in) context.write('in ');
|
|
2027
|
+
if (node.out) context.write('out ');
|
|
2028
|
+
|
|
1942
2029
|
if (node.name && node.name.type) context.visit(node.name);
|
|
1943
2030
|
// @ts-expect-error type mismatch TSESTree and acorn-typescript?
|
|
1944
2031
|
else context.write(node.name, node);
|
|
@@ -1955,19 +2042,14 @@ export default (options = {}) => {
|
|
|
1955
2042
|
},
|
|
1956
2043
|
|
|
1957
2044
|
TSTypePredicate(node, context) {
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
context.visit(node.typeAnnotation);
|
|
1962
|
-
}
|
|
2045
|
+
// `asserts` precedes the parameter name; `is <type>` follows it. Forms:
|
|
2046
|
+
// `x is T`, `asserts x is T`, `asserts x`
|
|
2047
|
+
if (node.asserts) context.write('asserts ');
|
|
1963
2048
|
|
|
1964
|
-
if (node.
|
|
1965
|
-
context.write(' asserts ');
|
|
1966
|
-
} else {
|
|
1967
|
-
context.write(' is ');
|
|
1968
|
-
}
|
|
2049
|
+
if (node.parameterName) context.visit(node.parameterName);
|
|
1969
2050
|
|
|
1970
2051
|
if (node.typeAnnotation) {
|
|
2052
|
+
context.write(' is ');
|
|
1971
2053
|
context.visit(node.typeAnnotation.typeAnnotation);
|
|
1972
2054
|
}
|
|
1973
2055
|
},
|
|
@@ -2005,7 +2087,16 @@ export default (options = {}) => {
|
|
|
2005
2087
|
},
|
|
2006
2088
|
|
|
2007
2089
|
TSMappedType(node, context) {
|
|
2008
|
-
context.write('{
|
|
2090
|
+
context.write('{');
|
|
2091
|
+
|
|
2092
|
+
// `readonly` / `+readonly` / `-readonly` modifier
|
|
2093
|
+
if (node.readonly) {
|
|
2094
|
+
context.write(
|
|
2095
|
+
node.readonly === '-' ? '-readonly ' : node.readonly === '+' ? '+readonly ' : 'readonly '
|
|
2096
|
+
);
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
context.write('[');
|
|
2009
2100
|
|
|
2010
2101
|
const legacy_type_parameter = node.typeParameter;
|
|
2011
2102
|
const key = node.key ?? legacy_type_parameter?.name;
|
|
@@ -2022,8 +2113,19 @@ export default (options = {}) => {
|
|
|
2022
2113
|
context.visit(constraint);
|
|
2023
2114
|
}
|
|
2024
2115
|
|
|
2116
|
+
// `as` key remapping
|
|
2117
|
+
if (node.nameType) {
|
|
2118
|
+
context.write(' as ');
|
|
2119
|
+
context.visit(node.nameType);
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2025
2122
|
context.write(']');
|
|
2026
2123
|
|
|
2124
|
+
// `?` / `+?` / `-?` optionality modifier
|
|
2125
|
+
if (node.optional) {
|
|
2126
|
+
context.write(node.optional === '-' ? '-?' : node.optional === '+' ? '+?' : '?');
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2027
2129
|
if (node.typeAnnotation) {
|
|
2028
2130
|
context.write(': ');
|
|
2029
2131
|
context.visit(node.typeAnnotation);
|
|
@@ -2033,7 +2135,9 @@ export default (options = {}) => {
|
|
|
2033
2135
|
},
|
|
2034
2136
|
|
|
2035
2137
|
TSMethodSignature(node, context) {
|
|
2138
|
+
if (node.computed) context.write('[', token_before(node.key.loc?.start));
|
|
2036
2139
|
context.visit(node.key);
|
|
2140
|
+
if (node.computed) context.write(']', token_at(node.key.loc?.end));
|
|
2037
2141
|
|
|
2038
2142
|
context.write('(');
|
|
2039
2143
|
sequence(
|
|
@@ -2191,8 +2295,17 @@ export default (options = {}) => {
|
|
|
2191
2295
|
context.visit(node.id);
|
|
2192
2296
|
}
|
|
2193
2297
|
|
|
2194
|
-
|
|
2195
|
-
|
|
2298
|
+
// a qualified name (`namespace A.B.C`) is represented as nested
|
|
2299
|
+
// `TSModuleDeclaration`s whose body is the next name part, not a block
|
|
2300
|
+
let body = /** @type {any} */ (node.body);
|
|
2301
|
+
while (body && body.type === 'TSModuleDeclaration') {
|
|
2302
|
+
context.write('.');
|
|
2303
|
+
context.visit(body.id);
|
|
2304
|
+
body = body.body;
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
if (!body) return;
|
|
2308
|
+
context.visit(body);
|
|
2196
2309
|
},
|
|
2197
2310
|
|
|
2198
2311
|
TSNonNullExpression(node, context) {
|
|
@@ -2320,19 +2433,20 @@ function operand_needs_wrap(node, parent, is_right) {
|
|
|
2320
2433
|
return true;
|
|
2321
2434
|
}
|
|
2322
2435
|
|
|
2323
|
-
// `**` can't take a unary/await left operand: `-2 ** 2`, `await x ** 2
|
|
2436
|
+
// `**` can't take a unary/await/assertion left operand: `-2 ** 2`, `await x ** 2`,
|
|
2437
|
+
// `<T>x ** 2` are syntax errors
|
|
2324
2438
|
const unary_base_of_pow =
|
|
2325
2439
|
!is_right &&
|
|
2326
2440
|
parent.operator === '**' &&
|
|
2327
|
-
(node.type === 'UnaryExpression' ||
|
|
2441
|
+
(node.type === 'UnaryExpression' ||
|
|
2442
|
+
node.type === 'AwaitExpression' ||
|
|
2443
|
+
node.type === 'TSTypeAssertion');
|
|
2328
2444
|
if (unary_base_of_pow) return true;
|
|
2329
2445
|
|
|
2330
2446
|
const precedence = EXPRESSIONS_PRECEDENCE[node.type];
|
|
2331
2447
|
const parent_precedence = EXPRESSIONS_PRECEDENCE[parent.type];
|
|
2332
2448
|
if (precedence !== parent_precedence) return precedence < parent_precedence;
|
|
2333
|
-
|
|
2334
2449
|
const operator = /** @type {TSESTree.BinaryExpression} */ (node).operator;
|
|
2335
|
-
|
|
2336
2450
|
if (operator === '**' && parent.operator === '**') {
|
|
2337
2451
|
// exponentiation is right-associative
|
|
2338
2452
|
return !is_right;
|
|
@@ -2375,6 +2489,95 @@ function has_call_expression(node) {
|
|
|
2375
2489
|
return false;
|
|
2376
2490
|
}
|
|
2377
2491
|
|
|
2492
|
+
/**
|
|
2493
|
+
* True when printing `node` as an expression statement would begin with `{`,
|
|
2494
|
+
* `function`, or `class` — which the parser would misread as a block, function
|
|
2495
|
+
* declaration, or class declaration. Walks the left spine following the same
|
|
2496
|
+
* parenthesization the visitors apply, so it stops as soon as a child position
|
|
2497
|
+
* would already be wrapped.
|
|
2498
|
+
* @param {TSESTree.Node} node
|
|
2499
|
+
* @returns {boolean}
|
|
2500
|
+
*/
|
|
2501
|
+
function leads_with_curly_or_keyword(node) {
|
|
2502
|
+
while (node) {
|
|
2503
|
+
switch (node.type) {
|
|
2504
|
+
case 'ObjectExpression':
|
|
2505
|
+
case 'ObjectPattern':
|
|
2506
|
+
case 'FunctionExpression':
|
|
2507
|
+
case 'ClassExpression':
|
|
2508
|
+
return true;
|
|
2509
|
+
|
|
2510
|
+
case 'BinaryExpression':
|
|
2511
|
+
case 'LogicalExpression':
|
|
2512
|
+
if (operand_needs_wrap(node.left, node, false)) return false;
|
|
2513
|
+
node = node.left;
|
|
2514
|
+
continue;
|
|
2515
|
+
|
|
2516
|
+
case 'AssignmentExpression':
|
|
2517
|
+
node = node.left;
|
|
2518
|
+
continue;
|
|
2519
|
+
|
|
2520
|
+
case 'ConditionalExpression':
|
|
2521
|
+
if (
|
|
2522
|
+
EXPRESSIONS_PRECEDENCE[node.test.type] <= EXPRESSIONS_PRECEDENCE.ConditionalExpression
|
|
2523
|
+
) {
|
|
2524
|
+
return false;
|
|
2525
|
+
}
|
|
2526
|
+
node = node.test;
|
|
2527
|
+
continue;
|
|
2528
|
+
|
|
2529
|
+
case 'MemberExpression':
|
|
2530
|
+
if (
|
|
2531
|
+
/** @type {string} */ (node.object.type) === 'ChainExpression' ||
|
|
2532
|
+
EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression
|
|
2533
|
+
) {
|
|
2534
|
+
return false;
|
|
2535
|
+
}
|
|
2536
|
+
node = node.object;
|
|
2537
|
+
continue;
|
|
2538
|
+
|
|
2539
|
+
case 'CallExpression':
|
|
2540
|
+
if (
|
|
2541
|
+
/** @type {string} */ (node.callee.type) === 'ChainExpression' ||
|
|
2542
|
+
EXPRESSIONS_PRECEDENCE[node.callee.type] < EXPRESSIONS_PRECEDENCE.CallExpression
|
|
2543
|
+
) {
|
|
2544
|
+
return false;
|
|
2545
|
+
}
|
|
2546
|
+
node = node.callee;
|
|
2547
|
+
continue;
|
|
2548
|
+
|
|
2549
|
+
case 'TaggedTemplateExpression':
|
|
2550
|
+
if (
|
|
2551
|
+
/** @type {string} */ (node.tag.type) === 'ChainExpression' ||
|
|
2552
|
+
EXPRESSIONS_PRECEDENCE[node.tag.type] < EXPRESSIONS_PRECEDENCE.CallExpression
|
|
2553
|
+
) {
|
|
2554
|
+
return false;
|
|
2555
|
+
}
|
|
2556
|
+
node = node.tag;
|
|
2557
|
+
continue;
|
|
2558
|
+
|
|
2559
|
+
case 'UpdateExpression':
|
|
2560
|
+
if (node.prefix) return false;
|
|
2561
|
+
node = node.argument;
|
|
2562
|
+
continue;
|
|
2563
|
+
|
|
2564
|
+
case 'TSAsExpression':
|
|
2565
|
+
case 'TSSatisfiesExpression':
|
|
2566
|
+
case 'TSNonNullExpression':
|
|
2567
|
+
node = node.expression;
|
|
2568
|
+
continue;
|
|
2569
|
+
|
|
2570
|
+
// a sequence expression always prints its own wrapping parens
|
|
2571
|
+
case 'SequenceExpression':
|
|
2572
|
+
return false;
|
|
2573
|
+
|
|
2574
|
+
default:
|
|
2575
|
+
return false;
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
return false;
|
|
2579
|
+
}
|
|
2580
|
+
|
|
2378
2581
|
/**
|
|
2379
2582
|
* @param {TSESTree.VariableDeclaration} node
|
|
2380
2583
|
* @param {Context} context
|
package/src/languages/types.d.ts
CHANGED
|
@@ -2,6 +2,14 @@ import type { BaseNode } from '../types';
|
|
|
2
2
|
|
|
3
3
|
export type TSOptions = {
|
|
4
4
|
quotes?: 'double' | 'single';
|
|
5
|
+
/**
|
|
6
|
+
* Anchor structural tokens (array/object brackets and braces, preserved
|
|
7
|
+
* parentheses, unary operators, and the closing tokens of calls and
|
|
8
|
+
* computed member access) with one-character source locations, so
|
|
9
|
+
* node-boundary positions always resolve through the source map instead of
|
|
10
|
+
* being attributed to the previous token. Denser maps; identical output.
|
|
11
|
+
*/
|
|
12
|
+
boundaryTokens?: boolean;
|
|
5
13
|
comments?: Comment[];
|
|
6
14
|
getLeadingComments?: (node: BaseNode) => BaseComment[] | undefined;
|
|
7
15
|
getTrailingComments?: (node: BaseNode) => BaseComment[] | undefined;
|
package/types/index.d.ts
CHANGED
|
@@ -95,6 +95,14 @@ declare module 'esrap/languages/ts' {
|
|
|
95
95
|
: SpecialisedVisitors<T> & { _?: (node: T, context: Context, visit: (node: T) => void) => void };
|
|
96
96
|
type TSOptions = {
|
|
97
97
|
quotes?: 'double' | 'single';
|
|
98
|
+
/**
|
|
99
|
+
* Anchor structural tokens (array/object brackets and braces, preserved
|
|
100
|
+
* parentheses, unary operators, and the closing tokens of calls and
|
|
101
|
+
* computed member access) with one-character source locations, so
|
|
102
|
+
* node-boundary positions always resolve through the source map instead of
|
|
103
|
+
* being attributed to the previous token. Denser maps; identical output.
|
|
104
|
+
*/
|
|
105
|
+
boundaryTokens?: boolean;
|
|
98
106
|
comments?: Comment[];
|
|
99
107
|
getLeadingComments?: (node: BaseNode) => BaseComment[] | undefined;
|
|
100
108
|
getTrailingComments?: (node: BaseNode) => BaseComment[] | undefined;
|
|
@@ -149,6 +157,14 @@ declare module 'esrap/languages/tsx' {
|
|
|
149
157
|
: SpecialisedVisitors<T> & { _?: (node: T, context: Context, visit: (node: T) => void) => void };
|
|
150
158
|
type TSOptions = {
|
|
151
159
|
quotes?: 'double' | 'single';
|
|
160
|
+
/**
|
|
161
|
+
* Anchor structural tokens (array/object brackets and braces, preserved
|
|
162
|
+
* parentheses, unary operators, and the closing tokens of calls and
|
|
163
|
+
* computed member access) with one-character source locations, so
|
|
164
|
+
* node-boundary positions always resolve through the source map instead of
|
|
165
|
+
* being attributed to the previous token. Denser maps; identical output.
|
|
166
|
+
*/
|
|
167
|
+
boundaryTokens?: boolean;
|
|
152
168
|
comments?: Comment[];
|
|
153
169
|
getLeadingComments?: (node: BaseNode) => BaseComment[] | undefined;
|
|
154
170
|
getTrailingComments?: (node: BaseNode) => BaseComment[] | undefined;
|
package/types/index.d.ts.map
CHANGED
|
@@ -37,6 +37,6 @@
|
|
|
37
37
|
null,
|
|
38
38
|
null
|
|
39
39
|
],
|
|
40
|
-
"mappings": ";MAEYA,QAAQA;;;;;;;;MAQfC,MAAMA;;MAENC,mBAAmBA;;;;MAIZC,OAAOA;;aAEPC,QAAQA;;;;WAWHC,QAAQA;;;;;;MAWbC,OAAOA;;kBAEFC,YAAYA;;;;;;;;;iBCWbC,KAAKA;;;;cC7CRC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aCLRC,IAAIA;yBACQC,EAAEA;;cAELC,sBAAsBA;MHJ/BZ,QAAQA;;;;;;;;MAQfC,MAAMA;;MAENC,mBAAmBA;;;;MAIZC,OAAOA;;MAEPC,QAAQA;;;MIhBRS,SAASA
|
|
40
|
+
"mappings": ";MAEYA,QAAQA;;;;;;;;MAQfC,MAAMA;;MAENC,mBAAmBA;;;;MAIZC,OAAOA;;aAEPC,QAAQA;;;;WAWHC,QAAQA;;;;;;MAWbC,OAAOA;;kBAEFC,YAAYA;;;;;;;;;iBCWbC,KAAKA;;;;cC7CRC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aCLRC,IAAIA;yBACQC,EAAEA;;cAELC,sBAAsBA;MHJ/BZ,QAAQA;;;;;;;;MAQfC,MAAMA;;MAENC,mBAAmBA;;;;MAIZC,OAAOA;;MAEPC,QAAQA;;;MIhBRS,SAASA;;;;;;;;;;;;;;;WAeXC,QAAQA;;;;;;;kBAODC,WAAWA;;;;;;;kBAOXC,OAAOA;;;;;;;;;;;;aC5BZN,IAAIA;yBACQO,GAAGA;MLFfjB,QAAQA;;;;;;;;MAQfC,MAAMA;;MAENC,mBAAmBA;;;;MAIZC,OAAOA;;MAEPC,QAAQA;;;MIhBRS,SAASA;;;;;;;;;;;;;;;WAeXC,QAAQA;;;;;;;kBAODC,WAAWA;;;;;;;kBAOXC,OAAOA",
|
|
41
41
|
"ignoreList": []
|
|
42
42
|
}
|