espolar 0.2.1 → 0.3.1
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.d.ts +4 -6
- package/dist/index.js +326 -149
- package/package.json +1 -1
- package/src/api.ts +5 -6
- package/src/printer.ts +35 -18
- package/src/printers.ts +542 -184
package/src/printers.ts
CHANGED
|
@@ -1,90 +1,179 @@
|
|
|
1
1
|
import type { PrinterContext, Printers } from "./api.ts";
|
|
2
|
-
import type { AST, Comment } from "./types.ts";
|
|
2
|
+
import type { AST, AST_NODE_TYPES, Comment } from "./types.ts";
|
|
3
3
|
|
|
4
|
-
const EXPRESSIONS_PRECEDENCE
|
|
4
|
+
const EXPRESSIONS_PRECEDENCE = {
|
|
5
|
+
// LHS of =, must NOT parenthesized
|
|
5
6
|
ArrayPattern: 20,
|
|
6
7
|
ObjectPattern: 20,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Super:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
MetaProperty: 19,
|
|
16
|
-
CallExpression: 19,
|
|
17
|
-
ChainExpression: 19,
|
|
18
|
-
ImportExpression: 19,
|
|
19
|
-
NewExpression: 19,
|
|
8
|
+
|
|
9
|
+
// PrimaryExpression
|
|
10
|
+
// @ts-expect-error acorn-typescript compat
|
|
11
|
+
ParenthesizedExpression: 18,
|
|
12
|
+
ThisExpression: 18,
|
|
13
|
+
Super: 18, // like ThisExpression
|
|
14
|
+
Identifier: 18,
|
|
15
|
+
PrivateIdentifier: 18, // LHS of in
|
|
20
16
|
Literal: 18,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
17
|
+
ClassExpression: 18,
|
|
18
|
+
FunctionExpression: 18,
|
|
19
|
+
ObjectExpression: 18,
|
|
20
|
+
ArrayExpression: 18,
|
|
21
|
+
TemplateLiteral: 18,
|
|
22
|
+
// https://react.github.io/jsx/
|
|
23
|
+
JSXElement: 18,
|
|
24
|
+
JSXFragment: 18,
|
|
25
|
+
|
|
26
|
+
MetaProperty: 17,
|
|
27
|
+
MemberExpression: 17,
|
|
28
|
+
// Same precedence as MemberExpression, e.g. foo!.bar
|
|
29
|
+
TSNonNullExpression: 17,
|
|
30
|
+
ChainExpression: 17,
|
|
31
|
+
NewExpression: 17, // only with argument list, 16 if not (we don't print this form)
|
|
32
|
+
CallExpression: 17,
|
|
33
|
+
TaggedTemplateExpression: 17,
|
|
34
|
+
ImportExpression: 17,
|
|
35
|
+
// Between MemberExpression and NewExpression w/o arguments, e.g.
|
|
36
|
+
// f<T>.x // Error
|
|
37
|
+
// (f<T>).x // OK
|
|
38
|
+
// new f<T> // OK
|
|
39
|
+
TSInstantiationExpression: 16.5,
|
|
40
|
+
|
|
41
|
+
// postfix operators
|
|
42
|
+
UpdateExpression: 15,
|
|
43
|
+
// prefix operators
|
|
44
|
+
UnaryExpression: 14,
|
|
45
|
+
AwaitExpression: 14,
|
|
46
|
+
// behaves like postfix operators (e.g. cannot be part of LHS of **)
|
|
47
|
+
TSTypeAssertion: 14,
|
|
48
|
+
|
|
49
|
+
// ranges from 13-5 depending on operator
|
|
50
|
+
BinaryExpression: 13,
|
|
51
|
+
// as/satisfies have same precedence as relational operators
|
|
52
|
+
TSAsExpression: 9,
|
|
53
|
+
TSSatisfiesExpression: 9,
|
|
54
|
+
// ranges from 4-3 depending on operator
|
|
55
|
+
LogicalExpression: 4,
|
|
56
|
+
|
|
57
|
+
AssignmentExpression: 2,
|
|
58
|
+
ConditionalExpression: 2,
|
|
37
59
|
YieldExpression: 2,
|
|
38
|
-
|
|
39
|
-
|
|
60
|
+
ArrowFunctionExpression: 2,
|
|
61
|
+
SpreadElement: 2,
|
|
40
62
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
63
|
+
SequenceExpression: 1,
|
|
64
|
+
} as const satisfies Partial<Record<AST.Expression["type"], number>>;
|
|
65
|
+
|
|
66
|
+
const OPERATOR_PRECEDENCE = {
|
|
67
|
+
"**": 13,
|
|
68
|
+
"*": 12,
|
|
69
|
+
"%": 12,
|
|
70
|
+
"/": 12,
|
|
71
|
+
"+": 11,
|
|
72
|
+
"-": 11,
|
|
73
|
+
"<<": 10,
|
|
74
|
+
">>": 10,
|
|
75
|
+
">>>": 10,
|
|
52
76
|
"<": 9,
|
|
53
77
|
">": 9,
|
|
54
78
|
"<=": 9,
|
|
55
79
|
">=": 9,
|
|
56
80
|
in: 9,
|
|
57
81
|
instanceof: 9,
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
82
|
+
"==": 8,
|
|
83
|
+
"!=": 8,
|
|
84
|
+
"===": 8,
|
|
85
|
+
"!==": 8,
|
|
86
|
+
"&": 7,
|
|
87
|
+
"^": 6,
|
|
88
|
+
"|": 5,
|
|
89
|
+
"&&": 4,
|
|
90
|
+
"??": 3,
|
|
91
|
+
"||": 3,
|
|
92
|
+
} as const satisfies Record<
|
|
93
|
+
(AST.BinaryExpression | AST.LogicalExpression)["operator"],
|
|
94
|
+
number
|
|
95
|
+
>;
|
|
96
|
+
|
|
97
|
+
const ASSOCIATIVE: Record<number, "left" | "right"> = {
|
|
98
|
+
[EXPRESSIONS_PRECEDENCE.MemberExpression]: "left",
|
|
99
|
+
[EXPRESSIONS_PRECEDENCE.UpdateExpression]: "left",
|
|
100
|
+
[EXPRESSIONS_PRECEDENCE.UnaryExpression]: "right",
|
|
101
|
+
[OPERATOR_PRECEDENCE["**"]]: "right",
|
|
102
|
+
[OPERATOR_PRECEDENCE["*"]]: "left",
|
|
103
|
+
[OPERATOR_PRECEDENCE["+"]]: "left",
|
|
104
|
+
[OPERATOR_PRECEDENCE["<"]]: "left",
|
|
105
|
+
[OPERATOR_PRECEDENCE["==="]]: "left",
|
|
106
|
+
[OPERATOR_PRECEDENCE["&"]]: "left",
|
|
107
|
+
[OPERATOR_PRECEDENCE["^"]]: "left",
|
|
108
|
+
[OPERATOR_PRECEDENCE["|"]]: "left",
|
|
109
|
+
[OPERATOR_PRECEDENCE["&&"]]: "left",
|
|
110
|
+
[OPERATOR_PRECEDENCE["||"]]: "left",
|
|
111
|
+
[EXPRESSIONS_PRECEDENCE.AssignmentExpression]: "right",
|
|
67
112
|
};
|
|
68
113
|
|
|
69
|
-
function
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
114
|
+
function getPrecedence(node: AST.Expression | AST.PrivateIdentifier): number {
|
|
115
|
+
if (node.type === "BinaryExpression" || node.type === "LogicalExpression") {
|
|
116
|
+
return (
|
|
117
|
+
OPERATOR_PRECEDENCE[node.operator] ?? EXPRESSIONS_PRECEDENCE[node.type]
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
return EXPRESSIONS_PRECEDENCE[node.type] ?? 20;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
type ExpressionWithPrecedence = keyof typeof EXPRESSIONS_PRECEDENCE;
|
|
124
|
+
type ExpressionTypeWithPrecedenceAs<T extends number> = {
|
|
125
|
+
[K in AST_NODE_TYPES]: K extends ExpressionWithPrecedence
|
|
126
|
+
? (typeof EXPRESSIONS_PRECEDENCE)[K] extends T
|
|
127
|
+
? K
|
|
128
|
+
: never
|
|
129
|
+
: never;
|
|
130
|
+
}[AST_NODE_TYPES];
|
|
131
|
+
|
|
132
|
+
// Expression with same precedence as MemberExpression
|
|
133
|
+
type MemberLikeExpression = Extract<
|
|
134
|
+
AST.Expression,
|
|
135
|
+
{
|
|
136
|
+
type: ExpressionTypeWithPrecedenceAs<
|
|
137
|
+
typeof EXPRESSIONS_PRECEDENCE.MemberExpression
|
|
138
|
+
>;
|
|
139
|
+
}
|
|
140
|
+
>;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Check whether the operand of a Binary/Logical/AssignmentExpression needs parentheses.
|
|
144
|
+
* @param node
|
|
145
|
+
* @param parent
|
|
146
|
+
* @param where
|
|
147
|
+
* @returns
|
|
148
|
+
*/
|
|
149
|
+
function operandOfBinaryExprNeedsParens(
|
|
75
150
|
node: AST.Expression | AST.PrivateIdentifier,
|
|
76
151
|
parent:
|
|
152
|
+
| AST.MemberExpression
|
|
153
|
+
| AST.CallExpression
|
|
154
|
+
| AST.NewExpression
|
|
155
|
+
| AST.TaggedTemplateExpression
|
|
156
|
+
| AST.TSInstantiationExpression
|
|
157
|
+
| AST.TSNonNullExpression
|
|
158
|
+
| AST.TSAsExpression
|
|
159
|
+
| AST.TSSatisfiesExpression
|
|
77
160
|
| AST.BinaryExpression
|
|
78
161
|
| AST.LogicalExpression
|
|
79
|
-
| AST.AssignmentExpression
|
|
80
|
-
|
|
162
|
+
| AST.AssignmentExpression
|
|
163
|
+
| AST.ConditionalExpression,
|
|
164
|
+
where: "left" | "right",
|
|
81
165
|
): boolean {
|
|
166
|
+
// In a BinaryExpression where LHS have a TS postfix, e.g.:
|
|
167
|
+
// (0 as number) & 1;
|
|
168
|
+
// (0 as number) | 1;
|
|
169
|
+
// If op is & or |, then LHS should be parenthesized to disambiguate;
|
|
170
|
+
// otherwise, no need to parenthesize.
|
|
82
171
|
if (
|
|
83
|
-
|
|
84
|
-
node.type === "
|
|
85
|
-
|
|
172
|
+
where === "left" &&
|
|
173
|
+
(node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression") &&
|
|
174
|
+
parent.type === "BinaryExpression"
|
|
86
175
|
) {
|
|
87
|
-
return
|
|
176
|
+
return parent.operator === "&" || parent.operator === "|";
|
|
88
177
|
}
|
|
89
178
|
|
|
90
179
|
// LogicalExpression mixed with ?? requires parens
|
|
@@ -96,62 +185,93 @@ function needsParens(
|
|
|
96
185
|
return true;
|
|
97
186
|
}
|
|
98
187
|
|
|
99
|
-
const precedence =
|
|
100
|
-
const parentPrecedence =
|
|
188
|
+
const precedence = getPrecedence(node);
|
|
189
|
+
const parentPrecedence = getPrecedence(parent);
|
|
190
|
+
|
|
191
|
+
if (
|
|
192
|
+
parent.type === "BinaryExpression" &&
|
|
193
|
+
parent.operator === "**" &&
|
|
194
|
+
precedence === EXPRESSIONS_PRECEDENCE.UnaryExpression
|
|
195
|
+
) {
|
|
196
|
+
// LHS of ** cannot have prefix operators, according to ES spec.
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
101
199
|
|
|
102
200
|
if (precedence !== parentPrecedence) {
|
|
103
|
-
// ** is right-to-left associative: `a ** b ** c` => `a ** (b ** c)`
|
|
104
|
-
if (
|
|
105
|
-
!isRight &&
|
|
106
|
-
precedence === 15 &&
|
|
107
|
-
parentPrecedence === 14 &&
|
|
108
|
-
parent.operator === "**"
|
|
109
|
-
) {
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
201
|
return precedence < parentPrecedence;
|
|
113
202
|
}
|
|
114
203
|
|
|
115
|
-
|
|
116
|
-
|
|
204
|
+
// optional chain cannot appeared as LHS of MemberExpression-like
|
|
205
|
+
if (
|
|
206
|
+
precedence === EXPRESSIONS_PRECEDENCE.MemberExpression &&
|
|
207
|
+
node.type === "ChainExpression"
|
|
208
|
+
) {
|
|
209
|
+
return true;
|
|
117
210
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
211
|
+
if (
|
|
212
|
+
parent.type === "NewExpression" &&
|
|
213
|
+
!validUnparenthesizedNewOperand(node as MemberLikeExpression)
|
|
214
|
+
) {
|
|
215
|
+
// new X(), X cannot contain CallExpression
|
|
216
|
+
return true;
|
|
123
217
|
}
|
|
124
218
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
return OPERATOR_PRECEDENCE[nodeOp] < OPERATOR_PRECEDENCE[parent.operator];
|
|
219
|
+
const associative = ASSOCIATIVE[precedence] ?? "left";
|
|
220
|
+
return associative !== where;
|
|
129
221
|
}
|
|
130
222
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
case "ConditionalExpression":
|
|
143
|
-
return body.test.type === "ObjectExpression";
|
|
144
|
-
case "TSAsExpression":
|
|
145
|
-
case "TSSatisfiesExpression":
|
|
146
|
-
case "TSNonNullExpression":
|
|
147
|
-
return body.expression
|
|
148
|
-
? arrowConciseBodyNeedsWrap(body.expression)
|
|
149
|
-
: false;
|
|
150
|
-
default:
|
|
223
|
+
/**
|
|
224
|
+
* A valid unparenthesized `new` operand must be a member chain
|
|
225
|
+
* which not contains a CallExpression
|
|
226
|
+
*/
|
|
227
|
+
function validUnparenthesizedNewOperand(node: MemberLikeExpression): boolean {
|
|
228
|
+
if (node.type === "ChainExpression" || node.type === "ImportExpression") {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
let cur: AST.Expression = node;
|
|
232
|
+
while (true) {
|
|
233
|
+
if (cur.type === "CallExpression") {
|
|
151
234
|
return false;
|
|
235
|
+
} else if (cur.type === "TSNonNullExpression") {
|
|
236
|
+
cur = cur.expression;
|
|
237
|
+
} else if (cur.type === "MemberExpression") {
|
|
238
|
+
cur = cur.object;
|
|
239
|
+
} else if (cur.type === "TaggedTemplateExpression") {
|
|
240
|
+
cur = cur.tag;
|
|
241
|
+
} else {
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
152
244
|
}
|
|
153
245
|
}
|
|
154
246
|
|
|
247
|
+
function operandOfUnaryExprNeedsParens(node: AST.Expression): boolean {
|
|
248
|
+
return (
|
|
249
|
+
EXPRESSIONS_PRECEDENCE[node.type] < EXPRESSIONS_PRECEDENCE.UnaryExpression
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function expectAssignmentExprNeedsParen(
|
|
254
|
+
node: AST.Expression | AST.SpreadElement,
|
|
255
|
+
): boolean {
|
|
256
|
+
return (
|
|
257
|
+
EXPRESSIONS_PRECEDENCE[node.type] <
|
|
258
|
+
EXPRESSIONS_PRECEDENCE.AssignmentExpression
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function expectLHSExprNeedsParen(
|
|
263
|
+
node: AST.Expression | AST.SpreadElement,
|
|
264
|
+
): boolean {
|
|
265
|
+
return (
|
|
266
|
+
EXPRESSIONS_PRECEDENCE[node.type] < EXPRESSIONS_PRECEDENCE.MemberExpression
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function commentNeedsNewline(comment: Comment): boolean {
|
|
271
|
+
if (comment.type === "Line") return true;
|
|
272
|
+
return comment.value.includes("\n");
|
|
273
|
+
}
|
|
274
|
+
|
|
155
275
|
// Printers
|
|
156
276
|
export const defaultPrinters = {
|
|
157
277
|
Program: printProgram,
|
|
@@ -306,7 +426,57 @@ export const defaultPrinters = {
|
|
|
306
426
|
// JS – Statements
|
|
307
427
|
|
|
308
428
|
function printProgram(program: AST.Program, context: PrinterContext): void {
|
|
309
|
-
context.
|
|
429
|
+
context.writeNodeListWithNewLineSep(program.body);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function canStartExpressionStatement(
|
|
433
|
+
node: AST.Expression | AST.PrivateIdentifier,
|
|
434
|
+
): boolean {
|
|
435
|
+
let lhs: AST.Expression | AST.PrivateIdentifier;
|
|
436
|
+
switch (node.type) {
|
|
437
|
+
default:
|
|
438
|
+
return true;
|
|
439
|
+
case "ObjectExpression":
|
|
440
|
+
case "FunctionExpression":
|
|
441
|
+
case "ClassExpression":
|
|
442
|
+
case "ObjectPattern":
|
|
443
|
+
return false;
|
|
444
|
+
case "AssignmentExpression":
|
|
445
|
+
case "LogicalExpression":
|
|
446
|
+
case "BinaryExpression":
|
|
447
|
+
lhs = node.left;
|
|
448
|
+
break;
|
|
449
|
+
case "TSAsExpression":
|
|
450
|
+
case "TSSatisfiesExpression":
|
|
451
|
+
case "TSNonNullExpression":
|
|
452
|
+
lhs = node.expression;
|
|
453
|
+
break;
|
|
454
|
+
case "CallExpression":
|
|
455
|
+
lhs = node.callee;
|
|
456
|
+
break;
|
|
457
|
+
case "MemberExpression":
|
|
458
|
+
lhs = node.object;
|
|
459
|
+
if (node.computed && lhs.type === "Identifier" && lhs.name === "let") {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
break;
|
|
463
|
+
case "TaggedTemplateExpression":
|
|
464
|
+
lhs = node.tag;
|
|
465
|
+
break;
|
|
466
|
+
case "ConditionalExpression":
|
|
467
|
+
lhs = node.test;
|
|
468
|
+
break;
|
|
469
|
+
case "SequenceExpression":
|
|
470
|
+
return canStartExpressionStatement(node.expressions[0]);
|
|
471
|
+
case "UpdateExpression":
|
|
472
|
+
return canStartExpressionStatement(node.argument);
|
|
473
|
+
case "ChainExpression":
|
|
474
|
+
return canStartExpressionStatement(node.expression);
|
|
475
|
+
}
|
|
476
|
+
return (
|
|
477
|
+
operandOfBinaryExprNeedsParens(lhs, node, "left") ||
|
|
478
|
+
canStartExpressionStatement(lhs)
|
|
479
|
+
);
|
|
310
480
|
}
|
|
311
481
|
|
|
312
482
|
function printExpressionStatement(
|
|
@@ -314,11 +484,7 @@ function printExpressionStatement(
|
|
|
314
484
|
context: PrinterContext,
|
|
315
485
|
): void {
|
|
316
486
|
const expr = statement.expression;
|
|
317
|
-
if (
|
|
318
|
-
expr.type === "ObjectExpression" ||
|
|
319
|
-
expr.type === "FunctionExpression" ||
|
|
320
|
-
(expr.type === "AssignmentExpression" && expr.left.type === "ObjectPattern")
|
|
321
|
-
) {
|
|
487
|
+
if (!canStartExpressionStatement(expr)) {
|
|
322
488
|
context.write("(");
|
|
323
489
|
context.writeNode(expr);
|
|
324
490
|
context.write(");");
|
|
@@ -358,7 +524,14 @@ function printVariableDeclarator(
|
|
|
358
524
|
}
|
|
359
525
|
if (declarator.init) {
|
|
360
526
|
context.write(" = ");
|
|
361
|
-
|
|
527
|
+
const needsParens = expectAssignmentExprNeedsParen(declarator.init);
|
|
528
|
+
if (needsParens) {
|
|
529
|
+
context.write("(");
|
|
530
|
+
context.writeNode(declarator.init);
|
|
531
|
+
context.write(")");
|
|
532
|
+
} else {
|
|
533
|
+
context.writeNode(declarator.init);
|
|
534
|
+
}
|
|
362
535
|
}
|
|
363
536
|
}
|
|
364
537
|
|
|
@@ -370,7 +543,7 @@ function printBlockStatement(
|
|
|
370
543
|
context.write("{");
|
|
371
544
|
if (body.length > 0) {
|
|
372
545
|
context.write("\n");
|
|
373
|
-
context.
|
|
546
|
+
context.writeNodeListWithNewLineSep(body);
|
|
374
547
|
context.write("\n");
|
|
375
548
|
}
|
|
376
549
|
context.write("}");
|
|
@@ -660,12 +833,21 @@ function printUnaryExpression(
|
|
|
660
833
|
if (expr.operator.length > 1) {
|
|
661
834
|
context.write(" ");
|
|
662
835
|
}
|
|
663
|
-
const
|
|
664
|
-
if (
|
|
836
|
+
const needsParen = operandOfUnaryExprNeedsParens(expr.argument);
|
|
837
|
+
if (needsParen) {
|
|
665
838
|
context.write("(");
|
|
666
839
|
context.writeNode(expr.argument);
|
|
667
840
|
context.write(")");
|
|
668
841
|
} else {
|
|
842
|
+
if (
|
|
843
|
+
expr.operator.length === 1 &&
|
|
844
|
+
(expr.argument.type === "UnaryExpression" ||
|
|
845
|
+
expr.argument.type === "UpdateExpression") &&
|
|
846
|
+
expr.argument.operator.startsWith(expr.operator)
|
|
847
|
+
) {
|
|
848
|
+
// `- -x` or `+ ++x` should not be printed as `--x` or `+++x`
|
|
849
|
+
context.write(" ");
|
|
850
|
+
}
|
|
669
851
|
context.writeNode(expr.argument);
|
|
670
852
|
}
|
|
671
853
|
}
|
|
@@ -704,7 +886,7 @@ function printBinaryExpression(
|
|
|
704
886
|
const left = expression.left;
|
|
705
887
|
const right = expression.right;
|
|
706
888
|
|
|
707
|
-
if (
|
|
889
|
+
if (operandOfBinaryExprNeedsParens(left, expression, "left")) {
|
|
708
890
|
context.write("(");
|
|
709
891
|
context.writeNode(left);
|
|
710
892
|
context.write(")");
|
|
@@ -716,7 +898,7 @@ function printBinaryExpression(
|
|
|
716
898
|
context.write(String(expression.operator));
|
|
717
899
|
context.write(" ");
|
|
718
900
|
|
|
719
|
-
if (
|
|
901
|
+
if (operandOfBinaryExprNeedsParens(right, expression, "right")) {
|
|
720
902
|
context.write("(");
|
|
721
903
|
context.writeNode(right);
|
|
722
904
|
context.write(")");
|
|
@@ -729,8 +911,7 @@ function printConditionalExpression(
|
|
|
729
911
|
expr: AST.ConditionalExpression,
|
|
730
912
|
context: PrinterContext,
|
|
731
913
|
): void {
|
|
732
|
-
|
|
733
|
-
if (testPrec <= EXPRESSIONS_PRECEDENCE.ConditionalExpression) {
|
|
914
|
+
if (operandOfBinaryExprNeedsParens(expr.test, expr, "left")) {
|
|
734
915
|
context.write("(");
|
|
735
916
|
context.writeNode(expr.test);
|
|
736
917
|
context.write(")");
|
|
@@ -740,7 +921,13 @@ function printConditionalExpression(
|
|
|
740
921
|
context.write(" ? ");
|
|
741
922
|
context.writeNode(expr.consequent);
|
|
742
923
|
context.write(" : ");
|
|
743
|
-
|
|
924
|
+
if (operandOfBinaryExprNeedsParens(expr.alternate, expr, "right")) {
|
|
925
|
+
context.write("(");
|
|
926
|
+
context.writeNode(expr.alternate);
|
|
927
|
+
context.write(")");
|
|
928
|
+
} else {
|
|
929
|
+
context.writeNode(expr.alternate);
|
|
930
|
+
}
|
|
744
931
|
}
|
|
745
932
|
|
|
746
933
|
function printYieldExpression(
|
|
@@ -753,12 +940,14 @@ function printYieldExpression(
|
|
|
753
940
|
const leadingComments = context.options.getLeadingComments?.(expr.argument);
|
|
754
941
|
const needsParensASi =
|
|
755
942
|
leadingComments?.some((c) => commentNeedsNewline(c)) ?? false;
|
|
756
|
-
|
|
943
|
+
const needsParens =
|
|
944
|
+
needsParensASi || expectAssignmentExprNeedsParen(expr.argument);
|
|
945
|
+
if (needsParens) {
|
|
757
946
|
context.write("(");
|
|
758
|
-
|
|
759
|
-
context.writeNode(expr.argument);
|
|
760
|
-
if (needsParensASi) {
|
|
947
|
+
context.writeNode(expr.argument);
|
|
761
948
|
context.write(")");
|
|
949
|
+
} else {
|
|
950
|
+
context.writeNode(expr.argument);
|
|
762
951
|
}
|
|
763
952
|
}
|
|
764
953
|
}
|
|
@@ -769,8 +958,8 @@ function printAwaitExpression(
|
|
|
769
958
|
): void {
|
|
770
959
|
context.write("await");
|
|
771
960
|
if (expr.argument) {
|
|
772
|
-
const
|
|
773
|
-
if (
|
|
961
|
+
const needsParens = operandOfUnaryExprNeedsParens(expr.argument);
|
|
962
|
+
if (needsParens) {
|
|
774
963
|
context.write(" (");
|
|
775
964
|
context.writeNode(expr.argument);
|
|
776
965
|
context.write(")");
|
|
@@ -785,17 +974,19 @@ function printSequenceExpression(
|
|
|
785
974
|
expr: AST.SequenceExpression,
|
|
786
975
|
context: PrinterContext,
|
|
787
976
|
): void {
|
|
788
|
-
context.write("(");
|
|
789
977
|
context.writeNodeList(expr.expressions, ", ");
|
|
790
|
-
context.write(")");
|
|
791
978
|
}
|
|
792
979
|
|
|
793
980
|
function printCallExpression(
|
|
794
981
|
expression: AST.CallExpression,
|
|
795
982
|
context: PrinterContext,
|
|
796
983
|
): void {
|
|
797
|
-
const
|
|
798
|
-
|
|
984
|
+
const needsParens = operandOfBinaryExprNeedsParens(
|
|
985
|
+
expression.callee,
|
|
986
|
+
expression,
|
|
987
|
+
"left",
|
|
988
|
+
);
|
|
989
|
+
if (needsParens) {
|
|
799
990
|
context.write("(");
|
|
800
991
|
context.writeNode(expression.callee);
|
|
801
992
|
context.write(")");
|
|
@@ -815,7 +1006,7 @@ function printCallExpression(
|
|
|
815
1006
|
} else {
|
|
816
1007
|
context.write("(");
|
|
817
1008
|
}
|
|
818
|
-
context.
|
|
1009
|
+
context.writeExpressionListWithCommaSep(expression.arguments);
|
|
819
1010
|
context.write(")");
|
|
820
1011
|
}
|
|
821
1012
|
|
|
@@ -824,11 +1015,12 @@ function printNewExpression(
|
|
|
824
1015
|
context: PrinterContext,
|
|
825
1016
|
): void {
|
|
826
1017
|
context.write("new ");
|
|
827
|
-
const
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
)
|
|
1018
|
+
const needsParens = operandOfBinaryExprNeedsParens(
|
|
1019
|
+
expression.callee,
|
|
1020
|
+
expression,
|
|
1021
|
+
"left",
|
|
1022
|
+
);
|
|
1023
|
+
if (needsParens) {
|
|
832
1024
|
context.write("(");
|
|
833
1025
|
context.writeNode(expression.callee);
|
|
834
1026
|
context.write(")");
|
|
@@ -845,23 +1037,10 @@ function printNewExpression(
|
|
|
845
1037
|
} else {
|
|
846
1038
|
context.write("(");
|
|
847
1039
|
}
|
|
848
|
-
context.
|
|
1040
|
+
context.writeExpressionListWithCommaSep(expression.arguments);
|
|
849
1041
|
context.write(")");
|
|
850
1042
|
}
|
|
851
1043
|
|
|
852
|
-
function hasCallExpression(node: AST.Expression): boolean {
|
|
853
|
-
let cur: AST.Expression | undefined = node;
|
|
854
|
-
while (cur) {
|
|
855
|
-
if (cur.type === "CallExpression") return true;
|
|
856
|
-
if (cur.type === "MemberExpression") {
|
|
857
|
-
cur = cur.object;
|
|
858
|
-
} else {
|
|
859
|
-
return false;
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
return false;
|
|
863
|
-
}
|
|
864
|
-
|
|
865
1044
|
function printChainExpression(
|
|
866
1045
|
expression: AST.ChainExpression,
|
|
867
1046
|
context: PrinterContext,
|
|
@@ -873,8 +1052,12 @@ function printMemberExpression(
|
|
|
873
1052
|
expression: AST.MemberExpression,
|
|
874
1053
|
context: PrinterContext,
|
|
875
1054
|
): void {
|
|
876
|
-
const
|
|
877
|
-
|
|
1055
|
+
const needsParens = operandOfBinaryExprNeedsParens(
|
|
1056
|
+
expression.object,
|
|
1057
|
+
expression,
|
|
1058
|
+
"left",
|
|
1059
|
+
);
|
|
1060
|
+
if (needsParens) {
|
|
878
1061
|
context.write("(");
|
|
879
1062
|
context.writeNode(expression.object);
|
|
880
1063
|
context.write(")");
|
|
@@ -915,7 +1098,7 @@ function printArrayExpression(
|
|
|
915
1098
|
context: PrinterContext,
|
|
916
1099
|
): void {
|
|
917
1100
|
context.write("[");
|
|
918
|
-
context.
|
|
1101
|
+
context.writeExpressionListWithCommaSep(array.elements);
|
|
919
1102
|
context.write("]");
|
|
920
1103
|
}
|
|
921
1104
|
|
|
@@ -950,7 +1133,10 @@ function printProperty(
|
|
|
950
1133
|
}
|
|
951
1134
|
|
|
952
1135
|
// shorthand method
|
|
953
|
-
if (
|
|
1136
|
+
if (
|
|
1137
|
+
value.type === "FunctionExpression" &&
|
|
1138
|
+
(property.method || property.kind !== "init")
|
|
1139
|
+
) {
|
|
954
1140
|
if (property.kind !== "init") {
|
|
955
1141
|
context.write(property.kind + " ");
|
|
956
1142
|
}
|
|
@@ -981,9 +1167,6 @@ function printProperty(
|
|
|
981
1167
|
context.writeNode(property.key);
|
|
982
1168
|
context.write("]: ");
|
|
983
1169
|
} else {
|
|
984
|
-
if (property.kind === "get" || property.kind === "set") {
|
|
985
|
-
context.write(property.kind + " ");
|
|
986
|
-
}
|
|
987
1170
|
context.writeNode(property.key);
|
|
988
1171
|
context.write(": ");
|
|
989
1172
|
}
|
|
@@ -996,7 +1179,14 @@ function printSpreadElement(
|
|
|
996
1179
|
context: PrinterContext,
|
|
997
1180
|
): void {
|
|
998
1181
|
context.write("...");
|
|
999
|
-
|
|
1182
|
+
const needsParens = expectAssignmentExprNeedsParen(spread.argument);
|
|
1183
|
+
if (needsParens) {
|
|
1184
|
+
context.write("(");
|
|
1185
|
+
context.writeNode(spread.argument);
|
|
1186
|
+
context.write(")");
|
|
1187
|
+
} else {
|
|
1188
|
+
context.writeNode(spread.argument);
|
|
1189
|
+
}
|
|
1000
1190
|
}
|
|
1001
1191
|
|
|
1002
1192
|
function printRestElement(
|
|
@@ -1037,7 +1227,17 @@ function printTaggedTemplateExpression(
|
|
|
1037
1227
|
node: AST.TaggedTemplateExpression,
|
|
1038
1228
|
context: PrinterContext,
|
|
1039
1229
|
): void {
|
|
1040
|
-
|
|
1230
|
+
const needsParens = operandOfBinaryExprNeedsParens(node.tag, node, "left");
|
|
1231
|
+
if (needsParens) {
|
|
1232
|
+
context.write("(");
|
|
1233
|
+
context.writeNode(node.tag);
|
|
1234
|
+
context.write(")");
|
|
1235
|
+
} else {
|
|
1236
|
+
context.writeNode(node.tag);
|
|
1237
|
+
}
|
|
1238
|
+
if (node.typeArguments) {
|
|
1239
|
+
context.writeNode(node.typeArguments);
|
|
1240
|
+
}
|
|
1041
1241
|
context.writeNode(node.quasi);
|
|
1042
1242
|
}
|
|
1043
1243
|
|
|
@@ -1114,6 +1314,60 @@ function printFunction(
|
|
|
1114
1314
|
}
|
|
1115
1315
|
}
|
|
1116
1316
|
|
|
1317
|
+
function canStartConciseBody(
|
|
1318
|
+
body: AST.BlockStatement | AST.Expression | AST.PrivateIdentifier,
|
|
1319
|
+
): boolean {
|
|
1320
|
+
if (body.type === "BlockStatement" || body.type === "PrivateIdentifier") {
|
|
1321
|
+
return true;
|
|
1322
|
+
}
|
|
1323
|
+
if (expectAssignmentExprNeedsParen(body)) {
|
|
1324
|
+
return false;
|
|
1325
|
+
}
|
|
1326
|
+
let lhs: AST.Expression | AST.PrivateIdentifier;
|
|
1327
|
+
switch (body.type) {
|
|
1328
|
+
default:
|
|
1329
|
+
return true;
|
|
1330
|
+
case "ObjectExpression":
|
|
1331
|
+
case "FunctionExpression":
|
|
1332
|
+
case "ClassExpression":
|
|
1333
|
+
case "ObjectPattern":
|
|
1334
|
+
return false;
|
|
1335
|
+
case "AssignmentExpression":
|
|
1336
|
+
case "LogicalExpression":
|
|
1337
|
+
case "BinaryExpression":
|
|
1338
|
+
lhs = body.left;
|
|
1339
|
+
break;
|
|
1340
|
+
case "TSAsExpression":
|
|
1341
|
+
case "TSSatisfiesExpression":
|
|
1342
|
+
case "TSNonNullExpression":
|
|
1343
|
+
lhs = body.expression;
|
|
1344
|
+
break;
|
|
1345
|
+
case "CallExpression":
|
|
1346
|
+
lhs = body.callee;
|
|
1347
|
+
break;
|
|
1348
|
+
case "MemberExpression":
|
|
1349
|
+
lhs = body.object;
|
|
1350
|
+
if (body.computed && lhs.type === "Identifier" && lhs.name === "let") {
|
|
1351
|
+
return false;
|
|
1352
|
+
}
|
|
1353
|
+
break;
|
|
1354
|
+
case "TaggedTemplateExpression":
|
|
1355
|
+
lhs = body.tag;
|
|
1356
|
+
break;
|
|
1357
|
+
case "ConditionalExpression":
|
|
1358
|
+
lhs = body.test;
|
|
1359
|
+
break;
|
|
1360
|
+
case "UpdateExpression":
|
|
1361
|
+
return canStartConciseBody(body.argument);
|
|
1362
|
+
case "ChainExpression":
|
|
1363
|
+
return canStartConciseBody(body.expression);
|
|
1364
|
+
}
|
|
1365
|
+
return (
|
|
1366
|
+
operandOfBinaryExprNeedsParens(lhs, body, "left") ||
|
|
1367
|
+
canStartConciseBody(lhs)
|
|
1368
|
+
);
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1117
1371
|
function printArrowFunctionExpression(
|
|
1118
1372
|
fn: AST.ArrowFunctionExpression,
|
|
1119
1373
|
context: PrinterContext,
|
|
@@ -1130,7 +1384,7 @@ function printArrowFunctionExpression(
|
|
|
1130
1384
|
writeReturnType(fn, context);
|
|
1131
1385
|
context.write(" => ");
|
|
1132
1386
|
const body = fn.body;
|
|
1133
|
-
if (
|
|
1387
|
+
if (!canStartConciseBody(body)) {
|
|
1134
1388
|
context.write("(");
|
|
1135
1389
|
context.writeNode(body);
|
|
1136
1390
|
context.write(")");
|
|
@@ -1175,7 +1429,14 @@ function printClass(
|
|
|
1175
1429
|
}
|
|
1176
1430
|
if (node.superClass) {
|
|
1177
1431
|
context.write("extends ");
|
|
1178
|
-
|
|
1432
|
+
const needsParens = expectLHSExprNeedsParen(node.superClass);
|
|
1433
|
+
if (needsParens) {
|
|
1434
|
+
context.write("(");
|
|
1435
|
+
context.writeNode(node.superClass);
|
|
1436
|
+
context.write(")");
|
|
1437
|
+
} else {
|
|
1438
|
+
context.writeNode(node.superClass);
|
|
1439
|
+
}
|
|
1179
1440
|
if (node.superTypeArguments) {
|
|
1180
1441
|
context.writeNode(node.superTypeArguments);
|
|
1181
1442
|
} else if (node.superTypeParameters) {
|
|
@@ -1197,7 +1458,7 @@ function printClassBody(node: AST.ClassBody, context: PrinterContext): void {
|
|
|
1197
1458
|
const body = node.body;
|
|
1198
1459
|
if (body.length > 0) {
|
|
1199
1460
|
context.write("\n");
|
|
1200
|
-
context.
|
|
1461
|
+
context.writeNodeListWithNewLineSep(body);
|
|
1201
1462
|
context.write("\n");
|
|
1202
1463
|
}
|
|
1203
1464
|
context.write("}");
|
|
@@ -1211,15 +1472,43 @@ function printStaticBlock(
|
|
|
1211
1472
|
const body = node.body;
|
|
1212
1473
|
if (body.length > 0) {
|
|
1213
1474
|
context.write("\n");
|
|
1214
|
-
context.
|
|
1475
|
+
context.writeNodeListWithNewLineSep(body);
|
|
1215
1476
|
context.write("\n");
|
|
1216
1477
|
}
|
|
1217
1478
|
context.write("}");
|
|
1218
1479
|
}
|
|
1219
1480
|
|
|
1481
|
+
function validUnparenthesizedDecorator(node: AST.Expression): boolean {
|
|
1482
|
+
let current: AST.Expression = node;
|
|
1483
|
+
if (current.type === "CallExpression") {
|
|
1484
|
+
current = current.callee;
|
|
1485
|
+
}
|
|
1486
|
+
if (current.type === "TSInstantiationExpression") {
|
|
1487
|
+
current = current.expression;
|
|
1488
|
+
}
|
|
1489
|
+
while (true) {
|
|
1490
|
+
if (current.type === "Identifier") {
|
|
1491
|
+
return true;
|
|
1492
|
+
} else if (current.type === "MemberExpression") {
|
|
1493
|
+
if (current.computed) {
|
|
1494
|
+
return false;
|
|
1495
|
+
}
|
|
1496
|
+
current = current.object;
|
|
1497
|
+
} else {
|
|
1498
|
+
return false;
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1220
1503
|
function printDecorator(node: AST.Decorator, context: PrinterContext): void {
|
|
1221
1504
|
context.write("@");
|
|
1222
|
-
|
|
1505
|
+
if (!validUnparenthesizedDecorator(node.expression)) {
|
|
1506
|
+
context.write("(");
|
|
1507
|
+
context.writeNode(node.expression);
|
|
1508
|
+
context.write(")");
|
|
1509
|
+
} else {
|
|
1510
|
+
context.writeNode(node.expression);
|
|
1511
|
+
}
|
|
1223
1512
|
context.write("\n");
|
|
1224
1513
|
}
|
|
1225
1514
|
|
|
@@ -1375,13 +1664,17 @@ function printImportDeclaration(
|
|
|
1375
1664
|
}
|
|
1376
1665
|
|
|
1377
1666
|
if (namespaceSpec) {
|
|
1378
|
-
if (wroteDefault)
|
|
1667
|
+
if (wroteDefault) {
|
|
1668
|
+
context.write(", ");
|
|
1669
|
+
}
|
|
1379
1670
|
context.write("* as ");
|
|
1380
1671
|
context.writeNode(namespaceSpec.local);
|
|
1381
1672
|
}
|
|
1382
1673
|
|
|
1383
1674
|
if (namedSpecs.length > 0) {
|
|
1384
|
-
if (wroteDefault || namespaceSpec)
|
|
1675
|
+
if (wroteDefault || namespaceSpec) {
|
|
1676
|
+
context.write(", ");
|
|
1677
|
+
}
|
|
1385
1678
|
context.write("{ ");
|
|
1386
1679
|
context.writeNodeList(namedSpecs, ", ");
|
|
1387
1680
|
context.write(" }");
|
|
@@ -1546,8 +1839,12 @@ function printTSAsExpression(
|
|
|
1546
1839
|
expression: AST.TSAsExpression,
|
|
1547
1840
|
context: PrinterContext,
|
|
1548
1841
|
): void {
|
|
1549
|
-
const
|
|
1550
|
-
|
|
1842
|
+
const needsParens = operandOfBinaryExprNeedsParens(
|
|
1843
|
+
expression.expression,
|
|
1844
|
+
expression,
|
|
1845
|
+
"left",
|
|
1846
|
+
);
|
|
1847
|
+
if (needsParens) {
|
|
1551
1848
|
context.write("(");
|
|
1552
1849
|
context.writeNode(expression.expression);
|
|
1553
1850
|
context.write(")");
|
|
@@ -1562,8 +1859,12 @@ function printTSSatisfiesExpression(
|
|
|
1562
1859
|
expression: AST.TSSatisfiesExpression,
|
|
1563
1860
|
context: PrinterContext,
|
|
1564
1861
|
): void {
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1862
|
+
const needsParens = operandOfBinaryExprNeedsParens(
|
|
1863
|
+
expression.expression,
|
|
1864
|
+
expression,
|
|
1865
|
+
"left",
|
|
1866
|
+
);
|
|
1867
|
+
if (needsParens) {
|
|
1567
1868
|
context.write("(");
|
|
1568
1869
|
context.writeNode(expression.expression);
|
|
1569
1870
|
context.write(")");
|
|
@@ -1581,8 +1882,8 @@ function printTSTypeAssertion(
|
|
|
1581
1882
|
context.write("<");
|
|
1582
1883
|
context.writeNode(expression.typeAnnotation);
|
|
1583
1884
|
context.write(">");
|
|
1584
|
-
const
|
|
1585
|
-
if (
|
|
1885
|
+
const needsParens = operandOfUnaryExprNeedsParens(expression.expression);
|
|
1886
|
+
if (needsParens) {
|
|
1586
1887
|
context.write("(");
|
|
1587
1888
|
context.writeNode(expression.expression);
|
|
1588
1889
|
context.write(")");
|
|
@@ -1595,7 +1896,18 @@ function printTSNonNullExpression(
|
|
|
1595
1896
|
expression: AST.TSNonNullExpression,
|
|
1596
1897
|
context: PrinterContext,
|
|
1597
1898
|
): void {
|
|
1598
|
-
|
|
1899
|
+
const needsParens = operandOfBinaryExprNeedsParens(
|
|
1900
|
+
expression.expression,
|
|
1901
|
+
expression,
|
|
1902
|
+
"left",
|
|
1903
|
+
);
|
|
1904
|
+
if (needsParens) {
|
|
1905
|
+
context.write("(");
|
|
1906
|
+
context.writeNode(expression.expression);
|
|
1907
|
+
context.write(")");
|
|
1908
|
+
} else {
|
|
1909
|
+
context.writeNode(expression.expression);
|
|
1910
|
+
}
|
|
1599
1911
|
context.write("!");
|
|
1600
1912
|
}
|
|
1601
1913
|
|
|
@@ -1991,7 +2303,14 @@ function printTSMappedType(
|
|
|
1991
2303
|
node: AST.TSMappedType,
|
|
1992
2304
|
context: PrinterContext,
|
|
1993
2305
|
): void {
|
|
1994
|
-
context.write("{
|
|
2306
|
+
context.write("{ ");
|
|
2307
|
+
if (node.readonly) {
|
|
2308
|
+
if (typeof node.readonly === "string") {
|
|
2309
|
+
context.write(node.readonly);
|
|
2310
|
+
}
|
|
2311
|
+
context.write("readonly ");
|
|
2312
|
+
}
|
|
2313
|
+
context.write("[");
|
|
1995
2314
|
const legacyTp = node.typeParameter;
|
|
1996
2315
|
const key = node.key ?? legacyTp?.name;
|
|
1997
2316
|
const constraint = node.constraint ?? legacyTp?.constraint;
|
|
@@ -2007,7 +2326,17 @@ function printTSMappedType(
|
|
|
2007
2326
|
context.write(" in ");
|
|
2008
2327
|
context.writeNode(constraint);
|
|
2009
2328
|
}
|
|
2329
|
+
if (node.nameType) {
|
|
2330
|
+
context.write(" as ");
|
|
2331
|
+
context.writeNode(node.nameType);
|
|
2332
|
+
}
|
|
2010
2333
|
context.write("]");
|
|
2334
|
+
if (node.optional) {
|
|
2335
|
+
if (typeof node.optional === "string") {
|
|
2336
|
+
context.write(node.optional);
|
|
2337
|
+
}
|
|
2338
|
+
context.write("?");
|
|
2339
|
+
}
|
|
2011
2340
|
if (node.typeAnnotation) {
|
|
2012
2341
|
context.write(": ");
|
|
2013
2342
|
context.writeNode(node.typeAnnotation);
|
|
@@ -2164,11 +2493,18 @@ function printTSModuleDeclaration(
|
|
|
2164
2493
|
context.write(String(kind) + " ");
|
|
2165
2494
|
context.writeNode(node.id);
|
|
2166
2495
|
}
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2496
|
+
let body = node.body as
|
|
2497
|
+
| AST.TSModuleDeclaration
|
|
2498
|
+
| AST.TSModuleBlock
|
|
2499
|
+
| undefined;
|
|
2500
|
+
while (body?.type === "TSModuleDeclaration") {
|
|
2501
|
+
context.write(".");
|
|
2502
|
+
context.writeNode(body.id);
|
|
2503
|
+
body = body.body;
|
|
2504
|
+
}
|
|
2505
|
+
if (body) {
|
|
2506
|
+
context.write(" ");
|
|
2507
|
+
context.writeNode(body);
|
|
2172
2508
|
}
|
|
2173
2509
|
}
|
|
2174
2510
|
|
|
@@ -2177,7 +2513,7 @@ function printTSModuleBlock(
|
|
|
2177
2513
|
context: PrinterContext,
|
|
2178
2514
|
): void {
|
|
2179
2515
|
context.write("{\n");
|
|
2180
|
-
context.
|
|
2516
|
+
context.writeNodeListWithNewLineSep(node.body);
|
|
2181
2517
|
context.write("\n}");
|
|
2182
2518
|
}
|
|
2183
2519
|
|
|
@@ -2239,10 +2575,21 @@ function printTSNamespaceExportDeclaration(
|
|
|
2239
2575
|
}
|
|
2240
2576
|
|
|
2241
2577
|
function printTSInstantiationExpression(
|
|
2242
|
-
node:
|
|
2578
|
+
node: AST.TSInstantiationExpression,
|
|
2243
2579
|
context: PrinterContext,
|
|
2244
2580
|
): void {
|
|
2245
|
-
|
|
2581
|
+
const needsParens = operandOfBinaryExprNeedsParens(
|
|
2582
|
+
node.expression,
|
|
2583
|
+
node,
|
|
2584
|
+
"left",
|
|
2585
|
+
);
|
|
2586
|
+
if (needsParens) {
|
|
2587
|
+
context.write("(");
|
|
2588
|
+
context.writeNode(node.expression);
|
|
2589
|
+
context.write(")");
|
|
2590
|
+
} else {
|
|
2591
|
+
context.writeNode(node.expression);
|
|
2592
|
+
}
|
|
2246
2593
|
context.writeNode(node.typeArguments);
|
|
2247
2594
|
}
|
|
2248
2595
|
|
|
@@ -2274,3 +2621,14 @@ function writeOptionalTypeAnnotation(
|
|
|
2274
2621
|
context.writeNode(node.typeAnnotation);
|
|
2275
2622
|
}
|
|
2276
2623
|
}
|
|
2624
|
+
|
|
2625
|
+
export function writeComment(comment: Comment, context: PrinterContext): void {
|
|
2626
|
+
if (comment.type === "Line") {
|
|
2627
|
+
context.write("//" + comment.value + "\n");
|
|
2628
|
+
} else {
|
|
2629
|
+
context.write("/*" + comment.value + "*/");
|
|
2630
|
+
if (comment.value.includes("\n")) {
|
|
2631
|
+
context.write("\n");
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
}
|