espolar 0.1.6 → 0.2.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.
@@ -0,0 +1,2276 @@
1
+ import type { PrinterContext, Printers } from "./api.ts";
2
+ import type { AST, Comment } from "./types.ts";
3
+
4
+ const EXPRESSIONS_PRECEDENCE: Record<string, number> = {
5
+ ArrayPattern: 20,
6
+ ObjectPattern: 20,
7
+ ArrayExpression: 20,
8
+ TaggedTemplateExpression: 20,
9
+ ThisExpression: 20,
10
+ Identifier: 20,
11
+ TemplateLiteral: 20,
12
+ Super: 20,
13
+ SequenceExpression: 20,
14
+ MemberExpression: 19,
15
+ MetaProperty: 19,
16
+ CallExpression: 19,
17
+ ChainExpression: 19,
18
+ ImportExpression: 19,
19
+ NewExpression: 19,
20
+ Literal: 18,
21
+ TSSatisfiesExpression: 18,
22
+ TSInstantiationExpression: 18,
23
+ TSNonNullExpression: 18,
24
+ TSTypeAssertion: 18,
25
+ AwaitExpression: 17,
26
+ ClassExpression: 17,
27
+ FunctionExpression: 17,
28
+ ObjectExpression: 17,
29
+ UnaryExpression: 16,
30
+ UpdateExpression: 16,
31
+ TSAsExpression: 15,
32
+ BinaryExpression: 14,
33
+ LogicalExpression: 13,
34
+ ConditionalExpression: 4,
35
+ ArrowFunctionExpression: 3,
36
+ AssignmentExpression: 3,
37
+ YieldExpression: 2,
38
+ RestElement: 1,
39
+ };
40
+
41
+ const OPERATOR_PRECEDENCE: Record<string, number> = {
42
+ "||": 2,
43
+ "&&": 3,
44
+ "??": 4,
45
+ "|": 5,
46
+ "^": 6,
47
+ "&": 7,
48
+ "==": 8,
49
+ "!=": 8,
50
+ "===": 8,
51
+ "!==": 8,
52
+ "<": 9,
53
+ ">": 9,
54
+ "<=": 9,
55
+ ">=": 9,
56
+ in: 9,
57
+ instanceof: 9,
58
+ "<<": 10,
59
+ ">>": 10,
60
+ ">>>": 10,
61
+ "+": 11,
62
+ "-": 11,
63
+ "*": 12,
64
+ "%": 12,
65
+ "/": 12,
66
+ "**": 13,
67
+ };
68
+
69
+ function commentNeedsNewline(comment: Comment): boolean {
70
+ if (comment.type === "Line") return true;
71
+ return comment.value.includes("\n");
72
+ }
73
+
74
+ function needsParens(
75
+ node: AST.Expression | AST.PrivateIdentifier,
76
+ parent:
77
+ | AST.BinaryExpression
78
+ | AST.LogicalExpression
79
+ | AST.AssignmentExpression,
80
+ isRight: boolean,
81
+ ): boolean {
82
+ if (
83
+ node.type === "PrivateIdentifier" ||
84
+ node.type === "Identifier" ||
85
+ node.type === "Super"
86
+ ) {
87
+ return false;
88
+ }
89
+
90
+ // LogicalExpression mixed with ?? requires parens
91
+ if (
92
+ node.type === "LogicalExpression" &&
93
+ parent.type === "LogicalExpression" &&
94
+ (parent.operator === "??") !== (node.operator === "??")
95
+ ) {
96
+ return true;
97
+ }
98
+
99
+ const precedence = EXPRESSIONS_PRECEDENCE[node.type] ?? 20;
100
+ const parentPrecedence = EXPRESSIONS_PRECEDENCE[parent.type] ?? 20;
101
+
102
+ 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
+ return precedence < parentPrecedence;
113
+ }
114
+
115
+ if (precedence !== 13 && precedence !== 14) {
116
+ return false;
117
+ }
118
+
119
+ const nodeOp = (node as AST.BinaryExpression | AST.LogicalExpression)
120
+ .operator;
121
+ if (nodeOp === "**" && parent.operator === "**") {
122
+ return !isRight;
123
+ }
124
+
125
+ if (isRight) {
126
+ return OPERATOR_PRECEDENCE[nodeOp] <= OPERATOR_PRECEDENCE[parent.operator];
127
+ }
128
+ return OPERATOR_PRECEDENCE[nodeOp] < OPERATOR_PRECEDENCE[parent.operator];
129
+ }
130
+
131
+ function arrowConciseBodyNeedsWrap(
132
+ body: AST.BlockStatement | AST.Expression,
133
+ ): boolean {
134
+ if (body.type === "BlockStatement") return false;
135
+ switch (body.type) {
136
+ case "ObjectExpression":
137
+ return true;
138
+ case "AssignmentExpression":
139
+ return body.left.type === "ObjectPattern";
140
+ case "LogicalExpression":
141
+ return body.left.type === "ObjectExpression";
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:
151
+ return false;
152
+ }
153
+ }
154
+
155
+ // Printers
156
+ export const defaultPrinters = {
157
+ Program: printProgram,
158
+ Identifier: printIdentifier,
159
+ PrivateIdentifier: printPrivateIdentifier,
160
+ Literal: printLiteral,
161
+ ExpressionStatement: printExpressionStatement,
162
+ EmptyStatement: printEmptyStatement,
163
+ VariableDeclaration: printVariableDeclaration,
164
+ VariableDeclarator: printVariableDeclarator,
165
+ BlockStatement: printBlockStatement,
166
+ ReturnStatement: printReturnStatement,
167
+ ThrowStatement: printThrowStatement,
168
+ DebuggerStatement: printDebuggerStatement,
169
+ BreakStatement: printBreakStatement,
170
+ ContinueStatement: printContinueStatement,
171
+ LabeledStatement: printLabeledStatement,
172
+ WhileStatement: printWhileStatement,
173
+ DoWhileStatement: printDoWhileStatement,
174
+ IfStatement: printIfStatement,
175
+ ForStatement: printForStatement,
176
+ ForInStatement: printForInStatement,
177
+ ForOfStatement: printForOfStatement,
178
+ SwitchStatement: printSwitchStatement,
179
+ SwitchCase: printSwitchCase,
180
+ TryStatement: printTryStatement,
181
+ WithStatement: printWithStatement,
182
+ FunctionDeclaration: printFunctionDeclaration,
183
+ FunctionExpression: printFunctionExpression,
184
+ ArrowFunctionExpression: printArrowFunctionExpression,
185
+ UnaryExpression: printUnaryExpression,
186
+ UpdateExpression: printUpdateExpression,
187
+ BinaryExpression: printBinaryExpression,
188
+ LogicalExpression: printBinaryExpression,
189
+ AssignmentExpression: printBinaryExpression,
190
+ ConditionalExpression: printConditionalExpression,
191
+ YieldExpression: printYieldExpression,
192
+ AwaitExpression: printAwaitExpression,
193
+ SequenceExpression: printSequenceExpression,
194
+ CallExpression: printCallExpression,
195
+ NewExpression: printNewExpression,
196
+ ChainExpression: printChainExpression,
197
+ MemberExpression: printMemberExpression,
198
+ ObjectExpression: printObjectExpression,
199
+ ObjectPattern: printObjectPattern,
200
+ ArrayExpression: printArrayExpression,
201
+ ArrayPattern: printArrayPattern,
202
+ Property: printProperty,
203
+ SpreadElement: printSpreadElement,
204
+ RestElement: printRestElement,
205
+ AssignmentPattern: printAssignmentPattern,
206
+ TemplateLiteral: printTemplateLiteral,
207
+ TaggedTemplateExpression: printTaggedTemplateExpression,
208
+ ThisExpression: printThisExpression,
209
+ Super: printSuper,
210
+ MetaProperty: printMetaProperty,
211
+ // @ts-expect-error acorn-typescript compat (ParenthesizedExpression is not in TSESTree types)
212
+ ParenthesizedExpression: printParenthesizedExpression,
213
+ ClassDeclaration: printClassDeclaration,
214
+ ClassExpression: printClassExpression,
215
+ ClassBody: printClassBody,
216
+ StaticBlock: printStaticBlock,
217
+ PropertyDefinition: printPropertyDefinition,
218
+ AccessorProperty: printPropertyDefinition,
219
+ MethodDefinition: printMethodDefinition,
220
+ Decorator: printDecorator,
221
+
222
+ ImportDeclaration: printImportDeclaration,
223
+ ImportExpression: printImportExpression,
224
+ ImportSpecifier: printImportSpecifier,
225
+ ImportDefaultSpecifier: printImportDefaultSpecifier,
226
+ ExportNamedDeclaration: printExportNamedDeclaration,
227
+ ExportDefaultDeclaration: printExportDefaultDeclaration,
228
+ ExportAllDeclaration: printExportAllDeclaration,
229
+ ExportSpecifier: printExportSpecifier,
230
+
231
+ // TypeScript
232
+ TSAsExpression: printTSAsExpression,
233
+ TSSatisfiesExpression: printTSSatisfiesExpression,
234
+ TSTypeAssertion: printTSTypeAssertion,
235
+ TSNonNullExpression: printTSNonNullExpression,
236
+ TSTypeAnnotation: printTSTypeAnnotation,
237
+ TSTypeAliasDeclaration: printTSTypeAliasDeclaration,
238
+ TSInterfaceDeclaration: printTSInterfaceDeclaration,
239
+ // TSESTree do not have this entry
240
+ // https://github.com/sveltejs/acorn-typescript/issues/7#issuecomment-3237280163
241
+ TSExpressionWithTypeArguments: printTSExpressionWithTypeArguments,
242
+ TSClassImplements: printTSExpressionWithTypeArguments,
243
+ TSInterfaceHeritage: printTSExpressionWithTypeArguments,
244
+ TSFunctionType: printTSFunctionType,
245
+ TSConstructorType: printTSConstructorType,
246
+ TSMethodSignature: printTSMethodSignature,
247
+ TSCallSignatureDeclaration: printTSCallSignatureDeclaration,
248
+ TSConstructSignatureDeclaration: printTSConstructSignatureDeclaration,
249
+ TSIndexSignature: printTSIndexSignature,
250
+ TSPropertySignature: printTSPropertySignature,
251
+ TSTypeParameterDeclaration: printTypeParameterDeclaration,
252
+ TSTypeParameterInstantiation: printTypeParameterInstantiation,
253
+ TSTypeParameter: printTSTypeParameter,
254
+ TSTypeReference: printTSTypeReference,
255
+ TSQualifiedName: printTSQualifiedName,
256
+ TSUnionType: printJoinedTypes,
257
+ TSIntersectionType: printJoinedTypes,
258
+ TSArrayType: printTSArrayType,
259
+ TSTupleType: printTSTupleType,
260
+ TSNamedTupleMember: printTSNamedTupleMember,
261
+ TSTypeLiteral: printTSTypeLiteral,
262
+ TSTypeOperator: printTSTypeOperator,
263
+ TSTypePredicate: printTSTypePredicate,
264
+ TSTypeQuery: printTSTypeQuery,
265
+ TSMappedType: printTSMappedType,
266
+ TSConditionalType: printTSConditionalType,
267
+ TSInferType: printTSInferType,
268
+ TSIndexedAccessType: printTSIndexedAccessType,
269
+ TSOptionalType: printTSOptionalType,
270
+ TSRestType: printTSRestType,
271
+ TSThisType: printTSThisType,
272
+ TSLiteralType: printTSLiteralType,
273
+ TSTemplateLiteralType: printTSTemplateLiteralType,
274
+ TSImportType: printTSImportType,
275
+ TSImportEqualsDeclaration: printTSImportEqualsDeclaration,
276
+ TSExternalModuleReference: printTSExternalModuleReference,
277
+ TSEnumDeclaration: printTSEnumDeclaration,
278
+ TSEnumMember: printTSEnumMember,
279
+ TSModuleDeclaration: printTSModuleDeclaration,
280
+ TSModuleBlock: printTSModuleBlock,
281
+ TSDeclareFunction: printTSDeclareFunction,
282
+ TSParameterProperty: printTSParameterProperty,
283
+ TSAbstractMethodDefinition: printMethodDefinition,
284
+ TSAbstractPropertyDefinition: printPropertyDefinition,
285
+ TSAbstractAccessorProperty: printPropertyDefinition,
286
+ TSExportAssignment: printTSExportAssignment,
287
+ TSNamespaceExportDeclaration: printTSNamespaceExportDeclaration,
288
+ TSInstantiationExpression: printTSInstantiationExpression,
289
+ TSParenthesizedType: printTSParenthesizedType,
290
+ TSInterfaceBody: printTSInterfaceBody,
291
+ TSStringKeyword: printKeywordType,
292
+ TSNumberKeyword: printKeywordType,
293
+ TSBooleanKeyword: printKeywordType,
294
+ TSVoidKeyword: printKeywordType,
295
+ TSUnknownKeyword: printKeywordType,
296
+ TSAnyKeyword: printKeywordType,
297
+ TSNeverKeyword: printKeywordType,
298
+ TSNullKeyword: printKeywordType,
299
+ TSUndefinedKeyword: printKeywordType,
300
+ TSObjectKeyword: printKeywordType,
301
+ TSSymbolKeyword: printKeywordType,
302
+ TSBigIntKeyword: printKeywordType,
303
+ TSIntrinsicKeyword: printKeywordType,
304
+ } satisfies Printers<unknown>;
305
+
306
+ // JS – Statements
307
+
308
+ function printProgram(program: AST.Program, context: PrinterContext): void {
309
+ context.writeNodeListWithSourceGaps(program.body, "\n");
310
+ }
311
+
312
+ function printExpressionStatement(
313
+ statement: AST.ExpressionStatement,
314
+ context: PrinterContext,
315
+ ): void {
316
+ const expr = statement.expression;
317
+ if (
318
+ expr.type === "ObjectExpression" ||
319
+ expr.type === "FunctionExpression" ||
320
+ (expr.type === "AssignmentExpression" && expr.left.type === "ObjectPattern")
321
+ ) {
322
+ context.write("(");
323
+ context.writeNode(expr);
324
+ context.write(");");
325
+ } else {
326
+ context.writeNode(expr);
327
+ context.write(";");
328
+ }
329
+ }
330
+
331
+ function printEmptyStatement(
332
+ _statement: AST.EmptyStatement,
333
+ context: PrinterContext,
334
+ ): void {
335
+ context.write(";");
336
+ }
337
+
338
+ function printVariableDeclaration(
339
+ declaration: AST.VariableDeclaration,
340
+ context: PrinterContext,
341
+ ): void {
342
+ if (declaration.declare === true) {
343
+ context.write("declare ");
344
+ }
345
+ context.write(String(declaration.kind));
346
+ context.write(" ");
347
+ context.writeNodeList(declaration.declarations, ", ");
348
+ context.write(";");
349
+ }
350
+
351
+ function printVariableDeclarator(
352
+ declarator: AST.VariableDeclarator,
353
+ context: PrinterContext,
354
+ ): void {
355
+ context.writeNode(declarator.id);
356
+ if (declarator.definite === true) {
357
+ context.write("!");
358
+ }
359
+ if (declarator.init) {
360
+ context.write(" = ");
361
+ context.writeNode(declarator.init);
362
+ }
363
+ }
364
+
365
+ function printBlockStatement(
366
+ block: AST.BlockStatement,
367
+ context: PrinterContext,
368
+ ): void {
369
+ const body = block.body;
370
+ context.write("{");
371
+ if (body.length > 0) {
372
+ context.write("\n");
373
+ context.writeNodeListWithSourceGaps(body, "\n");
374
+ context.write("\n");
375
+ }
376
+ context.write("}");
377
+ }
378
+
379
+ function printReturnStatement(
380
+ statement: AST.ReturnStatement,
381
+ context: PrinterContext,
382
+ ): void {
383
+ context.write("return");
384
+ if (statement.argument) {
385
+ context.write(" ");
386
+ const leadingComments = context.options.getLeadingComments?.(
387
+ statement.argument,
388
+ );
389
+ const needsParensASi =
390
+ leadingComments?.some((c) => commentNeedsNewline(c)) ?? false;
391
+ if (needsParensASi) {
392
+ context.write("(");
393
+ }
394
+ context.writeNode(statement.argument);
395
+ if (needsParensASi) {
396
+ context.write(")");
397
+ }
398
+ }
399
+ context.write(";");
400
+ }
401
+
402
+ function printThrowStatement(
403
+ statement: AST.ThrowStatement,
404
+ context: PrinterContext,
405
+ ): void {
406
+ context.write("throw ");
407
+ if (statement.argument) {
408
+ const leadingComments = context.options.getLeadingComments?.(
409
+ statement.argument,
410
+ );
411
+ const needsParensASi =
412
+ leadingComments?.some((c) => commentNeedsNewline(c)) ?? false;
413
+ if (needsParensASi) {
414
+ context.write("(");
415
+ }
416
+ context.writeNode(statement.argument);
417
+ if (needsParensASi) {
418
+ context.write(")");
419
+ }
420
+ }
421
+ context.write(";");
422
+ }
423
+
424
+ function printDebuggerStatement(
425
+ _statement: AST.DebuggerStatement,
426
+ context: PrinterContext,
427
+ ): void {
428
+ context.write("debugger;");
429
+ }
430
+
431
+ function printBreakStatement(
432
+ statement: AST.BreakStatement,
433
+ context: PrinterContext,
434
+ ): void {
435
+ context.write("break");
436
+ if (statement.label) {
437
+ context.write(" ");
438
+ context.writeNode(statement.label);
439
+ }
440
+ context.write(";");
441
+ }
442
+
443
+ function printContinueStatement(
444
+ statement: AST.ContinueStatement,
445
+ context: PrinterContext,
446
+ ): void {
447
+ context.write("continue");
448
+ if (statement.label) {
449
+ context.write(" ");
450
+ context.writeNode(statement.label);
451
+ }
452
+ context.write(";");
453
+ }
454
+
455
+ function printLabeledStatement(
456
+ statement: AST.LabeledStatement,
457
+ context: PrinterContext,
458
+ ): void {
459
+ context.writeNode(statement.label);
460
+ context.write(": ");
461
+ context.writeNode(statement.body);
462
+ }
463
+
464
+ function printWhileStatement(
465
+ statement: AST.WhileStatement,
466
+ context: PrinterContext,
467
+ ): void {
468
+ context.write("while (");
469
+ context.writeNode(statement.test);
470
+ context.write(") ");
471
+ context.writeNode(statement.body);
472
+ }
473
+
474
+ function printDoWhileStatement(
475
+ statement: AST.DoWhileStatement,
476
+ context: PrinterContext,
477
+ ): void {
478
+ context.write("do ");
479
+ context.writeNode(statement.body);
480
+ context.write(" while (");
481
+ context.writeNode(statement.test);
482
+ context.write(");");
483
+ }
484
+
485
+ function printIfStatement(
486
+ statement: AST.IfStatement,
487
+ context: PrinterContext,
488
+ ): void {
489
+ context.write("if (");
490
+ context.writeNode(statement.test);
491
+ context.write(") ");
492
+ context.writeNode(statement.consequent);
493
+ if (statement.alternate) {
494
+ context.write(" else ");
495
+ context.writeNode(statement.alternate);
496
+ }
497
+ }
498
+
499
+ function printForStatement(
500
+ statement: AST.ForStatement,
501
+ context: PrinterContext,
502
+ ): void {
503
+ context.write("for (");
504
+ if (statement.init) {
505
+ if (statement.init.type === "VariableDeclaration") {
506
+ printVariableDeclarationFor(statement.init, context);
507
+ } else {
508
+ context.writeNode(statement.init);
509
+ }
510
+ }
511
+ context.write("; ");
512
+ if (statement.test) {
513
+ context.writeNode(statement.test);
514
+ }
515
+ context.write("; ");
516
+ if (statement.update) {
517
+ context.writeNode(statement.update);
518
+ }
519
+ context.write(") ");
520
+ context.writeNode(statement.body);
521
+ }
522
+
523
+ function printForInStatement(
524
+ statement: AST.ForInStatement,
525
+ context: PrinterContext,
526
+ ): void {
527
+ context.write("for (");
528
+ if (statement.left.type === "VariableDeclaration") {
529
+ printVariableDeclarationFor(statement.left, context);
530
+ } else {
531
+ context.writeNode(statement.left);
532
+ }
533
+ context.write(" in ");
534
+ context.writeNode(statement.right);
535
+ context.write(") ");
536
+ context.writeNode(statement.body);
537
+ }
538
+
539
+ function printForOfStatement(
540
+ statement: AST.ForOfStatement,
541
+ context: PrinterContext,
542
+ ): void {
543
+ context.write("for ");
544
+ if (statement.await === true) {
545
+ context.write("await ");
546
+ }
547
+ context.write("(");
548
+ if (statement.left.type === "VariableDeclaration") {
549
+ printVariableDeclarationFor(statement.left, context);
550
+ } else {
551
+ context.writeNode(statement.left);
552
+ }
553
+ context.write(" of ");
554
+ context.writeNode(statement.right);
555
+ context.write(") ");
556
+ context.writeNode(statement.body);
557
+ }
558
+
559
+ function printVariableDeclarationFor(
560
+ declaration: AST.VariableDeclaration,
561
+ context: PrinterContext,
562
+ ): void {
563
+ context.write(String(declaration.kind));
564
+ context.write(" ");
565
+ context.writeNodeList(declaration.declarations, ", ");
566
+ }
567
+
568
+ function printSwitchStatement(
569
+ statement: AST.SwitchStatement,
570
+ context: PrinterContext,
571
+ ): void {
572
+ context.write("switch (");
573
+ context.writeNode(statement.discriminant);
574
+ context.write(") {");
575
+ for (const case_ of statement.cases) {
576
+ context.writeNode(case_);
577
+ }
578
+ context.write("}");
579
+ }
580
+
581
+ function printSwitchCase(case_: AST.SwitchCase, context: PrinterContext): void {
582
+ if (case_.test) {
583
+ context.write("\ncase ");
584
+ context.writeNode(case_.test);
585
+ context.write(":");
586
+ } else {
587
+ context.write("\ndefault:");
588
+ }
589
+ for (const stmt of case_.consequent) {
590
+ context.write("\n");
591
+ context.writeNode(stmt);
592
+ }
593
+ }
594
+
595
+ function printTryStatement(
596
+ statement: AST.TryStatement,
597
+ context: PrinterContext,
598
+ ): void {
599
+ context.write("try ");
600
+ context.writeNode(statement.block);
601
+ if (statement.handler) {
602
+ context.write(" catch");
603
+ if (statement.handler.param) {
604
+ context.write(" (");
605
+ context.writeNode(statement.handler.param);
606
+ context.write(") ");
607
+ } else {
608
+ context.write(" ");
609
+ }
610
+ context.writeNode(statement.handler.body);
611
+ }
612
+ if (statement.finalizer) {
613
+ context.write(" finally ");
614
+ context.writeNode(statement.finalizer);
615
+ }
616
+ }
617
+
618
+ function printWithStatement(
619
+ statement: AST.WithStatement,
620
+ context: PrinterContext,
621
+ ): void {
622
+ context.write("with (");
623
+ context.writeNode(statement.object);
624
+ context.write(") ");
625
+ context.writeNode(statement.body);
626
+ }
627
+
628
+ // JS – Expressions
629
+
630
+ function printIdentifier(
631
+ identifier: AST.Identifier,
632
+ context: PrinterContext,
633
+ ): void {
634
+ context.write(String(identifier.name));
635
+ writeOptionalTypeAnnotation(identifier, context);
636
+ }
637
+
638
+ function printPrivateIdentifier(
639
+ identifier: AST.PrivateIdentifier,
640
+ context: PrinterContext,
641
+ ): void {
642
+ context.write("#");
643
+ context.write(String(identifier.name));
644
+ }
645
+
646
+ function printLiteral(literal: AST.Literal, context: PrinterContext): void {
647
+ if (typeof literal.raw === "string") {
648
+ context.write(literal.raw);
649
+ return;
650
+ }
651
+ const l = literal as AST.Literal;
652
+ context.write(JSON.stringify(l.value));
653
+ }
654
+
655
+ function printUnaryExpression(
656
+ expr: AST.UnaryExpression,
657
+ context: PrinterContext,
658
+ ): void {
659
+ context.write(expr.operator);
660
+ if (expr.operator.length > 1) {
661
+ context.write(" ");
662
+ }
663
+ const argPrec = EXPRESSIONS_PRECEDENCE[expr.argument.type];
664
+ if (argPrec != null && argPrec < EXPRESSIONS_PRECEDENCE.UnaryExpression) {
665
+ context.write("(");
666
+ context.writeNode(expr.argument);
667
+ context.write(")");
668
+ } else {
669
+ context.writeNode(expr.argument);
670
+ }
671
+ }
672
+
673
+ function printUpdateExpression(
674
+ expr: AST.UpdateExpression,
675
+ context: PrinterContext,
676
+ ): void {
677
+ if (expr.prefix === true) {
678
+ context.write(expr.operator);
679
+ context.writeNode(expr.argument);
680
+ } else {
681
+ const trailingComments = context.options.getTrailingComments?.(
682
+ expr.argument,
683
+ );
684
+ const needsParensASi =
685
+ trailingComments?.some((c) => commentNeedsNewline(c)) ?? false;
686
+ if (needsParensASi) {
687
+ context.write("(");
688
+ }
689
+ context.writeNode(expr.argument);
690
+ if (needsParensASi) {
691
+ context.write(")");
692
+ }
693
+ context.write(expr.operator);
694
+ }
695
+ }
696
+
697
+ function printBinaryExpression(
698
+ expression:
699
+ | AST.AssignmentExpression
700
+ | AST.LogicalExpression
701
+ | AST.BinaryExpression,
702
+ context: PrinterContext,
703
+ ): void {
704
+ const left = expression.left;
705
+ const right = expression.right;
706
+
707
+ if (needsParens(left, expression, false)) {
708
+ context.write("(");
709
+ context.writeNode(left);
710
+ context.write(")");
711
+ } else {
712
+ context.writeNode(left);
713
+ }
714
+
715
+ context.write(" ");
716
+ context.write(String(expression.operator));
717
+ context.write(" ");
718
+
719
+ if (needsParens(right, expression, true)) {
720
+ context.write("(");
721
+ context.writeNode(right);
722
+ context.write(")");
723
+ } else {
724
+ context.writeNode(right);
725
+ }
726
+ }
727
+
728
+ function printConditionalExpression(
729
+ expr: AST.ConditionalExpression,
730
+ context: PrinterContext,
731
+ ): void {
732
+ const testPrec = EXPRESSIONS_PRECEDENCE[expr.test.type] ?? 20;
733
+ if (testPrec <= EXPRESSIONS_PRECEDENCE.ConditionalExpression) {
734
+ context.write("(");
735
+ context.writeNode(expr.test);
736
+ context.write(")");
737
+ } else {
738
+ context.writeNode(expr.test);
739
+ }
740
+ context.write(" ? ");
741
+ context.writeNode(expr.consequent);
742
+ context.write(" : ");
743
+ context.writeNode(expr.alternate);
744
+ }
745
+
746
+ function printYieldExpression(
747
+ expr: AST.YieldExpression,
748
+ context: PrinterContext,
749
+ ): void {
750
+ context.write(expr.delegate === true ? "yield*" : "yield");
751
+ if (expr.argument) {
752
+ context.write(" ");
753
+ const leadingComments = context.options.getLeadingComments?.(expr.argument);
754
+ const needsParensASi =
755
+ leadingComments?.some((c) => commentNeedsNewline(c)) ?? false;
756
+ if (needsParensASi) {
757
+ context.write("(");
758
+ }
759
+ context.writeNode(expr.argument);
760
+ if (needsParensASi) {
761
+ context.write(")");
762
+ }
763
+ }
764
+ }
765
+
766
+ function printAwaitExpression(
767
+ expr: AST.AwaitExpression,
768
+ context: PrinterContext,
769
+ ): void {
770
+ context.write("await");
771
+ if (expr.argument) {
772
+ const argPrec = EXPRESSIONS_PRECEDENCE[expr.argument.type];
773
+ if (argPrec != null && argPrec < EXPRESSIONS_PRECEDENCE.AwaitExpression) {
774
+ context.write(" (");
775
+ context.writeNode(expr.argument);
776
+ context.write(")");
777
+ } else {
778
+ context.write(" ");
779
+ context.writeNode(expr.argument);
780
+ }
781
+ }
782
+ }
783
+
784
+ function printSequenceExpression(
785
+ expr: AST.SequenceExpression,
786
+ context: PrinterContext,
787
+ ): void {
788
+ context.write("(");
789
+ context.writeNodeList(expr.expressions, ", ");
790
+ context.write(")");
791
+ }
792
+
793
+ function printCallExpression(
794
+ expression: AST.CallExpression,
795
+ context: PrinterContext,
796
+ ): void {
797
+ const calleePrec = EXPRESSIONS_PRECEDENCE[expression.callee.type] ?? 20;
798
+ if (calleePrec < EXPRESSIONS_PRECEDENCE.CallExpression) {
799
+ context.write("(");
800
+ context.writeNode(expression.callee);
801
+ context.write(")");
802
+ } else {
803
+ context.writeNode(expression.callee);
804
+ }
805
+ if (expression.typeArguments) {
806
+ context.writeNode(expression.typeArguments);
807
+ }
808
+ if (expression.optional === true) {
809
+ context.write("?.");
810
+ }
811
+ const parenRange =
812
+ context.options.experimentalGetLeftParenSourceRange?.(expression);
813
+ if (parenRange) {
814
+ context.writeMapped("(", parenRange.start, parenRange.end);
815
+ } else {
816
+ context.write("(");
817
+ }
818
+ context.writeNodeList(expression.arguments, ", ");
819
+ context.write(")");
820
+ }
821
+
822
+ function printNewExpression(
823
+ expression: AST.NewExpression,
824
+ context: PrinterContext,
825
+ ): void {
826
+ context.write("new ");
827
+ const calleePrec = EXPRESSIONS_PRECEDENCE[expression.callee.type] ?? 20;
828
+ if (
829
+ calleePrec < EXPRESSIONS_PRECEDENCE.NewExpression ||
830
+ hasCallExpression(expression.callee)
831
+ ) {
832
+ context.write("(");
833
+ context.writeNode(expression.callee);
834
+ context.write(")");
835
+ } else {
836
+ context.writeNode(expression.callee);
837
+ }
838
+ if (expression.typeArguments) {
839
+ context.writeNode(expression.typeArguments);
840
+ }
841
+ const parenRange =
842
+ context.options.experimentalGetLeftParenSourceRange?.(expression);
843
+ if (parenRange) {
844
+ context.writeMapped("(", parenRange.start, parenRange.end);
845
+ } else {
846
+ context.write("(");
847
+ }
848
+ context.writeNodeList(expression.arguments, ", ");
849
+ context.write(")");
850
+ }
851
+
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
+ function printChainExpression(
866
+ expression: AST.ChainExpression,
867
+ context: PrinterContext,
868
+ ): void {
869
+ context.writeNode(expression.expression);
870
+ }
871
+
872
+ function printMemberExpression(
873
+ expression: AST.MemberExpression,
874
+ context: PrinterContext,
875
+ ): void {
876
+ const objPrec = EXPRESSIONS_PRECEDENCE[expression.object.type] ?? 20;
877
+ if (objPrec < EXPRESSIONS_PRECEDENCE.MemberExpression) {
878
+ context.write("(");
879
+ context.writeNode(expression.object);
880
+ context.write(")");
881
+ } else {
882
+ context.writeNode(expression.object);
883
+ }
884
+ if (expression.computed === true) {
885
+ context.write(expression.optional === true ? "?.[" : "[");
886
+ context.writeNode(expression.property);
887
+ context.write("]");
888
+ } else {
889
+ context.write(expression.optional === true ? "?." : ".");
890
+ context.writeNode(expression.property);
891
+ }
892
+ }
893
+
894
+ function printObjectExpression(
895
+ object: AST.ObjectExpression,
896
+ context: PrinterContext,
897
+ ): void {
898
+ context.write("{ ");
899
+ context.writeNodeList(object.properties, ", ");
900
+ context.write(" }");
901
+ }
902
+
903
+ function printObjectPattern(
904
+ pattern: AST.ObjectPattern,
905
+ context: PrinterContext,
906
+ ): void {
907
+ context.write("{ ");
908
+ context.writeNodeList(pattern.properties, ", ");
909
+ context.write(" }");
910
+ writeOptionalTypeAnnotation(pattern, context);
911
+ }
912
+
913
+ function printArrayExpression(
914
+ array: AST.ArrayExpression,
915
+ context: PrinterContext,
916
+ ): void {
917
+ context.write("[");
918
+ context.writeNodeList(array.elements, ", ");
919
+ context.write("]");
920
+ }
921
+
922
+ function printArrayPattern(
923
+ pattern: AST.ArrayPattern,
924
+ context: PrinterContext,
925
+ ): void {
926
+ context.write("[");
927
+ context.writeNodeList(pattern.elements, ", ");
928
+ context.write("]");
929
+ writeOptionalTypeAnnotation(pattern, context);
930
+ }
931
+
932
+ function printProperty(
933
+ property: AST.Property | AST.PropertyDefinition,
934
+ context: PrinterContext,
935
+ ): void {
936
+ if (property.type === "Property") {
937
+ const value = property.value;
938
+ const valNode = value.type === "AssignmentPattern" ? value.left : value;
939
+
940
+ const shorthand =
941
+ !property.computed &&
942
+ property.kind === "init" &&
943
+ property.key.type === "Identifier" &&
944
+ valNode.type === "Identifier" &&
945
+ property.key.name === valNode.name;
946
+
947
+ if (shorthand) {
948
+ context.writeNode(value);
949
+ return;
950
+ }
951
+
952
+ // shorthand method
953
+ if (value.type === "FunctionExpression") {
954
+ if (property.kind !== "init") {
955
+ context.write(property.kind + " ");
956
+ }
957
+ if (value.async === true) {
958
+ context.write("async ");
959
+ }
960
+ if (value.generator === true) {
961
+ context.write("*");
962
+ }
963
+ if (property.computed === true) {
964
+ context.write("[");
965
+ context.writeNode(property.key);
966
+ context.write("]");
967
+ } else {
968
+ context.writeNode(property.key);
969
+ }
970
+ context.write("(");
971
+ context.writeNodeList(value.params, ", ");
972
+ context.write(")");
973
+ writeReturnType(value, context);
974
+ context.write(" ");
975
+ context.writeNode(value.body!);
976
+ return;
977
+ }
978
+
979
+ if (property.computed === true) {
980
+ context.write("[");
981
+ context.writeNode(property.key);
982
+ context.write("]: ");
983
+ } else {
984
+ if (property.kind === "get" || property.kind === "set") {
985
+ context.write(property.kind + " ");
986
+ }
987
+ context.writeNode(property.key);
988
+ context.write(": ");
989
+ }
990
+ context.writeNode(property.value);
991
+ }
992
+ }
993
+
994
+ function printSpreadElement(
995
+ spread: AST.SpreadElement,
996
+ context: PrinterContext,
997
+ ): void {
998
+ context.write("...");
999
+ context.writeNode(spread.argument);
1000
+ }
1001
+
1002
+ function printRestElement(
1003
+ rest: AST.RestElement,
1004
+ context: PrinterContext,
1005
+ ): void {
1006
+ context.write("...");
1007
+ context.writeNode(rest.argument);
1008
+ writeOptionalTypeAnnotation(rest, context);
1009
+ }
1010
+
1011
+ function printAssignmentPattern(
1012
+ pattern: AST.AssignmentPattern,
1013
+ context: PrinterContext,
1014
+ ): void {
1015
+ context.writeNode(pattern.left);
1016
+ context.write(" = ");
1017
+ context.writeNode(pattern.right);
1018
+ }
1019
+
1020
+ function printTemplateLiteral(
1021
+ node: AST.TemplateLiteral,
1022
+ context: PrinterContext,
1023
+ ): void {
1024
+ context.write("`");
1025
+ const { quasis, expressions } = node;
1026
+ for (let i = 0; i < expressions.length; i++) {
1027
+ context.write(quasis[i].value.raw);
1028
+ context.write("${");
1029
+ context.writeNode(expressions[i]);
1030
+ context.write("}");
1031
+ }
1032
+ context.write(quasis[quasis.length - 1].value.raw);
1033
+ context.write("`");
1034
+ }
1035
+
1036
+ function printTaggedTemplateExpression(
1037
+ node: AST.TaggedTemplateExpression,
1038
+ context: PrinterContext,
1039
+ ): void {
1040
+ context.writeNode(node.tag);
1041
+ context.writeNode(node.quasi);
1042
+ }
1043
+
1044
+ function printThisExpression(
1045
+ _node: AST.ThisExpression,
1046
+ context: PrinterContext,
1047
+ ): void {
1048
+ context.write("this");
1049
+ }
1050
+
1051
+ function printSuper(_node: AST.Super, context: PrinterContext): void {
1052
+ context.write("super");
1053
+ }
1054
+
1055
+ function printMetaProperty(
1056
+ node: AST.MetaProperty,
1057
+ context: PrinterContext,
1058
+ ): void {
1059
+ context.writeNode(node.meta);
1060
+ context.write(".");
1061
+ context.writeNode(node.property);
1062
+ }
1063
+
1064
+ function printParenthesizedExpression(
1065
+ node: { expression: AST.Node },
1066
+ context: PrinterContext,
1067
+ ): void {
1068
+ context.write("(");
1069
+ context.writeNode(node.expression);
1070
+ context.write(")");
1071
+ }
1072
+
1073
+ // JS – Functions / Classes
1074
+
1075
+ function printFunctionDeclaration(
1076
+ node: AST.FunctionDeclaration,
1077
+ context: PrinterContext,
1078
+ ): void {
1079
+ printFunction(node, context);
1080
+ }
1081
+
1082
+ function printFunctionExpression(
1083
+ node: AST.FunctionExpression,
1084
+ context: PrinterContext,
1085
+ ): void {
1086
+ printFunction(node, context);
1087
+ }
1088
+
1089
+ function printFunction(
1090
+ fn: AST.FunctionDeclaration | AST.FunctionExpression,
1091
+ context: PrinterContext,
1092
+ ): void {
1093
+ if (fn.async === true) {
1094
+ context.write("async ");
1095
+ }
1096
+ context.write("function");
1097
+ if (fn.generator === true) {
1098
+ context.write("*");
1099
+ }
1100
+ if (fn.id) {
1101
+ context.write(" ");
1102
+ context.writeNode(fn.id);
1103
+ }
1104
+ if (fn.typeParameters) {
1105
+ context.writeNode(fn.typeParameters);
1106
+ }
1107
+ context.write("(");
1108
+ context.writeNodeList(fn.params, ", ");
1109
+ context.write(")");
1110
+ writeReturnType(fn, context);
1111
+ if (fn.body) {
1112
+ context.write(" ");
1113
+ context.writeNode(fn.body);
1114
+ }
1115
+ }
1116
+
1117
+ function printArrowFunctionExpression(
1118
+ fn: AST.ArrowFunctionExpression,
1119
+ context: PrinterContext,
1120
+ ): void {
1121
+ if (fn.async === true) {
1122
+ context.write("async ");
1123
+ }
1124
+ if (fn.typeParameters) {
1125
+ context.writeNode(fn.typeParameters);
1126
+ }
1127
+ context.write("(");
1128
+ context.writeNodeList(fn.params, ", ");
1129
+ context.write(")");
1130
+ writeReturnType(fn, context);
1131
+ context.write(" => ");
1132
+ const body = fn.body;
1133
+ if (arrowConciseBodyNeedsWrap(body)) {
1134
+ context.write("(");
1135
+ context.writeNode(body);
1136
+ context.write(")");
1137
+ } else {
1138
+ context.writeNode(body);
1139
+ }
1140
+ }
1141
+
1142
+ function printClassDeclaration(
1143
+ node: AST.ClassDeclaration,
1144
+ context: PrinterContext,
1145
+ ): void {
1146
+ printClass(node, context);
1147
+ }
1148
+
1149
+ function printClassExpression(
1150
+ node: AST.ClassExpression,
1151
+ context: PrinterContext,
1152
+ ): void {
1153
+ printClass(node, context);
1154
+ }
1155
+
1156
+ function printClass(
1157
+ node: AST.ClassDeclaration | AST.ClassExpression,
1158
+ context: PrinterContext,
1159
+ ): void {
1160
+ if (node.decorators) {
1161
+ for (const d of node.decorators) {
1162
+ context.writeNode(d);
1163
+ }
1164
+ }
1165
+ if (node.declare === true) {
1166
+ context.write("declare ");
1167
+ }
1168
+ if (node.abstract === true) {
1169
+ context.write("abstract ");
1170
+ }
1171
+ context.write("class ");
1172
+ if (node.id) {
1173
+ context.writeNode(node.id);
1174
+ context.write(" ");
1175
+ }
1176
+ if (node.superClass) {
1177
+ context.write("extends ");
1178
+ context.writeNode(node.superClass);
1179
+ if (node.superTypeArguments) {
1180
+ context.writeNode(node.superTypeArguments);
1181
+ } else if (node.superTypeParameters) {
1182
+ context.writeNode(node.superTypeParameters);
1183
+ }
1184
+ }
1185
+ if (node.implements && node.implements.length > 0) {
1186
+ context.write(" implements ");
1187
+ context.writeNodeList(node.implements, ", ");
1188
+ }
1189
+ if (node.superClass || (node.implements && node.implements.length > 0)) {
1190
+ context.write(" ");
1191
+ }
1192
+ context.writeNode(node.body);
1193
+ }
1194
+
1195
+ function printClassBody(node: AST.ClassBody, context: PrinterContext): void {
1196
+ context.write("{");
1197
+ const body = node.body;
1198
+ if (body.length > 0) {
1199
+ context.write("\n");
1200
+ context.writeNodeListWithSourceGaps(body, "\n");
1201
+ context.write("\n");
1202
+ }
1203
+ context.write("}");
1204
+ }
1205
+
1206
+ function printStaticBlock(
1207
+ node: AST.StaticBlock,
1208
+ context: PrinterContext,
1209
+ ): void {
1210
+ context.write("static {");
1211
+ const body = node.body;
1212
+ if (body.length > 0) {
1213
+ context.write("\n");
1214
+ context.writeNodeListWithSourceGaps(body, "\n");
1215
+ context.write("\n");
1216
+ }
1217
+ context.write("}");
1218
+ }
1219
+
1220
+ function printDecorator(node: AST.Decorator, context: PrinterContext): void {
1221
+ context.write("@");
1222
+ context.writeNode(node.expression);
1223
+ context.write("\n");
1224
+ }
1225
+
1226
+ function printPropertyDefinition(
1227
+ node:
1228
+ | AST.PropertyDefinition
1229
+ | AST.AccessorProperty
1230
+ | AST.TSAbstractAccessorProperty
1231
+ | AST.TSAbstractPropertyDefinition,
1232
+ context: PrinterContext,
1233
+ ): void {
1234
+ if (node.decorators) {
1235
+ for (const d of node.decorators) {
1236
+ context.writeNode(d);
1237
+ }
1238
+ }
1239
+ if (
1240
+ node.type === "TSAbstractPropertyDefinition" ||
1241
+ ("abstract" in node && node.abstract === true)
1242
+ ) {
1243
+ context.write("abstract ");
1244
+ }
1245
+ if (node.accessibility) {
1246
+ context.write(node.accessibility + " ");
1247
+ }
1248
+ if (node.static === true) {
1249
+ context.write("static ");
1250
+ }
1251
+ if (node.override === true) {
1252
+ context.write("override ");
1253
+ }
1254
+ if (node.readonly === true) {
1255
+ context.write("readonly ");
1256
+ }
1257
+ if (
1258
+ node.type === "AccessorProperty" ||
1259
+ node.type === "TSAbstractAccessorProperty" ||
1260
+ ("accessor" in node && node.accessor === true)
1261
+ ) {
1262
+ context.write("accessor ");
1263
+ }
1264
+ if (node.computed === true) {
1265
+ context.write("[");
1266
+ context.writeNode(node.key);
1267
+ context.write("]");
1268
+ } else {
1269
+ context.writeNode(node.key);
1270
+ }
1271
+ if (node.typeAnnotation) {
1272
+ if ("accessor" in node && node.accessor === true) {
1273
+ context.writeNode(node.typeAnnotation);
1274
+ } else {
1275
+ context.write(": ");
1276
+ context.writeNode(node.typeAnnotation.typeAnnotation);
1277
+ }
1278
+ }
1279
+ if (node.value) {
1280
+ context.write(" = ");
1281
+ context.writeNode(node.value);
1282
+ }
1283
+ context.write(";");
1284
+ }
1285
+
1286
+ function printMethodDefinition(
1287
+ node: AST.MethodDefinition | AST.TSAbstractMethodDefinition,
1288
+ context: PrinterContext,
1289
+ ): void {
1290
+ const def = node;
1291
+ if (def.decorators) {
1292
+ for (const d of def.decorators) {
1293
+ context.writeNode(d);
1294
+ }
1295
+ }
1296
+ if (def.accessibility) {
1297
+ context.write(def.accessibility + " ");
1298
+ }
1299
+ if (def.static === true) {
1300
+ context.write("static ");
1301
+ }
1302
+ if (def.override === true) {
1303
+ context.write("override ");
1304
+ }
1305
+ if (
1306
+ node.type === "TSAbstractMethodDefinition" ||
1307
+ ("abstract" in def && def.abstract === true)
1308
+ ) {
1309
+ context.write("abstract ");
1310
+ }
1311
+ if (def.kind === "get" || def.kind === "set") {
1312
+ context.write(def.kind + " ");
1313
+ }
1314
+ if (def.value.async === true) {
1315
+ context.write("async ");
1316
+ }
1317
+ if (def.value.generator === true) {
1318
+ context.write("*");
1319
+ }
1320
+ if (def.computed === true) {
1321
+ context.write("[");
1322
+ context.writeNode(def.key);
1323
+ context.write("]");
1324
+ } else {
1325
+ context.writeNode(def.key);
1326
+ }
1327
+ context.write("(");
1328
+ context.writeNodeList(def.value.params, ", ");
1329
+ context.write(")");
1330
+ writeReturnType(def.value, context);
1331
+ if (def.value.body) {
1332
+ context.write(" ");
1333
+ context.writeNode(def.value.body);
1334
+ } else {
1335
+ context.write(";");
1336
+ }
1337
+ }
1338
+
1339
+ // JS – Imports / Exports
1340
+
1341
+ function printImportDeclaration(
1342
+ node: AST.ImportDeclaration,
1343
+ context: PrinterContext,
1344
+ ): void {
1345
+ context.write("import ");
1346
+ if (node.importKind === "type") {
1347
+ context.write("type ");
1348
+ }
1349
+
1350
+ const specifiers = node.specifiers;
1351
+ if (specifiers.length === 0) {
1352
+ context.writeNode(node.source);
1353
+ context.write(";");
1354
+ return;
1355
+ }
1356
+
1357
+ let wroteDefault = false;
1358
+
1359
+ for (const s of specifiers) {
1360
+ if (s.type === "ImportDefaultSpecifier") {
1361
+ context.writeNode(s);
1362
+ wroteDefault = true;
1363
+ }
1364
+ }
1365
+
1366
+ let namespaceSpec: AST.ImportNamespaceSpecifier | undefined;
1367
+ const namedSpecs: AST.ImportSpecifier[] = [];
1368
+
1369
+ for (const s of specifiers) {
1370
+ if (s.type === "ImportNamespaceSpecifier") {
1371
+ namespaceSpec = s;
1372
+ } else if (s.type === "ImportSpecifier") {
1373
+ namedSpecs.push(s);
1374
+ }
1375
+ }
1376
+
1377
+ if (namespaceSpec) {
1378
+ if (wroteDefault) context.write(", ");
1379
+ context.write("* as ");
1380
+ context.writeNode(namespaceSpec.local);
1381
+ }
1382
+
1383
+ if (namedSpecs.length > 0) {
1384
+ if (wroteDefault || namespaceSpec) context.write(", ");
1385
+ context.write("{ ");
1386
+ context.writeNodeList(namedSpecs, ", ");
1387
+ context.write(" }");
1388
+ }
1389
+
1390
+ context.write(" from ");
1391
+ context.writeNode(node.source);
1392
+
1393
+ if (node.attributes && node.attributes.length > 0) {
1394
+ context.write(" with { ");
1395
+ context.writeNodeList(node.attributes, ", ");
1396
+ context.write(" }");
1397
+ }
1398
+ context.write(";");
1399
+ }
1400
+
1401
+ function printImportExpression(
1402
+ node: AST.ImportExpression,
1403
+ context: PrinterContext,
1404
+ ): void {
1405
+ context.write("import(");
1406
+ context.writeNode(node.source);
1407
+ if (node.options) {
1408
+ context.write(", ");
1409
+ context.writeNode(node.options);
1410
+ }
1411
+ context.write(")");
1412
+ }
1413
+
1414
+ function printImportDefaultSpecifier(
1415
+ node: AST.ImportDefaultSpecifier,
1416
+ context: PrinterContext,
1417
+ ): void {
1418
+ context.writeNode(node.local);
1419
+ }
1420
+
1421
+ function printImportSpecifier(
1422
+ node: AST.ImportSpecifier,
1423
+ context: PrinterContext,
1424
+ ): void {
1425
+ if (node.importKind === "type") {
1426
+ context.write("type ");
1427
+ }
1428
+ if (
1429
+ node.local.type === "Identifier" &&
1430
+ node.imported.type === "Identifier" &&
1431
+ node.local.name !== node.imported.name
1432
+ ) {
1433
+ context.writeNode(node.imported);
1434
+ context.write(" as ");
1435
+ }
1436
+ context.writeNode(node.local);
1437
+ }
1438
+
1439
+ function printExportNamedDeclaration(
1440
+ node: AST.ExportNamedDeclaration,
1441
+ context: PrinterContext,
1442
+ ): void {
1443
+ if (node.declaration) {
1444
+ let decl = node.declaration;
1445
+ if ("decorators" in decl && decl.decorators && decl.decorators.length > 0) {
1446
+ const { decorators, ...rest } = decl;
1447
+ for (const d of decorators) {
1448
+ context.writeNode(d);
1449
+ }
1450
+ decl = rest as typeof decl;
1451
+ }
1452
+ context.write("export ");
1453
+ if (node.exportKind === "type") {
1454
+ context.write("type ");
1455
+ }
1456
+ context.writeNode(decl);
1457
+ if (
1458
+ decl.type !== "FunctionDeclaration" &&
1459
+ decl.type !== "ClassDeclaration" &&
1460
+ decl.type !== "VariableDeclaration" &&
1461
+ decl.type !== "TSModuleDeclaration" &&
1462
+ decl.type !== "TSEnumDeclaration" &&
1463
+ decl.type !== "TSTypeAliasDeclaration" &&
1464
+ decl.type !== "TSInterfaceDeclaration" &&
1465
+ decl.type !== "TSDeclareFunction"
1466
+ ) {
1467
+ context.write(";");
1468
+ }
1469
+ return;
1470
+ }
1471
+
1472
+ context.write("export ");
1473
+ if (node.exportKind === "type") {
1474
+ context.write("type ");
1475
+ }
1476
+ context.write("{ ");
1477
+ context.writeNodeList(node.specifiers, ", ");
1478
+ context.write(" }");
1479
+
1480
+ if (node.source) {
1481
+ context.write(" from ");
1482
+ context.writeNode(node.source);
1483
+ }
1484
+ context.write(";");
1485
+ }
1486
+
1487
+ function printExportDefaultDeclaration(
1488
+ node: AST.ExportDefaultDeclaration,
1489
+ context: PrinterContext,
1490
+ ): void {
1491
+ let decl = node.declaration;
1492
+ if ("decorators" in decl && decl.decorators && decl.decorators.length > 0) {
1493
+ const { decorators, ...rest } = decl;
1494
+ for (const d of decorators) {
1495
+ context.writeNode(d);
1496
+ }
1497
+ decl = rest as typeof decl;
1498
+ }
1499
+ context.write("export default ");
1500
+ context.writeNode(decl);
1501
+ if (
1502
+ decl.type !== "FunctionDeclaration" &&
1503
+ decl.type !== "ClassDeclaration" &&
1504
+ decl.type !== "ClassExpression"
1505
+ ) {
1506
+ context.write(";");
1507
+ }
1508
+ }
1509
+
1510
+ function printExportAllDeclaration(
1511
+ node: AST.ExportAllDeclaration,
1512
+ context: PrinterContext,
1513
+ ): void {
1514
+ context.write(node.exportKind === "type" ? "export type * " : "export * ");
1515
+ if (node.exported) {
1516
+ context.write("as ");
1517
+ context.writeNode(node.exported);
1518
+ context.write(" ");
1519
+ }
1520
+ context.write("from ");
1521
+ context.writeNode(node.source);
1522
+ context.write(";");
1523
+ }
1524
+
1525
+ function printExportSpecifier(
1526
+ node: AST.ExportSpecifier,
1527
+ context: PrinterContext,
1528
+ ): void {
1529
+ if (node.exportKind === "type") {
1530
+ context.write("type ");
1531
+ }
1532
+ context.writeNode(node.local);
1533
+ if (
1534
+ node.local.type === "Identifier" &&
1535
+ node.exported.type === "Identifier" &&
1536
+ node.local.name !== node.exported.name
1537
+ ) {
1538
+ context.write(" as ");
1539
+ context.writeNode(node.exported);
1540
+ }
1541
+ }
1542
+
1543
+ // TS – Expressions
1544
+
1545
+ function printTSAsExpression(
1546
+ expression: AST.TSAsExpression,
1547
+ context: PrinterContext,
1548
+ ): void {
1549
+ const exprPrec = EXPRESSIONS_PRECEDENCE[expression.expression.type] ?? 20;
1550
+ if (exprPrec < EXPRESSIONS_PRECEDENCE.TSAsExpression) {
1551
+ context.write("(");
1552
+ context.writeNode(expression.expression);
1553
+ context.write(")");
1554
+ } else {
1555
+ context.writeNode(expression.expression);
1556
+ }
1557
+ context.write(" as ");
1558
+ context.writeNode(expression.typeAnnotation);
1559
+ }
1560
+
1561
+ function printTSSatisfiesExpression(
1562
+ expression: AST.TSSatisfiesExpression,
1563
+ context: PrinterContext,
1564
+ ): void {
1565
+ const exprPrec = EXPRESSIONS_PRECEDENCE[expression.expression.type] ?? 20;
1566
+ if (exprPrec < EXPRESSIONS_PRECEDENCE.TSSatisfiesExpression) {
1567
+ context.write("(");
1568
+ context.writeNode(expression.expression);
1569
+ context.write(")");
1570
+ } else {
1571
+ context.writeNode(expression.expression);
1572
+ }
1573
+ context.write(" satisfies ");
1574
+ context.writeNode(expression.typeAnnotation);
1575
+ }
1576
+
1577
+ function printTSTypeAssertion(
1578
+ expression: AST.TSTypeAssertion,
1579
+ context: PrinterContext,
1580
+ ): void {
1581
+ context.write("<");
1582
+ context.writeNode(expression.typeAnnotation);
1583
+ context.write(">");
1584
+ const exprPrec = EXPRESSIONS_PRECEDENCE[expression.expression.type] ?? 20;
1585
+ if (exprPrec < EXPRESSIONS_PRECEDENCE.TSTypeAssertion) {
1586
+ context.write("(");
1587
+ context.writeNode(expression.expression);
1588
+ context.write(")");
1589
+ } else {
1590
+ context.writeNode(expression.expression);
1591
+ }
1592
+ }
1593
+
1594
+ function printTSNonNullExpression(
1595
+ expression: AST.TSNonNullExpression,
1596
+ context: PrinterContext,
1597
+ ): void {
1598
+ context.writeNode(expression.expression);
1599
+ context.write("!");
1600
+ }
1601
+
1602
+ function printTSTypeAnnotation(
1603
+ annotation: AST.TSTypeAnnotation,
1604
+ context: PrinterContext,
1605
+ ): void {
1606
+ context.write(": ");
1607
+ context.writeNode(annotation.typeAnnotation);
1608
+ }
1609
+
1610
+ function printTSTypeAliasDeclaration(
1611
+ alias: AST.TSTypeAliasDeclaration,
1612
+ context: PrinterContext,
1613
+ ): void {
1614
+ if (alias.declare === true) {
1615
+ context.write("declare ");
1616
+ }
1617
+ context.write("type ");
1618
+ context.writeNode(alias.id);
1619
+ if (alias.typeParameters) {
1620
+ context.writeNode(alias.typeParameters);
1621
+ }
1622
+ context.write(" = ");
1623
+ context.writeNode(alias.typeAnnotation);
1624
+ context.write(";");
1625
+ }
1626
+
1627
+ function printTSInterfaceDeclaration(
1628
+ node: AST.TSInterfaceDeclaration,
1629
+ context: PrinterContext,
1630
+ ): void {
1631
+ const declaration = node;
1632
+ if (declaration.declare === true) {
1633
+ context.write("declare ");
1634
+ }
1635
+ context.write("interface ");
1636
+ context.writeNode(declaration.id);
1637
+ if (declaration.typeParameters) {
1638
+ context.writeNode(declaration.typeParameters);
1639
+ }
1640
+ const heritage = declaration.extends ?? [];
1641
+ if (heritage.length > 0) {
1642
+ context.write(" extends ");
1643
+ context.writeNodeList(heritage, ", ");
1644
+ }
1645
+ context.write(" ");
1646
+ context.writeNode(declaration.body);
1647
+ }
1648
+
1649
+ function printTSExpressionWithTypeArguments(
1650
+ node: {
1651
+ expression: AST.Node;
1652
+ typeArguments?: AST.Node;
1653
+ typeParameters?: AST.Node;
1654
+ },
1655
+ context: PrinterContext,
1656
+ ): void {
1657
+ context.writeNode(node.expression);
1658
+ if (node.typeArguments) {
1659
+ context.writeNode(node.typeArguments);
1660
+ }
1661
+ if (node.typeParameters) {
1662
+ context.writeNode(node.typeParameters);
1663
+ }
1664
+ }
1665
+
1666
+ function printTSInterfaceBody(
1667
+ body: AST.TSInterfaceBody,
1668
+ context: PrinterContext,
1669
+ ): void {
1670
+ context.write("{");
1671
+ const members = body.body;
1672
+ if (members.length > 0) {
1673
+ context.write(" ");
1674
+ context.writeNodeList(members, " ");
1675
+ context.write(" ");
1676
+ }
1677
+ context.write("}");
1678
+ }
1679
+
1680
+ function printTSPropertySignature(
1681
+ signature: AST.TSPropertySignature,
1682
+ context: PrinterContext,
1683
+ ): void {
1684
+ if (signature.readonly === true) {
1685
+ context.write("readonly ");
1686
+ }
1687
+ if (signature.computed === true) {
1688
+ context.write("[");
1689
+ context.writeNode(signature.key);
1690
+ context.write("]");
1691
+ } else {
1692
+ context.writeNode(signature.key);
1693
+ }
1694
+ if (signature.optional === true) {
1695
+ context.write("?");
1696
+ }
1697
+ if (signature.typeAnnotation) {
1698
+ context.writeNode(signature.typeAnnotation);
1699
+ }
1700
+ context.write(";");
1701
+ }
1702
+
1703
+ function printTypeParameterDeclaration(
1704
+ declaration: AST.TSTypeParameterDeclaration,
1705
+ context: PrinterContext,
1706
+ ): void {
1707
+ context.write("<");
1708
+ context.writeNodeList(declaration.params, ", ");
1709
+ context.write(">");
1710
+ }
1711
+
1712
+ function printTypeParameterInstantiation(
1713
+ instantiation: AST.TSTypeParameterInstantiation,
1714
+ context: PrinterContext,
1715
+ ): void {
1716
+ context.write("<");
1717
+ context.writeNodeList(instantiation.params, ", ");
1718
+ context.write(">");
1719
+ }
1720
+
1721
+ function printTSTypeParameter(
1722
+ parameter: AST.TSTypeParameter,
1723
+ context: PrinterContext,
1724
+ ): void {
1725
+ if (parameter.const === true) {
1726
+ context.write("const ");
1727
+ }
1728
+ if (parameter.in === true) {
1729
+ context.write("in ");
1730
+ }
1731
+ if (parameter.out === true) {
1732
+ context.write("out ");
1733
+ }
1734
+ // https://github.com/sveltejs/acorn-typescript/issues/7
1735
+ // parameter.name might be a string instead of an Identifier node
1736
+ if (typeof parameter.name === "string") {
1737
+ context.write(parameter.name);
1738
+ } else {
1739
+ context.writeNode(parameter.name);
1740
+ }
1741
+ if (parameter.constraint) {
1742
+ context.write(" extends ");
1743
+ context.writeNode(parameter.constraint);
1744
+ }
1745
+ if (parameter.default) {
1746
+ context.write(" = ");
1747
+ context.writeNode(parameter.default);
1748
+ }
1749
+ }
1750
+
1751
+ function printTSFunctionType(
1752
+ type: AST.TSFunctionType,
1753
+ context: PrinterContext,
1754
+ ): void {
1755
+ if (type.typeParameters) {
1756
+ context.writeNode(type.typeParameters);
1757
+ }
1758
+ context.write("(");
1759
+ if (type.params) {
1760
+ context.writeNodeList(type.params, ", ");
1761
+ } else if (type.parameters) {
1762
+ context.writeNodeList(type.parameters, ", ");
1763
+ }
1764
+ context.write(")");
1765
+ context.write(" => ");
1766
+ writeReturnType(type, context, { tsArrowType: true });
1767
+ }
1768
+
1769
+ function printTSConstructorType(
1770
+ type: AST.TSConstructorType,
1771
+ context: PrinterContext,
1772
+ ): void {
1773
+ context.write("new ");
1774
+ if (type.typeParameters) {
1775
+ context.writeNode(type.typeParameters);
1776
+ }
1777
+ context.write("(");
1778
+ if (type.params) {
1779
+ context.writeNodeList(type.params, ", ");
1780
+ } else if (type.parameters) {
1781
+ context.writeNodeList(type.parameters, ", ");
1782
+ }
1783
+ context.write(")");
1784
+ context.write(" => ");
1785
+ writeReturnType(type, context, { tsArrowType: true });
1786
+ }
1787
+
1788
+ function printTSMethodSignature(
1789
+ signature: AST.TSMethodSignature,
1790
+ context: PrinterContext,
1791
+ ): void {
1792
+ if (signature.readonly === true) {
1793
+ context.write("readonly ");
1794
+ }
1795
+ if (signature.computed === true) {
1796
+ context.write("[");
1797
+ context.writeNode(signature.key);
1798
+ context.write("]");
1799
+ } else {
1800
+ context.writeNode(signature.key);
1801
+ }
1802
+ if (signature.optional === true) {
1803
+ context.write("?");
1804
+ }
1805
+ if (signature.typeParameters) {
1806
+ context.writeNode(signature.typeParameters);
1807
+ }
1808
+ context.write("(");
1809
+ if (signature.params) {
1810
+ context.writeNodeList(signature.params, ", ");
1811
+ } else if (signature.parameters) {
1812
+ context.writeNodeList(signature.parameters, ", ");
1813
+ }
1814
+ context.write(")");
1815
+ writeReturnType(signature, context);
1816
+ context.write(";");
1817
+ }
1818
+
1819
+ function printTSCallSignatureDeclaration(
1820
+ signature: AST.TSCallSignatureDeclaration,
1821
+ context: PrinterContext,
1822
+ ): void {
1823
+ if (signature.typeParameters) {
1824
+ context.writeNode(signature.typeParameters);
1825
+ }
1826
+ context.write("(");
1827
+ if (signature.params) {
1828
+ context.writeNodeList(signature.params, ", ");
1829
+ } else if (signature.parameters) {
1830
+ context.writeNodeList(signature.parameters, ", ");
1831
+ }
1832
+ context.write(")");
1833
+ writeReturnType(signature, context);
1834
+ context.write(";");
1835
+ }
1836
+
1837
+ function printTSConstructSignatureDeclaration(
1838
+ signature: AST.TSConstructSignatureDeclaration,
1839
+ context: PrinterContext,
1840
+ ): void {
1841
+ context.write("new ");
1842
+ if (signature.typeParameters) {
1843
+ context.writeNode(signature.typeParameters);
1844
+ }
1845
+ context.write("(");
1846
+ if (signature.params) {
1847
+ context.writeNodeList(signature.params, ", ");
1848
+ } else if (signature.parameters) {
1849
+ context.writeNodeList(signature.parameters, ", ");
1850
+ }
1851
+ context.write(")");
1852
+ writeReturnType(signature, context);
1853
+ context.write(";");
1854
+ }
1855
+
1856
+ function printTSIndexSignature(
1857
+ signature: AST.TSIndexSignature,
1858
+ context: PrinterContext,
1859
+ ): void {
1860
+ context.write("[");
1861
+ if (signature.parameters) {
1862
+ context.writeNodeList(signature.parameters, ", ");
1863
+ }
1864
+ context.write("]");
1865
+ writeReturnType(signature, context);
1866
+ context.write(";");
1867
+ }
1868
+
1869
+ function writeReturnType(
1870
+ node: {
1871
+ returnType?: AST.TSTypeAnnotation | null;
1872
+ typeAnnotation?: AST.TSTypeAnnotation | null;
1873
+ },
1874
+ context: PrinterContext,
1875
+ options?: { tsArrowType: true },
1876
+ ): void {
1877
+ let ret: AST.Node | null | undefined = node.returnType ?? node.typeAnnotation;
1878
+ if (options?.tsArrowType) {
1879
+ // TSFunctionType / TSConstructorType use `=>` syntax:
1880
+ // must unwrap the TSTypeAnnotation to get the raw type node
1881
+ ret = ret?.typeAnnotation;
1882
+ }
1883
+ if (ret) {
1884
+ context.writeNode(ret);
1885
+ }
1886
+ }
1887
+
1888
+ function printTSTypeReference(
1889
+ reference: AST.TSTypeReference,
1890
+ context: PrinterContext,
1891
+ ): void {
1892
+ context.writeNode(reference.typeName);
1893
+ if (reference.typeArguments) {
1894
+ context.writeNode(reference.typeArguments);
1895
+ }
1896
+ }
1897
+
1898
+ function printTSQualifiedName(
1899
+ name: AST.TSQualifiedName,
1900
+ context: PrinterContext,
1901
+ ): void {
1902
+ context.writeNode(name.left);
1903
+ context.write(".");
1904
+ context.writeNode(name.right);
1905
+ }
1906
+
1907
+ function printJoinedTypes(
1908
+ joined: AST.TSUnionType | AST.TSIntersectionType,
1909
+ context: PrinterContext,
1910
+ ): void {
1911
+ context.writeNodeList(
1912
+ joined.types,
1913
+ joined.type === "TSUnionType" ? " | " : " & ",
1914
+ );
1915
+ }
1916
+
1917
+ function printTSArrayType(
1918
+ array: AST.TSArrayType,
1919
+ context: PrinterContext,
1920
+ ): void {
1921
+ context.writeNode(array.elementType);
1922
+ context.write("[]");
1923
+ }
1924
+
1925
+ function printTSTupleType(
1926
+ node: AST.TSTupleType,
1927
+ context: PrinterContext,
1928
+ ): void {
1929
+ context.write("[");
1930
+ context.writeNodeList(node.elementTypes, ", ");
1931
+ context.write("]");
1932
+ }
1933
+
1934
+ function printTSNamedTupleMember(
1935
+ node: AST.TSNamedTupleMember,
1936
+ context: PrinterContext,
1937
+ ): void {
1938
+ context.writeNode(node.label);
1939
+ context.write(": ");
1940
+ context.writeNode(node.elementType);
1941
+ }
1942
+
1943
+ function printTSTypeLiteral(
1944
+ literal: AST.TSTypeLiteral,
1945
+ context: PrinterContext,
1946
+ ): void {
1947
+ context.write("{ ");
1948
+ context.writeNodeList(literal.members, " ");
1949
+ context.write(" }");
1950
+ }
1951
+
1952
+ function printTSTypeOperator(
1953
+ node: AST.TSTypeOperator,
1954
+ context: PrinterContext,
1955
+ ): void {
1956
+ context.write(node.operator + " ");
1957
+ if (node.typeAnnotation) {
1958
+ context.writeNode(node.typeAnnotation);
1959
+ }
1960
+ }
1961
+
1962
+ function printTSTypePredicate(
1963
+ node: AST.TSTypePredicate,
1964
+ context: PrinterContext,
1965
+ ): void {
1966
+ if (node.asserts === true) {
1967
+ context.write("asserts ");
1968
+ }
1969
+ if (node.parameterName) {
1970
+ context.writeNode(node.parameterName);
1971
+ } else if (node.typeAnnotation) {
1972
+ context.writeNode(node.typeAnnotation);
1973
+ }
1974
+ if (node.asserts !== true || node.typeAnnotation) {
1975
+ context.write(" is ");
1976
+ }
1977
+ if (node.typeAnnotation) {
1978
+ context.writeNode(node.typeAnnotation.typeAnnotation);
1979
+ }
1980
+ }
1981
+
1982
+ function printTSTypeQuery(
1983
+ node: AST.TSTypeQuery,
1984
+ context: PrinterContext,
1985
+ ): void {
1986
+ context.write("typeof ");
1987
+ context.writeNode(node.exprName);
1988
+ }
1989
+
1990
+ function printTSMappedType(
1991
+ node: AST.TSMappedType,
1992
+ context: PrinterContext,
1993
+ ): void {
1994
+ context.write("{ [");
1995
+ const legacyTp = node.typeParameter;
1996
+ const key = node.key ?? legacyTp?.name;
1997
+ const constraint = node.constraint ?? legacyTp?.constraint;
1998
+
1999
+ if (key) {
2000
+ if (typeof key === "string") {
2001
+ context.write(key);
2002
+ } else {
2003
+ context.writeNode(key);
2004
+ }
2005
+ }
2006
+ if (constraint) {
2007
+ context.write(" in ");
2008
+ context.writeNode(constraint);
2009
+ }
2010
+ context.write("]");
2011
+ if (node.typeAnnotation) {
2012
+ context.write(": ");
2013
+ context.writeNode(node.typeAnnotation);
2014
+ }
2015
+ context.write(" }");
2016
+ }
2017
+
2018
+ function printTSConditionalType(
2019
+ node: AST.TSConditionalType,
2020
+ context: PrinterContext,
2021
+ ): void {
2022
+ context.writeNode(node.checkType);
2023
+ context.write(" extends ");
2024
+ context.writeNode(node.extendsType);
2025
+ context.write(" ? ");
2026
+ context.writeNode(node.trueType);
2027
+ context.write(" : ");
2028
+ context.writeNode(node.falseType);
2029
+ }
2030
+
2031
+ function printTSInferType(
2032
+ node: AST.TSInferType,
2033
+ context: PrinterContext,
2034
+ ): void {
2035
+ context.write("infer ");
2036
+ context.writeNode(node.typeParameter);
2037
+ }
2038
+
2039
+ function printTSIndexedAccessType(
2040
+ node: AST.TSIndexedAccessType,
2041
+ context: PrinterContext,
2042
+ ): void {
2043
+ context.writeNode(node.objectType);
2044
+ context.write("[");
2045
+ context.writeNode(node.indexType);
2046
+ context.write("]");
2047
+ }
2048
+
2049
+ function printTSOptionalType(
2050
+ node: AST.TSOptionalType,
2051
+ context: PrinterContext,
2052
+ ): void {
2053
+ context.writeNode(node.typeAnnotation);
2054
+ context.write("?");
2055
+ }
2056
+
2057
+ function printTSRestType(node: AST.TSRestType, context: PrinterContext): void {
2058
+ context.write("...");
2059
+ context.writeNode(node.typeAnnotation);
2060
+ }
2061
+
2062
+ function printTSThisType(_node: AST.TSThisType, context: PrinterContext): void {
2063
+ context.write("this");
2064
+ }
2065
+
2066
+ function printTSLiteralType(
2067
+ literal: AST.TSLiteralType,
2068
+ context: PrinterContext,
2069
+ ): void {
2070
+ context.writeNode(literal.literal);
2071
+ }
2072
+
2073
+ function printTSTemplateLiteralType(
2074
+ node: AST.TSTemplateLiteralType,
2075
+ context: PrinterContext,
2076
+ ): void {
2077
+ context.write("`");
2078
+ const { quasis, types } = node;
2079
+ for (let i = 0; i < types.length; i++) {
2080
+ context.write(quasis[i].value.raw);
2081
+ context.write("${");
2082
+ context.writeNode(types[i]);
2083
+ context.write("}");
2084
+ }
2085
+ context.write(quasis[quasis.length - 1].value.raw);
2086
+ context.write("`");
2087
+ }
2088
+
2089
+ function printTSImportType(
2090
+ node: AST.TSImportType,
2091
+ context: PrinterContext,
2092
+ ): void {
2093
+ context.write("import(");
2094
+ context.writeNode(node.argument);
2095
+ context.write(")");
2096
+ if (node.qualifier) {
2097
+ context.write(".");
2098
+ context.writeNode(node.qualifier);
2099
+ }
2100
+ }
2101
+
2102
+ function printTSImportEqualsDeclaration(
2103
+ node: AST.TSImportEqualsDeclaration,
2104
+ context: PrinterContext,
2105
+ ): void {
2106
+ context.write("import ");
2107
+ context.writeNode(node.id);
2108
+ context.write(" = ");
2109
+ context.writeNode(node.moduleReference);
2110
+ context.write(";");
2111
+ }
2112
+
2113
+ function printTSExternalModuleReference(
2114
+ node: AST.TSExternalModuleReference,
2115
+ context: PrinterContext,
2116
+ ): void {
2117
+ context.write("require(");
2118
+ context.writeNode(node.expression);
2119
+ context.write(")");
2120
+ }
2121
+
2122
+ function printTSEnumDeclaration(
2123
+ node: AST.TSEnumDeclaration,
2124
+ context: PrinterContext,
2125
+ ): void {
2126
+ if (node.declare === true) {
2127
+ context.write("declare ");
2128
+ }
2129
+ const isConst = node.const === true;
2130
+ if (isConst) {
2131
+ context.write("const ");
2132
+ }
2133
+ context.write("enum ");
2134
+ context.writeNode(node.id);
2135
+ context.write(" { ");
2136
+ context.writeNodeList(node.members, ", ");
2137
+ context.write(" }");
2138
+ }
2139
+
2140
+ function printTSEnumMember(
2141
+ node: AST.TSEnumMember,
2142
+ context: PrinterContext,
2143
+ ): void {
2144
+ context.writeNode(node.id);
2145
+ if (node.initializer) {
2146
+ context.write(" = ");
2147
+ context.writeNode(node.initializer);
2148
+ }
2149
+ }
2150
+
2151
+ function printTSModuleDeclaration(
2152
+ node: AST.TSModuleDeclaration,
2153
+ context: PrinterContext,
2154
+ ): void {
2155
+ if (node.declare === true) {
2156
+ context.write("declare ");
2157
+ }
2158
+ if (node.global === true) {
2159
+ context.write("global");
2160
+ } else {
2161
+ const kind =
2162
+ (node as AST.TSModuleDeclaration).kind ??
2163
+ (node.id && node.id.type === "Literal" ? "module" : "namespace");
2164
+ context.write(String(kind) + " ");
2165
+ context.writeNode(node.id);
2166
+ }
2167
+ if (node.body) {
2168
+ if (node.body.type === "TSModuleBlock") {
2169
+ context.write(" ");
2170
+ }
2171
+ context.writeNode(node.body);
2172
+ }
2173
+ }
2174
+
2175
+ function printTSModuleBlock(
2176
+ node: AST.TSModuleBlock,
2177
+ context: PrinterContext,
2178
+ ): void {
2179
+ context.write("{\n");
2180
+ context.writeNodeListWithSourceGaps(node.body, "\n");
2181
+ context.write("\n}");
2182
+ }
2183
+
2184
+ function printTSDeclareFunction(
2185
+ node: AST.TSDeclareFunction,
2186
+ context: PrinterContext,
2187
+ ): void {
2188
+ context.write("declare ");
2189
+ if (node.async === true) {
2190
+ context.write("async ");
2191
+ }
2192
+ context.write("function");
2193
+ if ((node.generator as boolean) === true) {
2194
+ context.write("*");
2195
+ }
2196
+ if (node.id) {
2197
+ context.write(" ");
2198
+ context.writeNode(node.id);
2199
+ }
2200
+ if (node.typeParameters) {
2201
+ context.writeNode(node.typeParameters);
2202
+ }
2203
+ context.write("(");
2204
+ context.writeNodeList(node.params, ", ");
2205
+ context.write(")");
2206
+ writeReturnType(node, context);
2207
+ context.write(";");
2208
+ }
2209
+
2210
+ function printTSParameterProperty(
2211
+ node: AST.TSParameterProperty,
2212
+ context: PrinterContext,
2213
+ ): void {
2214
+ if (node.accessibility) {
2215
+ context.write(node.accessibility + " ");
2216
+ }
2217
+ if (node.readonly === true) {
2218
+ context.write("readonly ");
2219
+ }
2220
+ context.writeNode(node.parameter);
2221
+ }
2222
+
2223
+ function printTSExportAssignment(
2224
+ node: AST.TSExportAssignment,
2225
+ context: PrinterContext,
2226
+ ): void {
2227
+ context.write("export = ");
2228
+ context.writeNode(node.expression);
2229
+ context.write(";");
2230
+ }
2231
+
2232
+ function printTSNamespaceExportDeclaration(
2233
+ node: AST.TSNamespaceExportDeclaration,
2234
+ context: PrinterContext,
2235
+ ): void {
2236
+ context.write("export as namespace ");
2237
+ context.writeNode(node.id);
2238
+ context.write(";");
2239
+ }
2240
+
2241
+ function printTSInstantiationExpression(
2242
+ node: { expression: AST.Node; typeArguments: AST.Node },
2243
+ context: PrinterContext,
2244
+ ): void {
2245
+ context.writeNode(node.expression);
2246
+ context.writeNode(node.typeArguments);
2247
+ }
2248
+
2249
+ function printTSParenthesizedType(
2250
+ node: { typeAnnotation: AST.Node },
2251
+ context: PrinterContext,
2252
+ ): void {
2253
+ context.write("(");
2254
+ context.writeNode(node.typeAnnotation);
2255
+ context.write(")");
2256
+ }
2257
+
2258
+ function printKeywordType(
2259
+ node: Extract<AST.Node, { type: `${string}Keyword` }>,
2260
+ context: PrinterContext,
2261
+ ): void {
2262
+ const keyword = node.type.slice(2, -"Keyword".length).toLowerCase();
2263
+ context.write(keyword);
2264
+ }
2265
+
2266
+ function writeOptionalTypeAnnotation(
2267
+ node: { optional?: boolean; typeAnnotation?: AST.Node | null },
2268
+ context: PrinterContext,
2269
+ ): void {
2270
+ if (node.optional === true) {
2271
+ context.write("?");
2272
+ }
2273
+ if (node.typeAnnotation) {
2274
+ context.writeNode(node.typeAnnotation);
2275
+ }
2276
+ }