esrap 1.4.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/handlers.js DELETED
@@ -1,1669 +0,0 @@
1
- /** @import { TSESTree } from '@typescript-eslint/types' */
2
- /** @import { Command, Dedent, Handlers, Location, Indent, Newline, NodeWithComments, State, TypeAnnotationNodes } from './types' */
3
-
4
- /** @type {Newline} */
5
- const newline = { type: 'Newline' };
6
-
7
- /** @type {Indent} */
8
- const indent = { type: 'Indent' };
9
-
10
- /** @type {Dedent} */
11
- const dedent = { type: 'Dedent' };
12
-
13
- /**
14
- * @returns {Command[]}
15
- */
16
- function create_sequence() {
17
- return [];
18
- }
19
-
20
- /**
21
- * Rough estimate of the combined width of a group of commands
22
- * @param {Command[]} commands
23
- * @param {number} from
24
- * @param {number} to
25
- */
26
- function measure(commands, from, to = commands.length) {
27
- let total = 0;
28
- for (let i = from; i < to; i += 1) {
29
- const command = commands[i];
30
- if (typeof command === 'string') {
31
- total += command.length;
32
- } else if (Array.isArray(command)) {
33
- total +=
34
- command.length === 0
35
- ? 2 // assume this is ', '
36
- : measure(command, 0);
37
- }
38
- }
39
-
40
- return total;
41
- }
42
-
43
- /**
44
- * @param {TSESTree.Node} node
45
- * @param {State} state
46
- */
47
- export function handle(node, state) {
48
- const node_with_comments = /** @type {NodeWithComments} */ (node);
49
-
50
- const handler = handlers[node.type];
51
-
52
- if (!handler) {
53
- throw new Error(`Not implemented ${node.type}`);
54
- }
55
-
56
- if (node_with_comments.leadingComments) {
57
- prepend_comments(node_with_comments.leadingComments, state, false);
58
- }
59
-
60
- // @ts-expect-error
61
- handler(node, state);
62
-
63
- if (node_with_comments.trailingComments) {
64
- state.comments.push(node_with_comments.trailingComments[0]); // there is only ever one
65
- }
66
- }
67
-
68
- /**
69
- * @param {number} line
70
- * @param {number} column
71
- * @returns {Location}
72
- */
73
- function l(line, column) {
74
- return {
75
- type: 'Location',
76
- line,
77
- column
78
- };
79
- }
80
-
81
- /**
82
- * @param {string} content
83
- * @param {TSESTree.Node} node
84
- * @returns {string | Command[]}
85
- */
86
- function c(content, node) {
87
- return node.loc
88
- ? [
89
- l(node.loc.start.line, node.loc.start.column),
90
- content,
91
- l(node.loc.end.line, node.loc.end.column)
92
- ]
93
- : content;
94
- }
95
-
96
- /**
97
- * @param {TSESTree.Comment[]} comments
98
- * @param {State} state
99
- * @param {boolean} newlines
100
- */
101
- function prepend_comments(comments, state, newlines) {
102
- for (const comment of comments) {
103
- state.commands.push({ type: 'Comment', comment });
104
-
105
- if (newlines || comment.type === 'Line' || /\n/.test(comment.value)) {
106
- state.commands.push(newline);
107
- } else {
108
- state.commands.push(' ');
109
- }
110
- }
111
- }
112
-
113
- /**
114
- * @param {string} string
115
- * @param {'\'' | '"'} char
116
- */
117
- function quote(string, char) {
118
- let out = char;
119
-
120
- for (const c of string) {
121
- if (c === '\\') {
122
- out += '\\\\';
123
- } else if (c === char) {
124
- out += '\\' + c;
125
- } else if (c === '\n') {
126
- out += '\\n';
127
- } else if (c === '\r') {
128
- out += '\\r';
129
- } else {
130
- out += c;
131
- }
132
- }
133
-
134
- return out + char;
135
- }
136
-
137
- const OPERATOR_PRECEDENCE = {
138
- '||': 2,
139
- '&&': 3,
140
- '??': 4,
141
- '|': 5,
142
- '^': 6,
143
- '&': 7,
144
- '==': 8,
145
- '!=': 8,
146
- '===': 8,
147
- '!==': 8,
148
- '<': 9,
149
- '>': 9,
150
- '<=': 9,
151
- '>=': 9,
152
- in: 9,
153
- instanceof: 9,
154
- '<<': 10,
155
- '>>': 10,
156
- '>>>': 10,
157
- '+': 11,
158
- '-': 11,
159
- '*': 12,
160
- '%': 12,
161
- '/': 12,
162
- '**': 13
163
- };
164
-
165
- /** @type {Record<TSESTree.Expression['type'] | 'Super' | 'RestElement', number>} */
166
- const EXPRESSIONS_PRECEDENCE = {
167
- JSXFragment: 20,
168
- JSXElement: 20,
169
- ArrayPattern: 20,
170
- ObjectPattern: 20,
171
- ArrayExpression: 20,
172
- TaggedTemplateExpression: 20,
173
- ThisExpression: 20,
174
- Identifier: 20,
175
- TemplateLiteral: 20,
176
- Super: 20,
177
- SequenceExpression: 20,
178
- MemberExpression: 19,
179
- MetaProperty: 19,
180
- CallExpression: 19,
181
- ChainExpression: 19,
182
- ImportExpression: 19,
183
- NewExpression: 19,
184
- Literal: 18,
185
- TSSatisfiesExpression: 18,
186
- TSInstantiationExpression: 18,
187
- TSNonNullExpression: 18,
188
- TSTypeAssertion: 18,
189
- AwaitExpression: 17,
190
- ClassExpression: 17,
191
- FunctionExpression: 17,
192
- ObjectExpression: 17,
193
- TSAsExpression: 16,
194
- UpdateExpression: 16,
195
- UnaryExpression: 15,
196
- BinaryExpression: 14,
197
- LogicalExpression: 13,
198
- ConditionalExpression: 4,
199
- ArrowFunctionExpression: 3,
200
- AssignmentExpression: 3,
201
- YieldExpression: 2,
202
- RestElement: 1
203
- };
204
-
205
- /**
206
- *
207
- * @param {TSESTree.Expression | TSESTree.PrivateIdentifier} node
208
- * @param {TSESTree.BinaryExpression | TSESTree.LogicalExpression} parent
209
- * @param {boolean} is_right
210
- * @returns
211
- */
212
- function needs_parens(node, parent, is_right) {
213
- if (node.type === 'PrivateIdentifier') return false;
214
-
215
- // special case where logical expressions and coalesce expressions cannot be mixed,
216
- // either of them need to be wrapped with parentheses
217
- if (
218
- node.type === 'LogicalExpression' &&
219
- parent.type === 'LogicalExpression' &&
220
- ((parent.operator === '??' && node.operator !== '??') ||
221
- (parent.operator !== '??' && node.operator === '??'))
222
- ) {
223
- return true;
224
- }
225
-
226
- const precedence = EXPRESSIONS_PRECEDENCE[node.type];
227
- const parent_precedence = EXPRESSIONS_PRECEDENCE[parent.type];
228
-
229
- if (precedence !== parent_precedence) {
230
- // Different node types
231
- return (
232
- (!is_right && precedence === 15 && parent_precedence === 14 && parent.operator === '**') ||
233
- precedence < parent_precedence
234
- );
235
- }
236
-
237
- if (precedence !== 13 && precedence !== 14) {
238
- // Not a `LogicalExpression` or `BinaryExpression`
239
- return false;
240
- }
241
-
242
- if (
243
- /** @type {TSESTree.BinaryExpression} */ (node).operator === '**' &&
244
- parent.operator === '**'
245
- ) {
246
- // Exponentiation operator has right-to-left associativity
247
- return !is_right;
248
- }
249
-
250
- if (is_right) {
251
- // Parenthesis are used if both operators have the same precedence
252
- return (
253
- OPERATOR_PRECEDENCE[/** @type {TSESTree.BinaryExpression} */ (node).operator] <=
254
- OPERATOR_PRECEDENCE[parent.operator]
255
- );
256
- }
257
-
258
- return (
259
- OPERATOR_PRECEDENCE[/** @type {TSESTree.BinaryExpression} */ (node).operator] <
260
- OPERATOR_PRECEDENCE[parent.operator]
261
- );
262
- }
263
-
264
- /** @param {TSESTree.Node} node */
265
- function has_call_expression(node) {
266
- while (node) {
267
- if (node.type === 'CallExpression') {
268
- return true;
269
- } else if (node.type === 'MemberExpression') {
270
- node = node.object;
271
- } else {
272
- return false;
273
- }
274
- }
275
- }
276
-
277
- const grouped_expression_types = [
278
- 'ImportDeclaration',
279
- 'VariableDeclaration',
280
- 'ExportDefaultDeclaration',
281
- 'ExportNamedDeclaration'
282
- ];
283
-
284
- /**
285
- * @param {TSESTree.Node[]} nodes
286
- * @param {State} state
287
- */
288
- const handle_body = (nodes, state) => {
289
- let last_statement = /** @type {TSESTree.Node} */ ({
290
- type: 'EmptyStatement'
291
- });
292
- let first = true;
293
- let needs_margin = false;
294
-
295
- for (const statement of nodes) {
296
- if (statement.type === 'EmptyStatement') continue;
297
-
298
- const margin = create_sequence();
299
-
300
- if (!first) state.commands.push(margin, newline);
301
- first = false;
302
-
303
- const statement_with_comments = /** @type {NodeWithComments} */ (statement);
304
- const leading_comments = statement_with_comments.leadingComments;
305
- delete statement_with_comments.leadingComments;
306
-
307
- if (leading_comments && leading_comments.length > 0) {
308
- prepend_comments(leading_comments, state, true);
309
- }
310
-
311
- const child_state = { ...state, multiline: false };
312
- handle(statement, child_state);
313
-
314
- if (
315
- child_state.multiline ||
316
- needs_margin ||
317
- ((grouped_expression_types.includes(statement.type) ||
318
- grouped_expression_types.includes(last_statement.type)) &&
319
- last_statement.type !== statement.type)
320
- ) {
321
- margin.push('\n');
322
- }
323
-
324
- let add_newline = false;
325
-
326
- while (state.comments.length) {
327
- const comment = /** @type {TSESTree.Comment} */ (state.comments.shift());
328
-
329
- state.commands.push(add_newline ? newline : ' ', { type: 'Comment', comment });
330
- add_newline = comment.type === 'Line';
331
- }
332
-
333
- needs_margin = child_state.multiline;
334
- last_statement = statement;
335
- }
336
- };
337
-
338
- /**
339
- * @param {TSESTree.VariableDeclaration} node
340
- * @param {State} state
341
- */
342
- const handle_var_declaration = (node, state) => {
343
- const index = state.commands.length;
344
-
345
- const open = create_sequence();
346
- const join = create_sequence();
347
- const child_state = { ...state, multiline: false };
348
-
349
- state.commands.push(`${node.kind} `, open);
350
-
351
- let first = true;
352
-
353
- for (const d of node.declarations) {
354
- if (!first) state.commands.push(join);
355
- first = false;
356
-
357
- handle(d, child_state);
358
- }
359
-
360
- const multiline =
361
- child_state.multiline || (node.declarations.length > 1 && measure(state.commands, index) > 50);
362
-
363
- if (multiline) {
364
- state.multiline = true;
365
- if (node.declarations.length > 1) open.push(indent);
366
- join.push(',', newline);
367
- if (node.declarations.length > 1) state.commands.push(dedent);
368
- } else {
369
- join.push(', ');
370
- }
371
- };
372
-
373
- /**
374
- * @template {TSESTree.Node} T
375
- * @param {Array<T | null>} nodes
376
- * @param {State} state
377
- * @param {boolean} spaces
378
- * @param {(node: T, state: State) => void} fn
379
- */
380
- function sequence(nodes, state, spaces, fn, separator = ',') {
381
- if (nodes.length === 0) return;
382
-
383
- const index = state.commands.length;
384
-
385
- const open = create_sequence();
386
- const join = create_sequence();
387
- const close = create_sequence();
388
-
389
- state.commands.push(open);
390
-
391
- const child_state = { ...state, multiline: false };
392
-
393
- let prev;
394
-
395
- for (let i = 0; i < nodes.length; i += 1) {
396
- const node = nodes[i];
397
- const is_first = i === 0;
398
- const is_last = i === nodes.length - 1;
399
-
400
- if (node) {
401
- if (!is_first && !prev) {
402
- state.commands.push(join);
403
- }
404
-
405
- fn(node, child_state);
406
-
407
- if (!is_last) {
408
- state.commands.push(separator);
409
- }
410
-
411
- if (state.comments.length > 0) {
412
- state.commands.push(' ');
413
-
414
- while (state.comments.length) {
415
- const comment = /** @type {TSESTree.Comment} */ (state.comments.shift());
416
- state.commands.push({ type: 'Comment', comment });
417
- if (!is_last) state.commands.push(join);
418
- }
419
-
420
- child_state.multiline = true;
421
- } else {
422
- if (!is_last) state.commands.push(join);
423
- }
424
- } else {
425
- // This is only used for ArrayPattern and ArrayExpression, but
426
- // it makes more sense to have the logic here than there, because
427
- // otherwise we'd duplicate a lot more stuff
428
- state.commands.push(separator);
429
- }
430
-
431
- prev = node;
432
- }
433
-
434
- state.commands.push(close);
435
-
436
- const multiline = child_state.multiline || measure(state.commands, index) > 50;
437
-
438
- if (multiline) {
439
- state.multiline = true;
440
-
441
- open.push(indent, newline);
442
- join.push(newline);
443
- close.push(dedent, newline);
444
- } else {
445
- if (spaces) open.push(' ');
446
- join.push(' ');
447
- if (spaces) close.push(' ');
448
- }
449
- }
450
-
451
- /**
452
- * @param {TypeAnnotationNodes} node
453
- * @param {State} state
454
- */
455
- function handle_type_annotation(node, state) {
456
- switch (node.type) {
457
- case 'TSNumberKeyword':
458
- state.commands.push('number');
459
- break;
460
- case 'TSStringKeyword':
461
- state.commands.push('string');
462
- break;
463
- case 'TSBooleanKeyword':
464
- state.commands.push('boolean');
465
- break;
466
- case 'TSAnyKeyword':
467
- state.commands.push('any');
468
- break;
469
- case 'TSVoidKeyword':
470
- state.commands.push('void');
471
- break;
472
- case 'TSUnknownKeyword':
473
- state.commands.push('unknown');
474
- break;
475
- case 'TSNeverKeyword':
476
- state.commands.push('never');
477
- break;
478
- case 'TSArrayType':
479
- handle_type_annotation(node.elementType, state);
480
- state.commands.push('[]');
481
- break;
482
- case 'TSTypeAnnotation':
483
- state.commands.push(': ');
484
- handle_type_annotation(node.typeAnnotation, state);
485
- break;
486
- case 'TSTypeLiteral':
487
- state.commands.push('{ ');
488
- sequence(node.members, state, false, handle_type_annotation, ';');
489
- state.commands.push(' }');
490
- break;
491
- case 'TSPropertySignature':
492
- handle(node.key, state);
493
- if (node.optional) state.commands.push('?');
494
- if (node.typeAnnotation) handle_type_annotation(node.typeAnnotation, state);
495
- break;
496
- case 'TSTypeReference':
497
- handle(node.typeName, state);
498
-
499
- if (node.typeArguments) {
500
- handle_type_annotation(node.typeArguments, state);
501
- }
502
- break;
503
- case 'TSTypeParameterInstantiation':
504
- case 'TSTypeParameterDeclaration':
505
- state.commands.push('<');
506
- for (let i = 0; i < node.params.length; i++) {
507
- handle_type_annotation(node.params[i], state);
508
- if (i != node.params.length - 1) state.commands.push(', ');
509
- }
510
- state.commands.push('>');
511
- break;
512
- case 'TSTypeParameter':
513
- // @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
514
- state.commands.push(node.name);
515
-
516
- if (node.constraint) {
517
- state.commands.push(' extends ');
518
- handle_type_annotation(node.constraint, state);
519
- }
520
- break;
521
- case 'TSTypeQuery':
522
- state.commands.push('typeof ');
523
- handle(node.exprName, state);
524
- break;
525
- case 'TSEnumMember':
526
- handle(node.id, state);
527
- if (node.initializer) {
528
- state.commands.push(' = ');
529
- handle(node.initializer, state);
530
- }
531
- break;
532
- case 'TSFunctionType':
533
- if (node.typeParameters) handle_type_annotation(node.typeParameters, state);
534
-
535
- // @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
536
- const parameters = node.parameters;
537
- state.commands.push('(');
538
- sequence(parameters, state, false, handle);
539
-
540
- state.commands.push(') => ');
541
-
542
- // @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
543
- handle_type_annotation(node.typeAnnotation.typeAnnotation, state);
544
- break;
545
- case 'TSIndexSignature':
546
- const indexParameters = node.parameters;
547
- state.commands.push('[');
548
- sequence(indexParameters, state, false, handle);
549
- state.commands.push(']');
550
-
551
- // @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
552
- handle_type_annotation(node.typeAnnotation, state);
553
- break;
554
- case 'TSMethodSignature':
555
- handle(node.key, state);
556
-
557
- // @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
558
- const parametersSignature = node.parameters;
559
- state.commands.push('(');
560
- sequence(parametersSignature, state, false, handle);
561
- state.commands.push(')');
562
-
563
- // @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
564
- handle_type_annotation(node.typeAnnotation, state);
565
- break;
566
- case 'TSExpressionWithTypeArguments':
567
- handle(node.expression, state);
568
- break;
569
- case 'TSTupleType':
570
- state.commands.push('[');
571
- sequence(node.elementTypes, state, false, handle_type_annotation);
572
- state.commands.push(']');
573
- break;
574
- case 'TSNamedTupleMember':
575
- handle(node.label, state);
576
- state.commands.push(': ');
577
- handle_type_annotation(node.elementType, state);
578
-
579
- break;
580
- case 'TSUnionType':
581
- sequence(node.types, state, false, handle_type_annotation, ' |');
582
- break;
583
- case 'TSIntersectionType':
584
- sequence(node.types, state, false, handle_type_annotation, ' &');
585
- break;
586
- case 'TSLiteralType':
587
- handle(node.literal, state);
588
- break;
589
- case 'TSConditionalType':
590
- handle_type_annotation(node.checkType, state);
591
- state.commands.push(' extends ');
592
- handle_type_annotation(node.extendsType, state);
593
- state.commands.push(' ? ');
594
- handle_type_annotation(node.trueType, state);
595
- state.commands.push(' : ');
596
- handle_type_annotation(node.falseType, state);
597
- break;
598
- case 'TSIndexedAccessType':
599
- handle_type_annotation(node.objectType, state);
600
- state.commands.push('[');
601
- handle_type_annotation(node.indexType, state);
602
- state.commands.push(']');
603
- break;
604
- case 'TSImportType':
605
- state.commands.push('import(');
606
- handle(node.argument, state);
607
- state.commands.push(')');
608
-
609
- if (node.qualifier) {
610
- state.commands.push('.');
611
- handle(node.qualifier, state);
612
- }
613
- break;
614
- default:
615
- throw new Error(`Not implemented type annotation ${node.type}`);
616
- }
617
- }
618
-
619
- /** @satisfies {Record<string, (node: any, state: State) => undefined>} */
620
- const shared = {
621
- /**
622
- * @param {TSESTree.ArrayExpression | TSESTree.ArrayPattern} node
623
- * @param {State} state
624
- */
625
- 'ArrayExpression|ArrayPattern': (node, state) => {
626
- state.commands.push('[');
627
- sequence(/** @type {TSESTree.Node[]} */ (node.elements), state, false, handle);
628
- state.commands.push(']');
629
- },
630
-
631
- /**
632
- * @param {TSESTree.BinaryExpression | TSESTree.LogicalExpression} node
633
- * @param {State} state
634
- */
635
- 'BinaryExpression|LogicalExpression': (node, state) => {
636
- // TODO
637
- // const is_in = node.operator === 'in';
638
- // if (is_in) {
639
- // // Avoids confusion in `for` loops initializers
640
- // chunks.push(c('('));
641
- // }
642
-
643
- if (needs_parens(node.left, node, false)) {
644
- state.commands.push('(');
645
- handle(node.left, state);
646
- state.commands.push(')');
647
- } else {
648
- handle(node.left, state);
649
- }
650
-
651
- state.commands.push(` ${node.operator} `);
652
-
653
- if (needs_parens(node.right, node, true)) {
654
- state.commands.push('(');
655
- handle(node.right, state);
656
- state.commands.push(')');
657
- } else {
658
- handle(node.right, state);
659
- }
660
- },
661
-
662
- /**
663
- * @param {TSESTree.BlockStatement | TSESTree.ClassBody} node
664
- * @param {State} state
665
- */
666
- 'BlockStatement|ClassBody': (node, state) => {
667
- if (node.loc) {
668
- const { line, column } = node.loc.start;
669
- state.commands.push(l(line, column), '{', l(line, column + 1));
670
- } else {
671
- state.commands.push('{');
672
- }
673
-
674
- if (node.body.length > 0) {
675
- state.multiline = true;
676
- state.commands.push(indent, newline);
677
- handle_body(node.body, state);
678
- state.commands.push(dedent, newline);
679
- }
680
-
681
- if (node.loc) {
682
- const { line, column } = node.loc.end;
683
- state.commands.push(l(line, column - 1), '}', l(line, column));
684
- } else {
685
- state.commands.push('}');
686
- }
687
- },
688
-
689
- /**
690
- * @param {TSESTree.CallExpression | TSESTree.NewExpression} node
691
- * @param {State} state
692
- */
693
- 'CallExpression|NewExpression': (node, state) => {
694
- if (node.type === 'NewExpression') {
695
- state.commands.push('new ');
696
- }
697
-
698
- const needs_parens =
699
- EXPRESSIONS_PRECEDENCE[node.callee.type] < EXPRESSIONS_PRECEDENCE.CallExpression ||
700
- (node.type === 'NewExpression' && has_call_expression(node.callee));
701
-
702
- if (needs_parens) {
703
- state.commands.push('(');
704
- handle(node.callee, state);
705
- state.commands.push(')');
706
- } else {
707
- handle(node.callee, state);
708
- }
709
-
710
- if (/** @type {TSESTree.CallExpression} */ (node).optional) {
711
- state.commands.push('?.');
712
- }
713
-
714
- if (node.typeArguments) handle_type_annotation(node.typeArguments, state);
715
-
716
- const open = create_sequence();
717
- const join = create_sequence();
718
- const close = create_sequence();
719
-
720
- state.commands.push('(', open);
721
-
722
- // if the final argument is multiline, it doesn't need to force all the
723
- // other arguments to also be multiline
724
- const child_state = { ...state, multiline: false };
725
- const final_state = { ...state, multiline: false };
726
-
727
- for (let i = 0; i < node.arguments.length; i += 1) {
728
- if (i > 0) {
729
- if (state.comments.length > 0) {
730
- state.commands.push(', ');
731
-
732
- while (state.comments.length) {
733
- const comment = /** @type {TSESTree.Comment} */ (state.comments.shift());
734
-
735
- state.commands.push({ type: 'Comment', comment });
736
-
737
- if (comment.type === 'Line') {
738
- child_state.multiline = true;
739
- state.commands.push(newline);
740
- } else {
741
- state.commands.push(' ');
742
- }
743
- }
744
- } else {
745
- state.commands.push(join);
746
- }
747
- }
748
-
749
- const p = node.arguments[i];
750
-
751
- handle(p, i === node.arguments.length - 1 ? final_state : child_state);
752
- }
753
-
754
- state.commands.push(close, ')');
755
-
756
- const multiline = child_state.multiline;
757
-
758
- if (multiline || final_state.multiline) {
759
- state.multiline = true;
760
- }
761
-
762
- if (multiline) {
763
- open.push(indent, newline);
764
- join.push(',', newline);
765
- close.push(dedent, newline);
766
- } else {
767
- join.push(', ');
768
- }
769
- },
770
-
771
- /**
772
- * @param {TSESTree.ClassDeclaration | TSESTree.ClassExpression} node
773
- * @param {State} state
774
- */
775
- 'ClassDeclaration|ClassExpression': (node, state) => {
776
- state.commands.push('class ');
777
-
778
- if (node.id) {
779
- handle(node.id, state);
780
- state.commands.push(' ');
781
- }
782
-
783
- if (node.superClass) {
784
- state.commands.push('extends ');
785
- handle(node.superClass, state);
786
- state.commands.push(' ');
787
- }
788
-
789
- if (node.implements) {
790
- state.commands.push('implements ');
791
- sequence(node.implements, state, false, handle_type_annotation);
792
- }
793
-
794
- handle(node.body, state);
795
- },
796
-
797
- /**
798
- * @param {TSESTree.ForInStatement | TSESTree.ForOfStatement} node
799
- * @param {State} state
800
- */
801
- 'ForInStatement|ForOfStatement': (node, state) => {
802
- state.commands.push('for ');
803
- if (node.type === 'ForOfStatement' && node.await) state.commands.push('await ');
804
- state.commands.push('(');
805
-
806
- if (node.left.type === 'VariableDeclaration') {
807
- handle_var_declaration(node.left, state);
808
- } else {
809
- handle(node.left, state);
810
- }
811
-
812
- state.commands.push(node.type === 'ForInStatement' ? ` in ` : ` of `);
813
- handle(node.right, state);
814
- state.commands.push(') ');
815
- handle(node.body, state);
816
- },
817
-
818
- /**
819
- * @param {TSESTree.FunctionDeclaration | TSESTree.FunctionExpression} node
820
- * @param {State} state
821
- */
822
- 'FunctionDeclaration|FunctionExpression': (node, state) => {
823
- if (node.async) state.commands.push('async ');
824
- state.commands.push(node.generator ? 'function* ' : 'function ');
825
- if (node.id) handle(node.id, state);
826
-
827
- if (node.typeParameters) {
828
- handle_type_annotation(node.typeParameters, state);
829
- }
830
-
831
- state.commands.push('(');
832
- sequence(node.params, state, false, handle);
833
- state.commands.push(')');
834
-
835
- if (node.returnType) handle_type_annotation(node.returnType, state);
836
-
837
- state.commands.push(' ');
838
-
839
- handle(node.body, state);
840
- },
841
-
842
- /**
843
- * @param {TSESTree.RestElement | TSESTree.SpreadElement} node
844
- * @param {State} state
845
- */
846
- 'RestElement|SpreadElement': (node, state) => {
847
- state.commands.push('...');
848
- handle(node.argument, state);
849
-
850
- // @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
851
- if (node.typeAnnotation) handle_type_annotation(node.typeAnnotation, state);
852
- }
853
- };
854
-
855
- /** @type {Handlers} */
856
- const handlers = {
857
- ArrayExpression: shared['ArrayExpression|ArrayPattern'],
858
-
859
- ArrayPattern: shared['ArrayExpression|ArrayPattern'],
860
-
861
- ArrowFunctionExpression: (node, state) => {
862
- if (node.async) state.commands.push('async ');
863
-
864
- state.commands.push('(');
865
- sequence(node.params, state, false, handle);
866
- state.commands.push(') => ');
867
-
868
- if (
869
- node.body.type === 'ObjectExpression' ||
870
- (node.body.type === 'AssignmentExpression' && node.body.left.type === 'ObjectPattern') ||
871
- (node.body.type === 'LogicalExpression' && node.body.left.type === 'ObjectExpression') ||
872
- (node.body.type === 'ConditionalExpression' && node.body.test.type === 'ObjectExpression')
873
- ) {
874
- state.commands.push('(');
875
- handle(node.body, state);
876
- state.commands.push(')');
877
- } else {
878
- handle(node.body, state);
879
- }
880
- },
881
-
882
- AssignmentExpression(node, state) {
883
- handle(node.left, state);
884
- state.commands.push(` ${node.operator} `);
885
- handle(node.right, state);
886
- },
887
-
888
- AssignmentPattern(node, state) {
889
- handle(node.left, state);
890
- state.commands.push(' = ');
891
- handle(node.right, state);
892
- },
893
-
894
- AwaitExpression(node, state) {
895
- if (node.argument) {
896
- const precedence = EXPRESSIONS_PRECEDENCE[node.argument.type];
897
-
898
- if (precedence && precedence < EXPRESSIONS_PRECEDENCE.AwaitExpression) {
899
- state.commands.push('await (');
900
- handle(node.argument, state);
901
- state.commands.push(')');
902
- } else {
903
- state.commands.push('await ');
904
- handle(node.argument, state);
905
- }
906
- } else {
907
- state.commands.push('await');
908
- }
909
- },
910
-
911
- BinaryExpression: shared['BinaryExpression|LogicalExpression'],
912
-
913
- BlockStatement: shared['BlockStatement|ClassBody'],
914
-
915
- BreakStatement(node, state) {
916
- if (node.label) {
917
- state.commands.push('break ');
918
- handle(node.label, state);
919
- state.commands.push(';');
920
- } else {
921
- state.commands.push('break;');
922
- }
923
- },
924
-
925
- CallExpression: shared['CallExpression|NewExpression'],
926
-
927
- ChainExpression(node, state) {
928
- handle(node.expression, state);
929
- },
930
-
931
- ClassBody: shared['BlockStatement|ClassBody'],
932
-
933
- ClassDeclaration: shared['ClassDeclaration|ClassExpression'],
934
-
935
- ClassExpression: shared['ClassDeclaration|ClassExpression'],
936
-
937
- ConditionalExpression(node, state) {
938
- if (EXPRESSIONS_PRECEDENCE[node.test.type] > EXPRESSIONS_PRECEDENCE.ConditionalExpression) {
939
- handle(node.test, state);
940
- } else {
941
- state.commands.push('(');
942
- handle(node.test, state);
943
- state.commands.push(')');
944
- }
945
-
946
- const if_true = create_sequence();
947
- const if_false = create_sequence();
948
-
949
- const child_state = { ...state, multiline: false };
950
-
951
- state.commands.push(if_true);
952
- handle(node.consequent, child_state);
953
- state.commands.push(if_false);
954
- handle(node.alternate, child_state);
955
-
956
- const multiline = child_state.multiline;
957
-
958
- if (multiline) {
959
- if_true.push(indent, newline, '? ');
960
- if_false.push(newline, ': ');
961
- state.commands.push(dedent);
962
- } else {
963
- if_true.push(' ? ');
964
- if_false.push(' : ');
965
- }
966
- },
967
-
968
- ContinueStatement(node, state) {
969
- if (node.label) {
970
- state.commands.push('continue ');
971
- handle(node.label, state);
972
- state.commands.push(';');
973
- } else {
974
- state.commands.push('continue;');
975
- }
976
- },
977
-
978
- DebuggerStatement(node, state) {
979
- state.commands.push(c('debugger', node), ';');
980
- },
981
-
982
- Decorator(node, state) {
983
- state.commands.push('@');
984
- handle(node.expression, state);
985
- state.commands.push(newline);
986
- },
987
-
988
- DoWhileStatement(node, state) {
989
- state.commands.push('do ');
990
- handle(node.body, state);
991
- state.commands.push(' while (');
992
- handle(node.test, state);
993
- state.commands.push(');');
994
- },
995
-
996
- EmptyStatement(node, state) {
997
- state.commands.push(';');
998
- },
999
-
1000
- ExportAllDeclaration(node, state) {
1001
- state.commands.push('export * ');
1002
- if (node.exported) {
1003
- state.commands.push('as ');
1004
- handle(node.exported, state);
1005
- }
1006
- state.commands.push(' from ');
1007
- handle(node.source, state);
1008
- state.commands.push(';');
1009
- },
1010
-
1011
- ExportDefaultDeclaration(node, state) {
1012
- state.commands.push('export default ');
1013
-
1014
- handle(node.declaration, state);
1015
-
1016
- if (node.declaration.type !== 'FunctionDeclaration') {
1017
- state.commands.push(';');
1018
- }
1019
- },
1020
-
1021
- ExportNamedDeclaration(node, state) {
1022
- state.commands.push('export ');
1023
-
1024
- if (node.declaration) {
1025
- handle(node.declaration, state);
1026
- return;
1027
- }
1028
-
1029
- state.commands.push('{');
1030
- sequence(node.specifiers, state, true, (s, state) => {
1031
- handle(s.local, state);
1032
-
1033
- if (s.local.name !== s.exported.name) {
1034
- state.commands.push(' as ');
1035
- handle(s.exported, state);
1036
- }
1037
- });
1038
- state.commands.push('}');
1039
-
1040
- if (node.source) {
1041
- state.commands.push(' from ');
1042
- handle(node.source, state);
1043
- }
1044
-
1045
- state.commands.push(';');
1046
- },
1047
-
1048
- ExpressionStatement(node, state) {
1049
- if (
1050
- node.expression.type === 'ObjectExpression' ||
1051
- (node.expression.type === 'AssignmentExpression' &&
1052
- node.expression.left.type === 'ObjectPattern') ||
1053
- node.expression.type === 'FunctionExpression'
1054
- ) {
1055
- // is an AssignmentExpression to an ObjectPattern
1056
- state.commands.push('(');
1057
- handle(node.expression, state);
1058
- state.commands.push(');');
1059
- return;
1060
- }
1061
-
1062
- handle(node.expression, state);
1063
- state.commands.push(';');
1064
- },
1065
-
1066
- ForStatement: (node, state) => {
1067
- state.commands.push('for (');
1068
-
1069
- if (node.init) {
1070
- if (node.init.type === 'VariableDeclaration') {
1071
- handle_var_declaration(node.init, state);
1072
- } else {
1073
- handle(node.init, state);
1074
- }
1075
- }
1076
-
1077
- state.commands.push('; ');
1078
- if (node.test) handle(node.test, state);
1079
- state.commands.push('; ');
1080
- if (node.update) handle(node.update, state);
1081
-
1082
- state.commands.push(') ');
1083
- handle(node.body, state);
1084
- },
1085
-
1086
- ForInStatement: shared['ForInStatement|ForOfStatement'],
1087
-
1088
- ForOfStatement: shared['ForInStatement|ForOfStatement'],
1089
-
1090
- FunctionDeclaration: shared['FunctionDeclaration|FunctionExpression'],
1091
-
1092
- FunctionExpression: shared['FunctionDeclaration|FunctionExpression'],
1093
-
1094
- Identifier(node, state) {
1095
- let name = node.name;
1096
- state.commands.push(c(name, node));
1097
-
1098
- if (node.typeAnnotation) handle_type_annotation(node.typeAnnotation, state);
1099
- },
1100
-
1101
- IfStatement(node, state) {
1102
- state.commands.push('if (');
1103
- handle(node.test, state);
1104
- state.commands.push(') ');
1105
- handle(node.consequent, state);
1106
-
1107
- if (node.alternate) {
1108
- state.commands.push(' else ');
1109
- handle(node.alternate, state);
1110
- }
1111
- },
1112
-
1113
- ImportDeclaration(node, state) {
1114
- if (node.specifiers.length === 0) {
1115
- state.commands.push('import ');
1116
- handle(node.source, state);
1117
- state.commands.push(';');
1118
- return;
1119
- }
1120
-
1121
- /** @type {TSESTree.ImportNamespaceSpecifier | null} */
1122
- let namespace_specifier = null;
1123
-
1124
- /** @type {TSESTree.ImportDefaultSpecifier | null} */
1125
- let default_specifier = null;
1126
-
1127
- /** @type {TSESTree.ImportSpecifier[]} */
1128
- const named_specifiers = [];
1129
-
1130
- for (const s of node.specifiers) {
1131
- if (s.type === 'ImportNamespaceSpecifier') {
1132
- namespace_specifier = s;
1133
- } else if (s.type === 'ImportDefaultSpecifier') {
1134
- default_specifier = s;
1135
- } else {
1136
- named_specifiers.push(s);
1137
- }
1138
- }
1139
-
1140
- state.commands.push('import ');
1141
- if (node.importKind == 'type') state.commands.push('type ');
1142
-
1143
- if (default_specifier) {
1144
- state.commands.push(c(default_specifier.local.name, default_specifier));
1145
- if (namespace_specifier || named_specifiers.length > 0) state.commands.push(', ');
1146
- }
1147
-
1148
- if (namespace_specifier) {
1149
- state.commands.push(c('* as ' + namespace_specifier.local.name, namespace_specifier));
1150
- }
1151
-
1152
- if (named_specifiers.length > 0) {
1153
- state.commands.push('{');
1154
- sequence(named_specifiers, state, true, (s, state) => {
1155
- if (s.local.name !== s.imported.name) {
1156
- handle(s.imported, state);
1157
- state.commands.push(' as ');
1158
- }
1159
-
1160
- if (s.importKind == 'type') state.commands.push('type ');
1161
- handle(s.local, state);
1162
- });
1163
- state.commands.push('}');
1164
- }
1165
-
1166
- state.commands.push(' from ');
1167
- handle(node.source, state);
1168
- if (node.attributes && node.attributes.length > 0) {
1169
- state.commands.push(' with { ');
1170
- for (let index = 0; index < node.attributes.length; index++) {
1171
- const { key, value } = node.attributes[index];
1172
- handle(key, state);
1173
- state.commands.push(': ');
1174
- handle(value, state);
1175
- if (index + 1 !== node.attributes.length) {
1176
- state.commands.push(', ');
1177
- }
1178
- }
1179
- state.commands.push(' }');
1180
- }
1181
- state.commands.push(';');
1182
- },
1183
-
1184
- ImportExpression(node, state) {
1185
- state.commands.push('import(');
1186
- handle(node.source, state);
1187
- //@ts-expect-error for some reason the types haven't been updated
1188
- if (node.arguments) {
1189
- //@ts-expect-error
1190
- for (let index = 0; index < node.arguments.length; index++) {
1191
- state.commands.push(', ');
1192
- //@ts-expect-error
1193
- handle(node.arguments[index], state);
1194
- }
1195
- }
1196
- state.commands.push(')');
1197
- },
1198
-
1199
- LabeledStatement(node, state) {
1200
- handle(node.label, state);
1201
- state.commands.push(': ');
1202
- handle(node.body, state);
1203
- },
1204
-
1205
- Literal(node, state) {
1206
- // TODO do we need to handle weird unicode characters somehow?
1207
- // str.replace(/\\u(\d{4})/g, (m, n) => String.fromCharCode(+n))
1208
-
1209
- const value =
1210
- node.raw ||
1211
- (typeof node.value === 'string' ? quote(node.value, state.quote) : String(node.value));
1212
-
1213
- state.commands.push(c(value, node));
1214
- },
1215
-
1216
- LogicalExpression: shared['BinaryExpression|LogicalExpression'],
1217
-
1218
- MemberExpression(node, state) {
1219
- if (EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression) {
1220
- state.commands.push('(');
1221
- handle(node.object, state);
1222
- state.commands.push(')');
1223
- } else {
1224
- handle(node.object, state);
1225
- }
1226
-
1227
- if (node.computed) {
1228
- if (node.optional) {
1229
- state.commands.push('?.');
1230
- }
1231
- state.commands.push('[');
1232
- handle(node.property, state);
1233
- state.commands.push(']');
1234
- } else {
1235
- state.commands.push(node.optional ? '?.' : '.');
1236
- handle(node.property, state);
1237
- }
1238
- },
1239
-
1240
- MetaProperty(node, state) {
1241
- handle(node.meta, state);
1242
- state.commands.push('.');
1243
- handle(node.property, state);
1244
- },
1245
-
1246
- MethodDefinition(node, state) {
1247
- if (node.decorators) {
1248
- for (const decorator of node.decorators) {
1249
- handle(decorator, state);
1250
- }
1251
- }
1252
-
1253
- if (node.static) {
1254
- state.commands.push('static ');
1255
- }
1256
-
1257
- if (node.kind === 'get' || node.kind === 'set') {
1258
- // Getter or setter
1259
- state.commands.push(node.kind + ' ');
1260
- }
1261
-
1262
- if (node.value.async) {
1263
- state.commands.push('async ');
1264
- }
1265
-
1266
- if (node.value.generator) {
1267
- state.commands.push('*');
1268
- }
1269
-
1270
- if (node.computed) state.commands.push('[');
1271
- handle(node.key, state);
1272
- if (node.computed) state.commands.push(']');
1273
-
1274
- state.commands.push('(');
1275
- sequence(node.value.params, state, false, handle);
1276
- state.commands.push(') ');
1277
-
1278
- if (node.value.body) handle(node.value.body, state);
1279
- },
1280
-
1281
- NewExpression: shared['CallExpression|NewExpression'],
1282
-
1283
- ObjectExpression(node, state) {
1284
- state.commands.push('{');
1285
- sequence(node.properties, state, true, (p, state) => {
1286
- if (p.type === 'Property' && p.value.type === 'FunctionExpression') {
1287
- const fn = /** @type {TSESTree.FunctionExpression} */ (p.value);
1288
-
1289
- if (p.kind === 'get' || p.kind === 'set') {
1290
- state.commands.push(p.kind + ' ');
1291
- } else {
1292
- if (fn.async) state.commands.push('async ');
1293
- if (fn.generator) state.commands.push('*');
1294
- }
1295
-
1296
- if (p.computed) state.commands.push('[');
1297
- handle(p.key, state);
1298
- if (p.computed) state.commands.push(']');
1299
-
1300
- state.commands.push('(');
1301
- sequence(fn.params, state, false, handle);
1302
- state.commands.push(') ');
1303
-
1304
- handle(fn.body, state);
1305
- } else {
1306
- handle(p, state);
1307
- }
1308
- });
1309
- state.commands.push('}');
1310
- },
1311
-
1312
- ObjectPattern(node, state) {
1313
- state.commands.push('{');
1314
- sequence(node.properties, state, true, handle);
1315
- state.commands.push('}');
1316
-
1317
- if (node.typeAnnotation) handle_type_annotation(node.typeAnnotation, state);
1318
- },
1319
-
1320
- // @ts-expect-error this isn't a real node type, but Acorn produces it
1321
- ParenthesizedExpression(node, state) {
1322
- return handle(node.expression, state);
1323
- },
1324
-
1325
- PrivateIdentifier(node, state) {
1326
- state.commands.push('#', c(node.name, node));
1327
- },
1328
-
1329
- Program(node, state) {
1330
- handle_body(node.body, state);
1331
- },
1332
-
1333
- Property(node, state) {
1334
- const value = node.value.type === 'AssignmentPattern' ? node.value.left : node.value;
1335
-
1336
- const shorthand =
1337
- !node.computed &&
1338
- node.kind === 'init' &&
1339
- node.key.type === 'Identifier' &&
1340
- value.type === 'Identifier' &&
1341
- node.key.name === value.name;
1342
-
1343
- if (shorthand) {
1344
- handle(node.value, state);
1345
- return;
1346
- }
1347
-
1348
- if (node.computed) state.commands.push('[');
1349
- handle(node.key, state);
1350
- state.commands.push(node.computed ? ']: ' : ': ');
1351
- handle(node.value, state);
1352
- },
1353
-
1354
- PropertyDefinition(node, state) {
1355
- if (node.accessibility) {
1356
- state.commands.push(node.accessibility, ' ');
1357
- }
1358
-
1359
- if (node.static) {
1360
- state.commands.push('static ');
1361
- }
1362
-
1363
- if (node.computed) {
1364
- state.commands.push('[');
1365
- handle(node.key, state);
1366
- state.commands.push(']');
1367
- } else {
1368
- handle(node.key, state);
1369
- }
1370
-
1371
- if (node.typeAnnotation) {
1372
- state.commands.push(': ');
1373
- handle_type_annotation(node.typeAnnotation.typeAnnotation, state);
1374
- }
1375
-
1376
- if (node.value) {
1377
- state.commands.push(' = ');
1378
-
1379
- handle(node.value, state);
1380
- }
1381
-
1382
- state.commands.push(';');
1383
- },
1384
-
1385
- RestElement: shared['RestElement|SpreadElement'],
1386
-
1387
- ReturnStatement(node, state) {
1388
- if (node.argument) {
1389
- const argumentWithComment = /** @type {NodeWithComments} */ (node.argument);
1390
- const contains_comment =
1391
- argumentWithComment.leadingComments &&
1392
- argumentWithComment.leadingComments.some((comment) => comment.type === 'Line');
1393
-
1394
- state.commands.push(contains_comment ? 'return (' : 'return ');
1395
- handle(node.argument, state);
1396
- state.commands.push(contains_comment ? ');' : ';');
1397
- } else {
1398
- state.commands.push('return;');
1399
- }
1400
- },
1401
-
1402
- SequenceExpression(node, state) {
1403
- state.commands.push('(');
1404
- sequence(node.expressions, state, false, handle);
1405
- state.commands.push(')');
1406
- },
1407
-
1408
- SpreadElement: shared['RestElement|SpreadElement'],
1409
-
1410
- StaticBlock(node, state) {
1411
- state.commands.push(indent, 'static {', newline);
1412
-
1413
- handle_body(node.body, state);
1414
-
1415
- state.commands.push(dedent, newline, '}');
1416
- },
1417
-
1418
- Super(node, state) {
1419
- state.commands.push(c('super', node));
1420
- },
1421
-
1422
- SwitchStatement(node, state) {
1423
- state.commands.push('switch (');
1424
- handle(node.discriminant, state);
1425
- state.commands.push(') {', indent);
1426
-
1427
- let first = true;
1428
-
1429
- for (const block of node.cases) {
1430
- if (!first) state.commands.push('\n');
1431
- first = false;
1432
-
1433
- if (block.test) {
1434
- state.commands.push(newline, `case `);
1435
- handle(block.test, state);
1436
- state.commands.push(':');
1437
- } else {
1438
- state.commands.push(newline, `default:`);
1439
- }
1440
-
1441
- state.commands.push(indent);
1442
-
1443
- for (const statement of block.consequent) {
1444
- state.commands.push(newline);
1445
- handle(statement, state);
1446
- }
1447
-
1448
- state.commands.push(dedent);
1449
- }
1450
-
1451
- state.commands.push(dedent, newline, `}`);
1452
- },
1453
-
1454
- TaggedTemplateExpression(node, state) {
1455
- handle(node.tag, state);
1456
- handle(node.quasi, state);
1457
- },
1458
-
1459
- TemplateLiteral(node, state) {
1460
- state.commands.push('`');
1461
-
1462
- const { quasis, expressions } = node;
1463
-
1464
- for (let i = 0; i < expressions.length; i++) {
1465
- const raw = quasis[i].value.raw;
1466
-
1467
- state.commands.push(raw, '${');
1468
- handle(expressions[i], state);
1469
- state.commands.push('}');
1470
-
1471
- if (/\n/.test(raw)) state.multiline = true;
1472
- }
1473
-
1474
- const raw = quasis[quasis.length - 1].value.raw;
1475
-
1476
- state.commands.push(raw, '`');
1477
- if (/\n/.test(raw)) state.multiline = true;
1478
- },
1479
-
1480
- ThisExpression(node, state) {
1481
- state.commands.push(c('this', node));
1482
- },
1483
-
1484
- ThrowStatement(node, state) {
1485
- state.commands.push('throw ');
1486
- if (node.argument) handle(node.argument, state);
1487
- state.commands.push(';');
1488
- },
1489
-
1490
- TryStatement(node, state) {
1491
- state.commands.push('try ');
1492
- handle(node.block, state);
1493
-
1494
- if (node.handler) {
1495
- if (node.handler.param) {
1496
- state.commands.push(' catch(');
1497
- handle(node.handler.param, state);
1498
- state.commands.push(') ');
1499
- } else {
1500
- state.commands.push(' catch ');
1501
- }
1502
-
1503
- handle(node.handler.body, state);
1504
- }
1505
-
1506
- if (node.finalizer) {
1507
- state.commands.push(' finally ');
1508
- handle(node.finalizer, state);
1509
- }
1510
- },
1511
-
1512
- TSAsExpression(node, state) {
1513
- if (node.expression) {
1514
- const needs_parens =
1515
- EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSAsExpression;
1516
-
1517
- if (needs_parens) {
1518
- state.commands.push('(');
1519
- handle(node.expression, state);
1520
- state.commands.push(')');
1521
- } else {
1522
- handle(node.expression, state);
1523
- }
1524
- }
1525
- state.commands.push(' as ');
1526
- handle_type_annotation(node.typeAnnotation, state);
1527
- },
1528
-
1529
- TSEnumDeclaration(node, state) {
1530
- state.commands.push('enum ');
1531
- handle(node.id, state);
1532
- state.commands.push(' {', indent, newline);
1533
- sequence(node.members, state, false, handle_type_annotation);
1534
- state.commands.push(dedent, newline, '}', newline);
1535
- },
1536
-
1537
- TSModuleBlock(node, state) {
1538
- state.commands.push(' {', indent, newline);
1539
- handle_body(node.body, state);
1540
- state.commands.push(dedent, newline, '}');
1541
- },
1542
-
1543
- TSModuleDeclaration(node, state) {
1544
- if (node.declare) state.commands.push('declare ');
1545
- else state.commands.push('namespace ');
1546
-
1547
- handle(node.id, state);
1548
-
1549
- if (!node.body) return;
1550
- handle(node.body, state);
1551
- },
1552
-
1553
- TSNonNullExpression(node, state) {
1554
- handle(node.expression, state);
1555
- state.commands.push('!');
1556
- },
1557
-
1558
- TSInterfaceBody(node, state) {
1559
- sequence(node.body, state, true, handle_type_annotation, ';');
1560
- },
1561
-
1562
- TSInterfaceDeclaration(node, state) {
1563
- state.commands.push('interface ');
1564
- handle(node.id, state);
1565
- if (node.typeParameters) handle_type_annotation(node.typeParameters, state);
1566
- if (node.extends) {
1567
- state.commands.push(' extends ');
1568
- sequence(node.extends, state, false, handle_type_annotation);
1569
- }
1570
- state.commands.push(' {');
1571
- handle(node.body, state);
1572
- state.commands.push('}');
1573
- },
1574
-
1575
- TSSatisfiesExpression(node, state) {
1576
- if (node.expression) {
1577
- const needs_parens =
1578
- EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSSatisfiesExpression;
1579
-
1580
- if (needs_parens) {
1581
- state.commands.push('(');
1582
- handle(node.expression, state);
1583
- state.commands.push(')');
1584
- } else {
1585
- handle(node.expression, state);
1586
- }
1587
- }
1588
- state.commands.push(' satisfies ');
1589
- handle_type_annotation(node.typeAnnotation, state);
1590
- },
1591
-
1592
- TSTypeAliasDeclaration(node, state) {
1593
- state.commands.push('type ');
1594
- handle(node.id, state);
1595
- if (node.typeParameters) handle_type_annotation(node.typeParameters, state);
1596
- state.commands.push(' = ');
1597
- handle_type_annotation(node.typeAnnotation, state);
1598
- state.commands.push(';');
1599
- },
1600
-
1601
- TSQualifiedName(node, state) {
1602
- handle(node.left, state);
1603
- state.commands.push('.');
1604
- handle(node.right, state);
1605
- },
1606
-
1607
- UnaryExpression(node, state) {
1608
- state.commands.push(node.operator);
1609
-
1610
- if (node.operator.length > 1) {
1611
- state.commands.push(' ');
1612
- }
1613
-
1614
- if (EXPRESSIONS_PRECEDENCE[node.argument.type] < EXPRESSIONS_PRECEDENCE.UnaryExpression) {
1615
- state.commands.push('(');
1616
- handle(node.argument, state);
1617
- state.commands.push(')');
1618
- } else {
1619
- handle(node.argument, state);
1620
- }
1621
- },
1622
-
1623
- UpdateExpression(node, state) {
1624
- if (node.prefix) {
1625
- state.commands.push(node.operator);
1626
- handle(node.argument, state);
1627
- } else {
1628
- handle(node.argument, state);
1629
- state.commands.push(node.operator);
1630
- }
1631
- },
1632
-
1633
- VariableDeclaration(node, state) {
1634
- handle_var_declaration(node, state);
1635
- state.commands.push(';');
1636
- },
1637
-
1638
- VariableDeclarator(node, state) {
1639
- handle(node.id, state);
1640
-
1641
- if (node.init) {
1642
- state.commands.push(' = ');
1643
- handle(node.init, state);
1644
- }
1645
- },
1646
-
1647
- WhileStatement(node, state) {
1648
- state.commands.push('while (');
1649
- handle(node.test, state);
1650
- state.commands.push(') ');
1651
- handle(node.body, state);
1652
- },
1653
-
1654
- WithStatement(node, state) {
1655
- state.commands.push('with (');
1656
- handle(node.object, state);
1657
- state.commands.push(') ');
1658
- handle(node.body, state);
1659
- },
1660
-
1661
- YieldExpression(node, state) {
1662
- if (node.argument) {
1663
- state.commands.push(node.delegate ? `yield* ` : `yield `);
1664
- handle(node.argument, state);
1665
- } else {
1666
- state.commands.push(node.delegate ? `yield*` : `yield`);
1667
- }
1668
- }
1669
- };