flow-api-translator 0.20.0 → 0.21.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.
@@ -0,0 +1,1812 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @format
9
+ */
10
+ 'use strict';
11
+
12
+ Object.defineProperty(exports, "__esModule", {
13
+ value: true
14
+ });
15
+ exports.TSDefToFlowDef = TSDefToFlowDef;
16
+
17
+ var FlowESTree = _interopRequireWildcard(require("hermes-estree"));
18
+
19
+ var TSESTree = _interopRequireWildcard(require("./utils/ts-estree-ast-types"));
20
+
21
+ var _hermesTransform = require("hermes-transform");
22
+
23
+ var _ErrorUtils = require("./utils/ErrorUtils");
24
+
25
+ var _os = require("os");
26
+
27
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
28
+
29
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
30
+
31
+ const DUMMY_LOC = null;
32
+ const DUMMY_RANGE = [0, 0];
33
+ const DUMMY_PARENT = null;
34
+ const DUMMY_COMMON = {
35
+ loc: DUMMY_LOC,
36
+ range: DUMMY_RANGE,
37
+ parent: DUMMY_PARENT
38
+ };
39
+
40
+ function constructFlowNode(node) {
41
+ return { ...node,
42
+ ...DUMMY_COMMON
43
+ };
44
+ }
45
+
46
+ const makeCommentOwnLine = // $FlowExpectedError[incompatible-cast] - trust me this re-type is 100% safe
47
+ _hermesTransform.makeCommentOwnLine;
48
+
49
+ function TSDefToFlowDef(originalCode, ast, opts) {
50
+ const flowBody = [];
51
+ const flowProgram = { ...DUMMY_COMMON,
52
+ type: 'Program',
53
+ body: flowBody,
54
+ comments: [],
55
+ sourceType: ast.sourceType,
56
+ interpreter: null,
57
+ tokens: [],
58
+ loc: ast.loc,
59
+ docblock: {
60
+ comment: { ...DUMMY_COMMON,
61
+ type: 'Block',
62
+ value: ''
63
+ },
64
+ directives: {
65
+ flow: []
66
+ }
67
+ }
68
+ };
69
+ const [transform, code] = getTransforms(originalCode, opts);
70
+
71
+ for (const node of ast.body) {
72
+ const result = transform.AllStatement(node);
73
+ flowBody.push(...(Array.isArray(result) ? result : [result]));
74
+ }
75
+
76
+ return [flowProgram, code];
77
+ } // Note: The implementation here is still in early stage. If something is not supported, it doesn't
78
+ // necessarily mean that it cannot be. It might just mean that it's not priortized yet. If something
79
+ // is translated in way that is wrong, then it's likely wrong.
80
+
81
+
82
+ const getTransforms = (originalCode, opts) => {
83
+ let code = originalCode;
84
+
85
+ function translationError(node, message) {
86
+ return (0, _ErrorUtils.translationError)(node, message, {
87
+ code
88
+ });
89
+ }
90
+
91
+ function unexpectedTranslationError(node, message) {
92
+ return (0, _ErrorUtils.unexpectedTranslationError)(node, message, {
93
+ code
94
+ });
95
+ }
96
+
97
+ function unsupportedFeatureMessage(thing) {
98
+ return `Unsupported feature: Translating "${thing}" is currently not supported.`;
99
+ }
100
+
101
+ function buildCodeFrameForComment(node, message) {
102
+ return (0, _ErrorUtils.buildCodeFrame)(node, message, code, false);
103
+ }
104
+
105
+ function addErrorComment(node, message) {
106
+ var _node$comments;
107
+
108
+ const comment = {
109
+ type: 'Block',
110
+ loc: DUMMY_LOC,
111
+ value: `*${_os.EOL} * ${message.replace(new RegExp(_os.EOL, 'g'), `${_os.EOL} * `)}${_os.EOL}*`,
112
+ leading: true,
113
+ printed: false
114
+ };
115
+ code = makeCommentOwnLine(code, comment); // $FlowExpectedError[prop-missing]
116
+ // $FlowExpectedError[cannot-write]
117
+
118
+ (_node$comments = node.comments) != null ? _node$comments : node.comments = []; // $FlowExpectedError[incompatible-cast]
119
+
120
+ node.comments.push(comment);
121
+ }
122
+
123
+ function unsupportedAnnotation(node, thing) {
124
+ const message = unsupportedFeatureMessage(thing);
125
+
126
+ if (opts.recoverFromErrors) {
127
+ const codeFrame = buildCodeFrameForComment(node, message);
128
+ const newNode = { ...DUMMY_COMMON,
129
+ type: 'AnyTypeAnnotation'
130
+ };
131
+ addErrorComment(newNode, codeFrame);
132
+ return newNode;
133
+ }
134
+
135
+ throw translationError(node, message);
136
+ }
137
+
138
+ function unsupportedDeclaration(node, thing, id, typeParameters = null) {
139
+ const message = unsupportedFeatureMessage(thing);
140
+
141
+ if (opts.recoverFromErrors) {
142
+ const codeFrame = buildCodeFrameForComment(node, message);
143
+ const newNode = { ...DUMMY_COMMON,
144
+ type: 'TypeAlias',
145
+ id: Transform.Identifier(id, false),
146
+ right: { ...DUMMY_COMMON,
147
+ type: 'AnyTypeAnnotation'
148
+ },
149
+ typeParameters: Transform.TSTypeParameterDeclarationOpt(typeParameters)
150
+ };
151
+ addErrorComment(newNode, codeFrame);
152
+ return newNode;
153
+ }
154
+
155
+ throw translationError(node, message);
156
+ }
157
+
158
+ class Transform {
159
+ static BlockStatement(node) {
160
+ return constructFlowNode({
161
+ type: 'BlockStatement',
162
+ body: node.body.flatMap(node => Transform.Statement(node))
163
+ });
164
+ }
165
+
166
+ static ClassDeclarationWithName(node) {
167
+ return constructFlowNode({
168
+ type: 'DeclareClass',
169
+ id: Transform.Identifier(node.id),
170
+ typeParameters: Transform.TSTypeParameterDeclarationOpt(node.typeParameters),
171
+ implements: (node.implements || []).map(impl => Transform.ClassImplements(impl)),
172
+ extends: Transform.ClassDeclarationSuperClass(node.superClass, node.superTypeParameters),
173
+ mixins: [],
174
+ body: Transform.ClassDeclarationBody(node.body)
175
+ });
176
+ }
177
+
178
+ static ClassDeclarationBody({
179
+ body
180
+ }) {
181
+ const properties = [];
182
+ const indexers = [];
183
+
184
+ for (const classItem of body) {
185
+ switch (classItem.type) {
186
+ case 'StaticBlock':
187
+ break;
188
+
189
+ case 'TSIndexSignature':
190
+ break;
191
+
192
+ case 'TSAbstractPropertyDefinition':
193
+ case 'PropertyDefinition':
194
+ // $FlowFixMe[incompatible-call] ambiguous node
195
+ Transform._translateIntoObjectProp(classItem, properties, indexers);
196
+
197
+ break;
198
+
199
+ case 'MethodDefinition':
200
+ case 'TSAbstractMethodDefinition':
201
+ // $FlowFixMe[incompatible-call] ambiguous node
202
+ Transform._translateIntoObjectMethod(classItem, properties);
203
+
204
+ break;
205
+ }
206
+ }
207
+
208
+ return constructFlowNode({
209
+ type: 'ObjectTypeAnnotation',
210
+ properties,
211
+ indexers,
212
+ callProperties: [],
213
+ internalSlots: [],
214
+ exact: false,
215
+ inexact: false
216
+ });
217
+ }
218
+
219
+ static ClassDeclarationSuperClass(superClass, superTypeParameters) {
220
+ if (superClass == null) {
221
+ return [];
222
+ }
223
+
224
+ const id = Transform._expressionToIdOrQualifiedTypeId(superClass, 'superClass');
225
+
226
+ return [constructFlowNode({
227
+ type: 'InterfaceExtends',
228
+ id,
229
+ typeParameters: Transform.TSTypeParameterInstantiationOpt(superTypeParameters)
230
+ })];
231
+ }
232
+
233
+ static ClassImplements(node) {
234
+ if (node.expression.type !== 'Identifier') {
235
+ throw unexpectedTranslationError(node, 'Expected expression to be an Identifier');
236
+ }
237
+
238
+ return constructFlowNode({
239
+ type: 'ClassImplements',
240
+ id: Transform.Identifier(node.expression),
241
+ typeParameters: Transform.TSTypeParameterInstantiationOpt(node.typeParameters)
242
+ });
243
+ }
244
+
245
+ static DebuggerStatement() {
246
+ return constructFlowNode({
247
+ type: 'DebuggerStatement'
248
+ });
249
+ }
250
+
251
+ static EntityNameToTypeIdentifier(node) {
252
+ switch (node.type) {
253
+ case 'Identifier':
254
+ return Transform.Identifier(node);
255
+
256
+ case 'TSQualifiedName':
257
+ return Transform.TSQualifiedNameToQualifiedTypeIdentifier(node);
258
+
259
+ case 'ThisExpression':
260
+ return constructFlowNode({
261
+ type: 'Identifier',
262
+ name: 'this',
263
+ typeAnnotation: null,
264
+ optional: false
265
+ });
266
+ }
267
+ }
268
+
269
+ static EntityNameToTypeofIdentifier(node) {
270
+ switch (node.type) {
271
+ case 'Identifier':
272
+ return Transform.Identifier(node);
273
+
274
+ case 'TSQualifiedName':
275
+ return Transform.TSQualifiedNameToQualifiedTypeofIdentifier(node);
276
+
277
+ case 'ThisExpression':
278
+ return constructFlowNode({
279
+ type: 'Identifier',
280
+ name: 'this',
281
+ typeAnnotation: null,
282
+ optional: false
283
+ });
284
+ }
285
+ }
286
+
287
+ static ExportAllDeclaration(node) {
288
+ return constructFlowNode({
289
+ type: 'ExportAllDeclaration',
290
+ source: constructFlowNode({
291
+ type: 'Literal',
292
+ literalType: 'string',
293
+ value: node.source.value,
294
+ raw: node.source.raw
295
+ }),
296
+ assertions: [],
297
+ exportKind: node.exportKind,
298
+ exported: node.exported != null ? Transform.Identifier(node.exported) : null
299
+ });
300
+ }
301
+
302
+ static ExportDefaultDeclaration(node) {
303
+ let declaration;
304
+
305
+ switch (node.declaration.type) {
306
+ case 'ClassDeclaration':
307
+ declaration = Transform.ClassDeclarationWithName( // possibly missing id
308
+ node.declaration);
309
+ break;
310
+
311
+ case 'FunctionDeclaration':
312
+ declaration = Transform.FunctionDeclarationWithName( // possibly missing id
313
+ node.declaration);
314
+ break;
315
+
316
+ case 'TSDeclareFunction':
317
+ declaration = Transform.TSDeclareFunction(node.declaration);
318
+ break;
319
+
320
+ case 'Identifier':
321
+ declaration = constructFlowNode({
322
+ type: 'TypeofTypeAnnotation',
323
+ argument: Transform.Identifier(node.declaration)
324
+ });
325
+ break;
326
+
327
+ default:
328
+ throw translationError(node.declaration, `Unsupported export declaration: ${node.declaration.type}`);
329
+ }
330
+
331
+ return constructFlowNode({
332
+ type: 'DeclareExportDeclaration',
333
+ declaration,
334
+ default: true,
335
+ source: null,
336
+ specifiers: []
337
+ });
338
+ }
339
+
340
+ static ExportNamedDeclaration(node) {
341
+ if (node.declaration == null) {
342
+ const source = node.source == null ? null : constructFlowNode({
343
+ type: 'Literal',
344
+ literalType: 'string',
345
+ value: node.source.value,
346
+ raw: node.source.raw
347
+ });
348
+ const specifiers = node.specifiers.map(specifier => constructFlowNode({
349
+ type: 'ExportSpecifier',
350
+ local: Transform.Identifier(specifier.local),
351
+ exported: Transform.Identifier(specifier.exported)
352
+ }));
353
+ return constructFlowNode({
354
+ type: 'DeclareExportDeclaration',
355
+ declaration: null,
356
+ default: false,
357
+ source,
358
+ specifiers
359
+ });
360
+ }
361
+
362
+ switch (node.declaration.type) {
363
+ case 'ClassDeclaration':
364
+ return constructFlowNode({
365
+ type: 'DeclareExportDeclaration',
366
+ declaration: Transform.ClassDeclarationWithName( // possibly missing id
367
+ node.declaration),
368
+ default: false,
369
+ source: null,
370
+ specifiers: []
371
+ });
372
+
373
+ case 'FunctionDeclaration':
374
+ return constructFlowNode({
375
+ type: 'DeclareExportDeclaration',
376
+ declaration: Transform.FunctionDeclarationWithName( // possibly missing id
377
+ node.declaration),
378
+ default: false,
379
+ source: null,
380
+ specifiers: []
381
+ });
382
+
383
+ case 'TSDeclareFunction':
384
+ return constructFlowNode({
385
+ type: 'DeclareExportDeclaration',
386
+ declaration: Transform.TSDeclareFunction(node.declaration),
387
+ default: false,
388
+ source: null,
389
+ specifiers: []
390
+ });
391
+
392
+ case 'TSEnumDeclaration':
393
+ throw translationError(node.declaration, `Unsupported export declaration: ${node.declaration.type}`);
394
+
395
+ case 'TSModuleDeclaration':
396
+ {
397
+ const decl = Transform.TSModuleDeclaration(node.declaration);
398
+
399
+ if (decl.id.type !== 'Identifier') {
400
+ throw translationError(decl.id, `Unsupported module declaration id`);
401
+ }
402
+
403
+ return [decl, constructFlowNode({
404
+ type: 'ExportNamedDeclaration',
405
+ declaration: null,
406
+ source: null,
407
+ exportKind: 'value',
408
+ specifiers: [constructFlowNode({
409
+ type: 'ExportSpecifier',
410
+ local: decl.id,
411
+ exported: decl.id
412
+ })]
413
+ })];
414
+ }
415
+
416
+ case 'TSInterfaceDeclaration':
417
+ {
418
+ const decl = Transform.TSInterfaceDeclaration(node.declaration);
419
+ return constructFlowNode({
420
+ type: 'DeclareExportDeclaration',
421
+ declaration: constructFlowNode({
422
+ type: 'DeclareInterface',
423
+ id: decl.id,
424
+ typeParameters: decl.typeParameters,
425
+ body: decl.body,
426
+ extends: decl.extends
427
+ }),
428
+ default: false,
429
+ source: null,
430
+ specifiers: []
431
+ });
432
+ }
433
+
434
+ case 'TSTypeAliasDeclaration':
435
+ {
436
+ const decl = Transform.TSTypeAliasDeclaration(node.declaration);
437
+ return constructFlowNode({
438
+ type: 'ExportNamedDeclaration',
439
+ declaration: decl,
440
+ source: null,
441
+ exportKind: 'type',
442
+ specifiers: []
443
+ });
444
+ }
445
+
446
+ case 'VariableDeclaration':
447
+ {
448
+ return Transform.VariableDeclaration(node.declaration).map(declaration => constructFlowNode({
449
+ type: 'DeclareExportDeclaration',
450
+ declaration,
451
+ default: false,
452
+ source: null,
453
+ specifiers: []
454
+ }));
455
+ }
456
+ }
457
+ }
458
+
459
+ static FunctionDeclarationWithName(node) {
460
+ var _node$returnType;
461
+
462
+ const {
463
+ thisParam,
464
+ restParam,
465
+ params
466
+ } = Transform._partitionAndTranslateTSFunctionParams(node.params);
467
+
468
+ const fnAnnot = constructFlowNode({
469
+ type: 'FunctionTypeAnnotation',
470
+ typeParameters: Transform.TSTypeParameterDeclarationOpt(node.typeParameters),
471
+ params,
472
+ rest: restParam,
473
+ returnType: ((_node$returnType = node.returnType) == null ? void 0 : _node$returnType.typeAnnotation) == null ? unsupportedAnnotation(node, 'missing return type') : Transform.TSTypeAnnotation(node.returnType.typeAnnotation),
474
+ this: thisParam
475
+ });
476
+ return constructFlowNode({
477
+ type: 'DeclareFunction',
478
+ id: { ...DUMMY_COMMON,
479
+ type: 'Identifier',
480
+ name: node.id.name,
481
+ typeAnnotation: { ...DUMMY_COMMON,
482
+ type: 'TypeAnnotation',
483
+ typeAnnotation: fnAnnot
484
+ },
485
+ optional: false
486
+ },
487
+ predicate: null
488
+ });
489
+ }
490
+
491
+ static Identifier(node, optional) {
492
+ return constructFlowNode({
493
+ type: 'Identifier',
494
+ name: node.name,
495
+ typeAnnotation: node.typeAnnotation != null ? Transform.TSTypeAnnotationNode(node.typeAnnotation) : null,
496
+ optional: Boolean(optional != null ? optional : node.optional)
497
+ });
498
+ }
499
+
500
+ static ImportDeclaration(node) {
501
+ const specifiers = node.specifiers.map(specifier => {
502
+ var _specifier$importKind;
503
+
504
+ switch (specifier.type) {
505
+ case 'ImportNamespaceSpecifier':
506
+ return constructFlowNode({
507
+ type: 'ImportNamespaceSpecifier',
508
+ local: Transform.Identifier(specifier.local)
509
+ });
510
+
511
+ case 'ImportDefaultSpecifier':
512
+ return constructFlowNode({
513
+ type: 'ImportDefaultSpecifier',
514
+ local: Transform.Identifier(specifier.local)
515
+ });
516
+
517
+ case 'ImportSpecifier':
518
+ return constructFlowNode({
519
+ type: 'ImportSpecifier',
520
+ local: Transform.Identifier(specifier.local),
521
+ imported: Transform.Identifier(specifier.imported),
522
+ importKind: specifier.importKind === 'value' ? null : (_specifier$importKind = specifier.importKind) != null ? _specifier$importKind : null
523
+ });
524
+ }
525
+ });
526
+ return constructFlowNode({
527
+ type: 'ImportDeclaration',
528
+ source: constructFlowNode({
529
+ type: 'Literal',
530
+ literalType: 'string',
531
+ value: node.source.value,
532
+ raw: node.source.raw
533
+ }),
534
+ importKind: // `import type React from 'react'` in TS means `import typeof React from react` in Flow
535
+ specifiers.some(s => s.type === 'ImportDefaultSpecifier') && node.importKind === 'type' ? 'typeof' : node.importKind,
536
+ assertions: [],
537
+ specifiers
538
+ });
539
+ }
540
+
541
+ static LabeledStatement(node) {
542
+ const body = Transform.Statement(node.body);
543
+
544
+ if (Array.isArray(body)) {
545
+ throw translationError(node.body, 'Unexpected array of statements');
546
+ }
547
+
548
+ return constructFlowNode({
549
+ type: 'LabeledStatement',
550
+ label: Transform.Identifier(node.label),
551
+ body
552
+ });
553
+ }
554
+
555
+ static Literal(node) {
556
+ if (typeof node.value === 'number') {
557
+ return constructFlowNode({
558
+ type: 'Literal',
559
+ literalType: 'numeric',
560
+ value: Number(node.raw),
561
+ raw: node.raw
562
+ });
563
+ } else if (typeof node.value === 'string') {
564
+ return constructFlowNode({
565
+ type: 'Literal',
566
+ literalType: 'string',
567
+ value: node.value,
568
+ raw: node.raw
569
+ });
570
+ } else if (typeof node.value === 'boolean') {
571
+ return constructFlowNode({
572
+ type: 'Literal',
573
+ literalType: 'boolean',
574
+ value: node.value,
575
+ raw: node.value ? 'true' : 'false'
576
+ });
577
+ } else if (typeof node.value === 'bigint') {
578
+ return constructFlowNode({
579
+ type: 'Literal',
580
+ literalType: 'bigint',
581
+ value: node.value,
582
+ raw: node.raw,
583
+ bigint: node.raw
584
+ });
585
+ } else if (node.value instanceof RegExp) {
586
+ return constructFlowNode({
587
+ type: 'Literal',
588
+ literalType: 'regexp',
589
+ value: node.value,
590
+ regex: null,
591
+ raw: node.raw
592
+ });
593
+ } else if (node.value == null) {
594
+ return constructFlowNode({
595
+ type: 'Literal',
596
+ literalType: 'null',
597
+ value: node.value,
598
+ raw: 'null'
599
+ });
600
+ } else {
601
+ throw translationError(node, `Unsupported literal type ${typeof node.value}`);
602
+ }
603
+ }
604
+
605
+ static LiteralType(node) {
606
+ const literal = Transform.Literal(node);
607
+
608
+ switch (literal.literalType) {
609
+ case 'boolean':
610
+ return constructFlowNode({
611
+ type: 'BooleanLiteralTypeAnnotation',
612
+ value: literal.value,
613
+ raw: literal.raw
614
+ });
615
+
616
+ case 'numeric':
617
+ return constructFlowNode({
618
+ type: 'NumberLiteralTypeAnnotation',
619
+ value: literal.value,
620
+ raw: literal.raw
621
+ });
622
+
623
+ case 'string':
624
+ return constructFlowNode({
625
+ type: 'StringLiteralTypeAnnotation',
626
+ value: literal.value,
627
+ raw: literal.raw
628
+ });
629
+
630
+ case 'bigint':
631
+ return constructFlowNode({
632
+ type: 'BigIntLiteralTypeAnnotation',
633
+ value: literal.value,
634
+ bigint: literal.bigint,
635
+ raw: literal.raw
636
+ });
637
+
638
+ case 'null':
639
+ return constructFlowNode({
640
+ type: 'NullLiteralTypeAnnotation',
641
+ value: literal.value,
642
+ raw: literal.raw
643
+ });
644
+
645
+ case 'regexp':
646
+ return unsupportedAnnotation(node, 'regexp literal type');
647
+
648
+ default:
649
+ literal;
650
+ throw 'unreachable';
651
+ }
652
+ }
653
+
654
+ static AllStatement(node) {
655
+ switch (node.type) {
656
+ case 'BlockStatement':
657
+ return Transform.BlockStatement(node);
658
+
659
+ case 'ClassDeclaration':
660
+ return Transform.ClassDeclarationWithName(node);
661
+
662
+ case 'DebuggerStatement':
663
+ return Transform.DebuggerStatement();
664
+
665
+ case 'ExportAllDeclaration':
666
+ return Transform.ExportAllDeclaration(node);
667
+
668
+ case 'ExportDefaultDeclaration':
669
+ return Transform.ExportDefaultDeclaration(node);
670
+
671
+ case 'ExportNamedDeclaration':
672
+ return Transform.ExportNamedDeclaration(node);
673
+
674
+ case 'FunctionDeclaration':
675
+ return Transform.FunctionDeclarationWithName(node);
676
+
677
+ case 'ImportDeclaration':
678
+ return Transform.ImportDeclaration(node);
679
+
680
+ case 'LabeledStatement':
681
+ return Transform.LabeledStatement(node);
682
+
683
+ case 'TSDeclareFunction':
684
+ return Transform.TSDeclareFunction(node);
685
+
686
+ case 'TSEnumDeclaration':
687
+ return Transform.TSEnumDeclaration(node);
688
+
689
+ case 'TSExportAssignment':
690
+ return Transform.TSExportAssignment(node);
691
+
692
+ case 'TSImportEqualsDeclaration':
693
+ return Transform.TSImportEqualsDeclaration(node);
694
+
695
+ case 'TSInterfaceDeclaration':
696
+ return Transform.TSInterfaceDeclaration(node);
697
+
698
+ case 'TSModuleDeclaration':
699
+ return Transform.TSModuleDeclaration(node);
700
+
701
+ case 'TSNamespaceExportDeclaration':
702
+ // Flow will never support `export as namespace` since we can't allow a normal file to
703
+ // introduce a global out of nowhere, and because it's only useful for legacy module
704
+ // system However, it's very reasonable to completely ignore it under some mode, so that
705
+ // people using these libdefs won't have a lot of pain.
706
+ return [];
707
+
708
+ case 'TSTypeAliasDeclaration':
709
+ return Transform.TSTypeAliasDeclaration(node);
710
+
711
+ case 'VariableDeclaration':
712
+ return Transform.VariableDeclaration(node);
713
+
714
+ case 'ExpressionStatement':
715
+ throw translationError(node, 'Unsupported expression statement');
716
+
717
+ case 'WithStatement':
718
+ throw translationError(node, 'Unsupported with statement');
719
+
720
+ case 'BreakStatement':
721
+ case 'ContinueStatement':
722
+ case 'DoWhileStatement':
723
+ case 'ForInStatement':
724
+ case 'ForOfStatement':
725
+ case 'ForStatement':
726
+ case 'IfStatement':
727
+ case 'ReturnStatement':
728
+ case 'SwitchStatement':
729
+ case 'ThrowStatement':
730
+ case 'TryStatement':
731
+ case 'WhileStatement':
732
+ throw translationError(node, 'Unsupported control flow statement');
733
+ }
734
+ }
735
+
736
+ static Statement(node) {
737
+ return Transform.AllStatement(node);
738
+ }
739
+
740
+ static TSAnyType() {
741
+ return constructFlowNode({
742
+ type: 'AnyTypeAnnotation'
743
+ });
744
+ }
745
+
746
+ static TSArrayType(node) {
747
+ return constructFlowNode({
748
+ type: 'ArrayTypeAnnotation',
749
+ elementType: Transform.TSTypeAnnotation(node.elementType)
750
+ });
751
+ }
752
+
753
+ static TSBigIntType() {
754
+ return constructFlowNode({
755
+ type: 'BigIntTypeAnnotation'
756
+ });
757
+ }
758
+
759
+ static TSBooleanType() {
760
+ return constructFlowNode({
761
+ type: 'BooleanTypeAnnotation'
762
+ });
763
+ }
764
+
765
+ static TSConditionalType(node) {
766
+ return constructFlowNode({
767
+ type: 'ConditionalTypeAnnotation',
768
+ checkType: Transform.TSTypeAnnotation(node.checkType),
769
+ extendsType: Transform.TSTypeAnnotation(node.extendsType),
770
+ trueType: Transform.TSTypeAnnotation(node.trueType),
771
+ falseType: Transform.TSTypeAnnotation(node.falseType)
772
+ });
773
+ }
774
+
775
+ static TSConstructorType(node) {
776
+ return unsupportedAnnotation(node, 'constructor types');
777
+ }
778
+
779
+ static TSDeclareFunction(node) {
780
+ var _node$returnType2;
781
+
782
+ if (node.id == null) {
783
+ throw translationError(node, 'Missing function name');
784
+ }
785
+
786
+ const name = node.id.name;
787
+
788
+ const {
789
+ thisParam,
790
+ restParam,
791
+ params
792
+ } = Transform._partitionAndTranslateTSFunctionParams(node.params);
793
+
794
+ const fnAnnot = constructFlowNode({
795
+ type: 'FunctionTypeAnnotation',
796
+ typeParameters: Transform.TSTypeParameterDeclarationOpt(node.typeParameters),
797
+ params,
798
+ rest: restParam,
799
+ returnType: ((_node$returnType2 = node.returnType) == null ? void 0 : _node$returnType2.typeAnnotation) == null ? unsupportedAnnotation(node, 'missing return type') : Transform.TSTypeAnnotation(node.returnType.typeAnnotation),
800
+ this: thisParam
801
+ });
802
+ return constructFlowNode({
803
+ type: 'DeclareFunction',
804
+ id: { ...DUMMY_COMMON,
805
+ type: 'Identifier',
806
+ name,
807
+ typeAnnotation: { ...DUMMY_COMMON,
808
+ type: 'TypeAnnotation',
809
+ typeAnnotation: fnAnnot
810
+ },
811
+ optional: false
812
+ },
813
+ predicate: null
814
+ });
815
+ }
816
+
817
+ static TSEnumDeclaration(node) {
818
+ return unsupportedDeclaration(node, 'enums', node.id);
819
+ }
820
+
821
+ static TSExportAssignment(node) {
822
+ let typeAnnotation;
823
+
824
+ if (node.expression.type === 'Identifier') {
825
+ typeAnnotation = constructFlowNode({
826
+ type: 'TypeofTypeAnnotation',
827
+ argument: Transform.Identifier(node.expression)
828
+ });
829
+ } else if (node.expression.type === 'Literal') {
830
+ typeAnnotation = Transform.LiteralType(node.expression);
831
+ } else {
832
+ throw translationError(node, `Unsupported export assignment expression ${node.expression.type}`);
833
+ }
834
+
835
+ return constructFlowNode({
836
+ type: 'DeclareModuleExports',
837
+ typeAnnotation: constructFlowNode({
838
+ type: 'TypeAnnotation',
839
+ typeAnnotation
840
+ })
841
+ });
842
+ }
843
+
844
+ static TSFunctionType(node, allowMissingReturn = false) {
845
+ var _node$returnType3;
846
+
847
+ const {
848
+ thisParam,
849
+ restParam,
850
+ params
851
+ } = Transform._partitionAndTranslateTSFunctionParams(node.params);
852
+
853
+ return constructFlowNode({
854
+ type: 'FunctionTypeAnnotation',
855
+ typeParameters: Transform.TSTypeParameterDeclarationOpt(node.typeParameters),
856
+ params: params,
857
+ rest: restParam,
858
+ returnType: ((_node$returnType3 = node.returnType) == null ? void 0 : _node$returnType3.typeAnnotation) == null ? allowMissingReturn ? constructFlowNode({
859
+ type: 'VoidTypeAnnotation'
860
+ }) : unsupportedAnnotation(node, 'missing return type') : Transform.TSTypeAnnotation(node.returnType.typeAnnotation),
861
+ this: thisParam
862
+ });
863
+ }
864
+
865
+ static _partitionAndTranslateTSFunctionParams(tsParams) {
866
+ const params = [...tsParams];
867
+ const firstParam = params[0];
868
+ let thisParam = null;
869
+ let restParam = null;
870
+
871
+ if (firstParam != null && firstParam.type === 'Identifier' && firstParam.name === 'this') {
872
+ var _firstParam$typeAnnot;
873
+
874
+ thisParam = constructFlowNode({
875
+ type: 'FunctionTypeParam',
876
+ name: constructFlowNode({
877
+ type: 'Identifier',
878
+ name: 'this',
879
+ optional: false,
880
+ typeAnnotation: null
881
+ }),
882
+ optional: false,
883
+ typeAnnotation: Transform.TSTypeAnnotationOpt((_firstParam$typeAnnot = firstParam.typeAnnotation) == null ? void 0 : _firstParam$typeAnnot.typeAnnotation)
884
+ });
885
+ params.shift();
886
+ }
887
+
888
+ const lastParam = params[params.length - 1];
889
+
890
+ if (lastParam != null && lastParam.type === 'RestElement') {
891
+ var _lastParam$typeAnnota;
892
+
893
+ restParam = constructFlowNode({
894
+ type: 'FunctionTypeParam',
895
+ name: constructFlowNode({
896
+ type: 'Identifier',
897
+ name: '$$rest$$',
898
+ optional: false,
899
+ typeAnnotation: null
900
+ }),
901
+ optional: false,
902
+ typeAnnotation: Transform.TSTypeAnnotationOpt((_lastParam$typeAnnota = lastParam.typeAnnotation) == null ? void 0 : _lastParam$typeAnnota.typeAnnotation)
903
+ });
904
+ params.pop();
905
+ }
906
+
907
+ return {
908
+ thisParam,
909
+ restParam,
910
+ params: params.map((param, i) => {
911
+ if (param.type === 'Identifier') {
912
+ var _param$typeAnnotation;
913
+
914
+ return constructFlowNode({
915
+ type: 'FunctionTypeParam',
916
+ name: constructFlowNode({
917
+ type: 'Identifier',
918
+ name: param.name,
919
+ optional: false,
920
+ typeAnnotation: null
921
+ }),
922
+ optional: Boolean(param.optional),
923
+ typeAnnotation: Transform.TSTypeAnnotationOpt((_param$typeAnnotation = param.typeAnnotation) == null ? void 0 : _param$typeAnnotation.typeAnnotation)
924
+ });
925
+ } else if (param.type === 'ArrayPattern' || param.type === 'ObjectPattern') {
926
+ var _param$typeAnnotation2;
927
+
928
+ return constructFlowNode({
929
+ type: 'FunctionTypeParam',
930
+ name: constructFlowNode({
931
+ type: 'Identifier',
932
+ name: `$$param${i}$`,
933
+ optional: false,
934
+ typeAnnotation: null
935
+ }),
936
+ optional: Boolean(param.optional),
937
+ typeAnnotation: Transform.TSTypeAnnotationOpt((_param$typeAnnotation2 = param.typeAnnotation) == null ? void 0 : _param$typeAnnotation2.typeAnnotation)
938
+ });
939
+ } else {
940
+ throw new Error(`Unexpected function parameter ${param.type}`);
941
+ }
942
+ })
943
+ };
944
+ }
945
+
946
+ static TSImportType(node) {
947
+ let base = constructFlowNode({
948
+ type: 'GenericTypeAnnotation',
949
+ id: constructFlowNode({
950
+ type: 'Identifier',
951
+ name: '$Exports',
952
+ optional: false,
953
+ typeAnnotation: null
954
+ }),
955
+ typeParameters: constructFlowNode({
956
+ type: 'TypeParameterInstantiation',
957
+ params: [Transform.TSTypeAnnotation(node.argument)]
958
+ })
959
+ });
960
+
961
+ if (node.qualifier == null) {
962
+ return base;
963
+ }
964
+
965
+ if (node.typeParameters != null) {
966
+ return unsupportedAnnotation(node, 'import types with type parameters');
967
+ }
968
+
969
+ let qualifier = Transform.EntityNameToTypeIdentifier(node.qualifier);
970
+ const namesRev = [];
971
+
972
+ while (qualifier.type !== 'Identifier') {
973
+ namesRev.push(qualifier.id.name);
974
+ qualifier = qualifier.qualification;
975
+ }
976
+
977
+ namesRev.push(qualifier.name);
978
+
979
+ while (namesRev.length > 0) {
980
+ const name = namesRev.pop();
981
+ base = constructFlowNode({
982
+ type: 'IndexedAccessType',
983
+ objectType: base,
984
+ indexType: constructFlowNode({
985
+ type: 'StringLiteralTypeAnnotation',
986
+ value: name,
987
+ raw: `'${name}'`
988
+ })
989
+ });
990
+ }
991
+
992
+ return base;
993
+ }
994
+
995
+ static TSImportEqualsDeclaration(node) {
996
+ if (node.moduleReference.type === 'ThisExpression' || node.moduleReference.type === 'TSQualifiedName') {
997
+ return unsupportedDeclaration(node, 'import equals declaration with weird module reference', node.id);
998
+ }
999
+
1000
+ let moduleName;
1001
+
1002
+ if (node.moduleReference.type === 'TSExternalModuleReference') {
1003
+ if (node.moduleReference.expression.type === 'Literal') {
1004
+ moduleName = String(node.moduleReference.expression.value);
1005
+ } else {
1006
+ return unsupportedDeclaration(node, 'import equals declaration with weird module reference', node.id);
1007
+ }
1008
+ } else {
1009
+ moduleName = node.moduleReference.name;
1010
+ }
1011
+
1012
+ return constructFlowNode({
1013
+ type: 'VariableDeclaration',
1014
+ kind: 'const',
1015
+ declarations: [constructFlowNode({
1016
+ type: 'VariableDeclarator',
1017
+ id: constructFlowNode({
1018
+ type: 'Identifier',
1019
+ name: node.id.name,
1020
+ optional: false,
1021
+ typeAnnotation: null
1022
+ }),
1023
+ init: constructFlowNode({
1024
+ type: 'CallExpression',
1025
+ callee: constructFlowNode({
1026
+ type: 'Identifier',
1027
+ name: 'require',
1028
+ optional: false,
1029
+ typeAnnotation: null
1030
+ }),
1031
+ arguments: [constructFlowNode({
1032
+ type: 'Literal',
1033
+ literalType: 'string',
1034
+ value: moduleName,
1035
+ raw: `"${moduleName}"`
1036
+ })],
1037
+ optional: false,
1038
+ typeArguments: null
1039
+ })
1040
+ })]
1041
+ });
1042
+ }
1043
+
1044
+ static TSIndexedAccessType(node) {
1045
+ return constructFlowNode({
1046
+ type: 'IndexedAccessType',
1047
+ objectType: Transform.TSTypeAnnotation(node.objectType),
1048
+ indexType: Transform.TSTypeAnnotation(node.indexType)
1049
+ });
1050
+ }
1051
+
1052
+ static TSInferType(node) {
1053
+ return constructFlowNode({
1054
+ type: 'InferTypeAnnotation',
1055
+ typeParameter: Transform.TSTypeParameter(node.typeParameter)
1056
+ });
1057
+ }
1058
+
1059
+ static TSInterfaceDeclaration(node) {
1060
+ const body = Transform.TSTypeLiteralOrInterfaceBody(node.body); // $FlowFixMe[cannot-write]
1061
+
1062
+ body.inexact = false;
1063
+ return constructFlowNode({
1064
+ type: 'InterfaceDeclaration',
1065
+ id: Transform.Identifier(node.id),
1066
+ typeParameters: Transform.TSTypeParameterDeclarationOpt(node.typeParameters),
1067
+ body,
1068
+ extends: (node.extends || []).map(e => Transform.TSInterfaceHeritage(e))
1069
+ });
1070
+ }
1071
+
1072
+ static TSInterfaceHeritage(node) {
1073
+ return constructFlowNode({
1074
+ type: 'InterfaceExtends',
1075
+ id: Transform._expressionToIdOrQualifiedTypeId(node.expression, 'interface extends'),
1076
+ typeParameters: Transform.TSTypeParameterInstantiationOpt(node.typeParameters)
1077
+ });
1078
+ }
1079
+
1080
+ static _expressionToIdOrQualifiedTypeId(node, kind) {
1081
+ if (node.type === 'Identifier') {
1082
+ return Transform.Identifier(node);
1083
+ } else if (node.type === 'MemberExpression' && node.property.type === 'Identifier') {
1084
+ const id = Transform.Identifier(node.property);
1085
+ return constructFlowNode({
1086
+ type: 'QualifiedTypeIdentifier',
1087
+ qualification: Transform._expressionToIdOrQualifiedTypeId(node.object, kind),
1088
+ id
1089
+ });
1090
+ } else {
1091
+ throw unexpectedTranslationError(node, `Expected ${kind} to be an Identifier or Member`);
1092
+ }
1093
+ }
1094
+
1095
+ static TSIntersectionType(node) {
1096
+ return constructFlowNode({
1097
+ type: 'IntersectionTypeAnnotation',
1098
+ types: node.types.map(node => Transform.TSTypeAnnotation(node))
1099
+ });
1100
+ }
1101
+
1102
+ static TSLiteralType(node) {
1103
+ switch (node.literal.type) {
1104
+ case 'TemplateLiteral':
1105
+ return unsupportedAnnotation(node, 'template literals');
1106
+
1107
+ case 'Literal':
1108
+ return Transform.LiteralType(node.literal);
1109
+
1110
+ case 'UnaryExpression':
1111
+ return unsupportedAnnotation(node, 'UnaryExpression literal type');
1112
+
1113
+ case 'UpdateExpression':
1114
+ return unsupportedAnnotation(node, 'UpdateExpression literal type');
1115
+ }
1116
+ }
1117
+
1118
+ static TSMappedType(node) {
1119
+ var _keyTparam$bound;
1120
+
1121
+ const keyTparam = Transform.TSTypeParameter(node.typeParameter);
1122
+ const sourceType = (_keyTparam$bound = keyTparam.bound) == null ? void 0 : _keyTparam$bound.typeAnnotation; // $FlowFixMe[cannot-write]
1123
+
1124
+ keyTparam.bound = null;
1125
+ const prop = constructFlowNode({
1126
+ type: 'ObjectTypeMappedTypeProperty',
1127
+ keyTparam,
1128
+ propType: Transform.TSTypeAnnotationOpt(node.typeAnnotation),
1129
+ sourceType,
1130
+ variance: node.readonly === '+' || Boolean(node.readonly) ? constructFlowNode({
1131
+ type: 'Variance',
1132
+ kind: 'plus'
1133
+ }) : null,
1134
+ optional: node.optional === '+' ? 'PlusOptional' : node.optional === '-' ? 'MinusOptional' : // eslint-disable-next-line no-extra-boolean-cast
1135
+ Boolean(node.optional) ? 'Optional' : null
1136
+ });
1137
+ return constructFlowNode({
1138
+ type: 'ObjectTypeAnnotation',
1139
+ properties: [prop],
1140
+ indexers: [],
1141
+ callProperties: [],
1142
+ internalSlots: [],
1143
+ exact: false,
1144
+ inexact: false
1145
+ });
1146
+ }
1147
+
1148
+ static TSModuleDeclaration(node) {
1149
+ var _node$global;
1150
+
1151
+ const body = node.body == null ? constructFlowNode({
1152
+ type: 'BlockStatement',
1153
+ body: []
1154
+ }) : node.body.type === 'TSModuleDeclaration' ? (() => {
1155
+ throw translationError(node, 'nested module declarations');
1156
+ })() : constructFlowNode({
1157
+ type: 'BlockStatement',
1158
+ body: node.body.body.flatMap(s => Transform.Statement(s))
1159
+ });
1160
+
1161
+ if (node.id.type === 'Literal') {
1162
+ return constructFlowNode({
1163
+ type: 'DeclareModule',
1164
+ id: Transform.Literal(node.id),
1165
+ body
1166
+ });
1167
+ }
1168
+
1169
+ if ((_node$global = node.global) != null ? _node$global : false) {
1170
+ return unsupportedDeclaration(node, 'global declaration', node.id);
1171
+ }
1172
+
1173
+ return constructFlowNode({
1174
+ type: 'DeclareNamespace',
1175
+ id: Transform.Identifier(node.id),
1176
+ body
1177
+ });
1178
+ }
1179
+
1180
+ static TSNamedTupleMember(node) {
1181
+ let optional = false;
1182
+ let elementType;
1183
+
1184
+ if (node.elementType.type === 'TSRestType') {
1185
+ const child = node.elementType;
1186
+ return constructFlowNode({
1187
+ type: 'TupleTypeSpreadElement',
1188
+ label: Transform.Identifier(node.label),
1189
+ typeAnnotation: Transform.TSTypeAnnotation(child.typeAnnotation),
1190
+ optional: false,
1191
+ variance: null
1192
+ });
1193
+ } else if (node.elementType.type === 'TSOptionalType') {
1194
+ optional = true;
1195
+ elementType = Transform.TSTypeAnnotation(node.elementType.typeAnnotation);
1196
+ } else {
1197
+ elementType = Transform.TSTypeAnnotation(node.elementType);
1198
+ }
1199
+
1200
+ return constructFlowNode({
1201
+ type: 'TupleTypeLabeledElement',
1202
+ label: Transform.Identifier(node.label),
1203
+ elementType,
1204
+ optional,
1205
+ variance: null
1206
+ });
1207
+ }
1208
+
1209
+ static TSNeverType() {
1210
+ return constructFlowNode({
1211
+ type: 'EmptyTypeAnnotation'
1212
+ });
1213
+ }
1214
+
1215
+ static TSNullType() {
1216
+ return constructFlowNode({
1217
+ type: 'NullLiteralTypeAnnotation'
1218
+ });
1219
+ }
1220
+
1221
+ static TSNumberType() {
1222
+ return constructFlowNode({
1223
+ type: 'NumberTypeAnnotation'
1224
+ });
1225
+ }
1226
+
1227
+ static TSObjectType() {
1228
+ return constructFlowNode({
1229
+ type: 'InterfaceTypeAnnotation',
1230
+ body: constructFlowNode({
1231
+ type: 'ObjectTypeAnnotation',
1232
+ inexact: false,
1233
+ exact: false,
1234
+ properties: [],
1235
+ indexers: [],
1236
+ callProperties: [],
1237
+ internalSlots: []
1238
+ }),
1239
+ extends: []
1240
+ });
1241
+ }
1242
+
1243
+ static TSQualifiedNameToQualifiedTypeIdentifier(node) {
1244
+ return constructFlowNode({
1245
+ type: 'QualifiedTypeIdentifier',
1246
+ qualification: Transform.EntityNameToTypeIdentifier(node.left),
1247
+ id: Transform.Identifier(node.right)
1248
+ });
1249
+ }
1250
+
1251
+ static TSQualifiedNameToQualifiedTypeofIdentifier(node) {
1252
+ return constructFlowNode({
1253
+ type: 'QualifiedTypeofIdentifier',
1254
+ qualification: Transform.EntityNameToTypeofIdentifier(node.left),
1255
+ id: Transform.Identifier(node.right)
1256
+ });
1257
+ }
1258
+
1259
+ static TSStringType() {
1260
+ return constructFlowNode({
1261
+ type: 'StringTypeAnnotation'
1262
+ });
1263
+ }
1264
+
1265
+ static TSSymbolType() {
1266
+ return constructFlowNode({
1267
+ type: 'SymbolTypeAnnotation'
1268
+ });
1269
+ }
1270
+
1271
+ static TSTemplateLiteralType(node) {
1272
+ return unsupportedAnnotation(node, 'constructor types');
1273
+ }
1274
+
1275
+ static TSThisType(_node) {
1276
+ return constructFlowNode({
1277
+ type: 'GenericTypeAnnotation',
1278
+ id: constructFlowNode({
1279
+ type: 'Identifier',
1280
+ name: 'this',
1281
+ typeAnnotation: null,
1282
+ optional: false
1283
+ }),
1284
+ typeParameters: null
1285
+ });
1286
+ }
1287
+
1288
+ static TSTupleType(node) {
1289
+ return constructFlowNode({
1290
+ type: 'TupleTypeAnnotation',
1291
+ types: node.elementTypes.map(node => Transform.TSTypeAnnotation(node)),
1292
+ inexact: false
1293
+ });
1294
+ }
1295
+
1296
+ static TSTypeAliasDeclaration(node) {
1297
+ return constructFlowNode({
1298
+ type: 'TypeAlias',
1299
+ id: Transform.Identifier(node.id),
1300
+ typeParameters: Transform.TSTypeParameterDeclarationOpt(node.typeParameters),
1301
+ right: Transform.TSTypeAnnotation(node.typeAnnotation)
1302
+ });
1303
+ }
1304
+
1305
+ static TSTypeAnnotation(node) {
1306
+ switch (node.type) {
1307
+ case 'TSOptionalType':
1308
+ case 'TSQualifiedName':
1309
+ case 'TSRestType':
1310
+ return unsupportedAnnotation(node, 'unexpected toplevel ' + node.type);
1311
+
1312
+ case 'TSAbstractKeyword':
1313
+ case 'TSAsyncKeyword':
1314
+ case 'TSDeclareKeyword':
1315
+ case 'TSExportKeyword':
1316
+ case 'TSPrivateKeyword':
1317
+ case 'TSProtectedKeyword':
1318
+ case 'TSPublicKeyword':
1319
+ case 'TSReadonlyKeyword':
1320
+ case 'TSStaticKeyword':
1321
+ return unsupportedAnnotation(node, 'wat keyword ' + node.type);
1322
+
1323
+ case 'TSAnyKeyword':
1324
+ return Transform.TSAnyType();
1325
+
1326
+ case 'TSArrayType':
1327
+ return Transform.TSArrayType(node);
1328
+
1329
+ case 'TSBigIntKeyword':
1330
+ return Transform.TSBigIntType();
1331
+
1332
+ case 'TSBooleanKeyword':
1333
+ return Transform.TSBooleanType();
1334
+
1335
+ case 'TSConditionalType':
1336
+ return Transform.TSConditionalType(node);
1337
+
1338
+ case 'TSConstructorType':
1339
+ return Transform.TSConstructorType(node);
1340
+
1341
+ case 'TSFunctionType':
1342
+ return Transform.TSFunctionType(node);
1343
+
1344
+ case 'TSImportType':
1345
+ return Transform.TSImportType(node);
1346
+
1347
+ case 'TSIndexedAccessType':
1348
+ return Transform.TSIndexedAccessType(node);
1349
+
1350
+ case 'TSInferType':
1351
+ return Transform.TSInferType(node);
1352
+
1353
+ case 'TSIntersectionType':
1354
+ return Transform.TSIntersectionType(node);
1355
+
1356
+ case 'TSIntrinsicKeyword':
1357
+ return unsupportedAnnotation(node, 'intrinsic keyword');
1358
+
1359
+ case 'TSLiteralType':
1360
+ return Transform.TSLiteralType(node);
1361
+
1362
+ case 'TSMappedType':
1363
+ return Transform.TSMappedType(node);
1364
+
1365
+ case 'TSNamedTupleMember':
1366
+ return Transform.TSNamedTupleMember(node);
1367
+
1368
+ case 'TSNeverKeyword':
1369
+ return Transform.TSNeverType();
1370
+
1371
+ case 'TSNullKeyword':
1372
+ return Transform.TSNullType();
1373
+
1374
+ case 'TSNumberKeyword':
1375
+ return Transform.TSNumberType();
1376
+
1377
+ case 'TSObjectKeyword':
1378
+ return Transform.TSObjectType();
1379
+
1380
+ case 'TSStringKeyword':
1381
+ return Transform.TSStringType();
1382
+
1383
+ case 'TSSymbolKeyword':
1384
+ return Transform.TSSymbolType();
1385
+
1386
+ case 'TSTemplateLiteralType':
1387
+ return Transform.TSTemplateLiteralType(node);
1388
+
1389
+ case 'TSThisType':
1390
+ return Transform.TSThisType(node);
1391
+
1392
+ case 'TSTupleType':
1393
+ return Transform.TSTupleType(node);
1394
+
1395
+ case 'TSTypeLiteral':
1396
+ return Transform.TSTypeLiteralOrInterfaceBody(node);
1397
+
1398
+ case 'TSTypeOperator':
1399
+ return Transform.TSTypeOperator(node);
1400
+
1401
+ case 'TSTypePredicate':
1402
+ return Transform.TSTypePredicate(node);
1403
+
1404
+ case 'TSTypeQuery':
1405
+ return Transform.TSTypeQuery(node);
1406
+
1407
+ case 'TSTypeReference':
1408
+ return Transform.TSTypeReference(node);
1409
+
1410
+ case 'TSUndefinedKeyword':
1411
+ case 'TSVoidKeyword':
1412
+ return Transform.TSUndefinedOrVoidType();
1413
+
1414
+ case 'TSUnionType':
1415
+ return Transform.TSUnionType(node);
1416
+
1417
+ case 'TSUnknownKeyword':
1418
+ return Transform.TSUnknownType();
1419
+ }
1420
+ }
1421
+
1422
+ static TSTypeAnnotationOpt(node) {
1423
+ return node == null ? constructFlowNode({
1424
+ type: 'AnyTypeAnnotation'
1425
+ }) : Transform.TSTypeAnnotation(node);
1426
+ }
1427
+
1428
+ static TSTypeAnnotationNode(node) {
1429
+ return constructFlowNode({
1430
+ type: 'TypeAnnotation',
1431
+ typeAnnotation: Transform.TSTypeAnnotation(node.typeAnnotation)
1432
+ });
1433
+ }
1434
+ /** A very confusingly named object type */
1435
+
1436
+
1437
+ static TSTypeLiteralOrInterfaceBody(node) {
1438
+ const properties = [];
1439
+ const indexers = [];
1440
+ const callProperties = [];
1441
+
1442
+ for (const prop of node.type === 'TSTypeLiteral' ? node.members : node.body) {
1443
+ switch (prop.type) {
1444
+ case 'TSPropertySignature':
1445
+ {
1446
+ Transform._translateIntoObjectProp(prop, properties, indexers);
1447
+
1448
+ break;
1449
+ }
1450
+
1451
+ case 'TSMethodSignature':
1452
+ {
1453
+ Transform._translateIntoObjectMethod(prop, properties);
1454
+
1455
+ break;
1456
+ }
1457
+
1458
+ case 'TSCallSignatureDeclaration':
1459
+ callProperties.push(constructFlowNode({
1460
+ type: 'ObjectTypeCallProperty',
1461
+ method: false,
1462
+ optional: false,
1463
+ static: false,
1464
+ proto: false,
1465
+ variance: null,
1466
+ value: Transform.TSFunctionType({
1467
+ type: 'TSFunctionType',
1468
+ loc: prop.loc,
1469
+ params: prop.params,
1470
+ returnType: prop.returnType,
1471
+ typeParameters: prop.typeParameters
1472
+ })
1473
+ }));
1474
+ break;
1475
+
1476
+ case 'TSIndexSignature':
1477
+ {
1478
+ var _prop$typeAnnotation;
1479
+
1480
+ // eslint-disable-next-line no-extra-boolean-cast
1481
+ const variance = Boolean(prop.readonly) ? constructFlowNode({
1482
+ type: 'Variance',
1483
+ kind: 'plus'
1484
+ }) : null;
1485
+ indexers.push(constructFlowNode({
1486
+ type: 'ObjectTypeIndexer',
1487
+ kind: 'init',
1488
+ method: false,
1489
+ optional: false,
1490
+ static: Boolean(prop.static),
1491
+ proto: false,
1492
+ variance,
1493
+ id: null,
1494
+ key: constructFlowNode({
1495
+ type: 'StringTypeAnnotation'
1496
+ }),
1497
+ value: Transform.TSTypeAnnotationOpt((_prop$typeAnnotation = prop.typeAnnotation) == null ? void 0 : _prop$typeAnnotation.typeAnnotation)
1498
+ }));
1499
+ break;
1500
+ }
1501
+
1502
+ case 'TSConstructSignatureDeclaration':
1503
+ properties.push(constructFlowNode({
1504
+ type: 'ObjectTypeProperty',
1505
+ kind: 'init',
1506
+ method: true,
1507
+ optional: false,
1508
+ static: false,
1509
+ proto: false,
1510
+ variance: null,
1511
+ key: constructFlowNode({
1512
+ type: 'Identifier',
1513
+ name: 'constructor',
1514
+ optional: false,
1515
+ typeAnnotation: null
1516
+ }),
1517
+ value: Transform.TSFunctionType({
1518
+ type: 'TSFunctionType',
1519
+ loc: prop.loc,
1520
+ params: prop.params,
1521
+ returnType: prop.returnType,
1522
+ typeParameters: prop.typeParameters
1523
+ }, true)
1524
+ }));
1525
+ break;
1526
+ }
1527
+ }
1528
+
1529
+ return constructFlowNode({
1530
+ type: 'ObjectTypeAnnotation',
1531
+ properties,
1532
+ indexers,
1533
+ callProperties,
1534
+ internalSlots: [],
1535
+ exact: false,
1536
+ inexact: true
1537
+ });
1538
+ }
1539
+
1540
+ static _translateIntoObjectProp(prop, properties, indexers) {
1541
+ // eslint-disable-next-line no-extra-boolean-cast
1542
+ const variance = Boolean(prop.readonly) ? constructFlowNode({
1543
+ type: 'Variance',
1544
+ kind: 'plus'
1545
+ }) : null;
1546
+
1547
+ if (prop.computed === false) {
1548
+ var _prop$typeAnnotation2;
1549
+
1550
+ const key = prop.key;
1551
+ properties.push(constructFlowNode({
1552
+ type: 'ObjectTypeProperty',
1553
+ kind: 'init',
1554
+ method: false,
1555
+ optional: Boolean(prop.optional),
1556
+ static: false,
1557
+ proto: false,
1558
+ variance,
1559
+ key: key.type === 'Identifier' ? Transform.Identifier(key, false) : key.type === 'PrivateIdentifier' ? constructFlowNode({
1560
+ type: 'PrivateIdentifier',
1561
+ name: key.name
1562
+ }) : constructFlowNode({
1563
+ type: 'Literal',
1564
+ literalType: 'string',
1565
+ value: String(key.value),
1566
+ raw: JSON.stringify(String(key.value))
1567
+ }),
1568
+ value: Transform.TSTypeAnnotationOpt((_prop$typeAnnotation2 = prop.typeAnnotation) == null ? void 0 : _prop$typeAnnotation2.typeAnnotation)
1569
+ }));
1570
+ } else {
1571
+ var _prop$typeAnnotation3;
1572
+
1573
+ indexers.push(constructFlowNode({
1574
+ type: 'ObjectTypeIndexer',
1575
+ kind: 'init',
1576
+ method: false,
1577
+ optional: Boolean(prop.optional),
1578
+ static: false,
1579
+ proto: false,
1580
+ variance,
1581
+ id: null,
1582
+ key: constructFlowNode({
1583
+ type: 'StringTypeAnnotation'
1584
+ }),
1585
+ value: Transform.TSTypeAnnotationOpt((_prop$typeAnnotation3 = prop.typeAnnotation) == null ? void 0 : _prop$typeAnnotation3.typeAnnotation)
1586
+ }));
1587
+ }
1588
+ }
1589
+
1590
+ static _translateIntoObjectMethod(prop, properties) {
1591
+ if (prop.computed === true) {
1592
+ throw translationError(prop, 'computed method signature');
1593
+ }
1594
+
1595
+ const originalKey = prop.key;
1596
+ const key = originalKey.type === 'Identifier' ? Transform.Identifier(originalKey, false) : originalKey.type === 'PrivateIdentifier' ? constructFlowNode({
1597
+ type: 'PrivateIdentifier',
1598
+ name: originalKey.name
1599
+ }) : constructFlowNode({
1600
+ type: 'Literal',
1601
+ literalType: 'string',
1602
+ value: String(originalKey.value),
1603
+ raw: JSON.stringify(String(originalKey.value))
1604
+ });
1605
+ const value = Transform.TSFunctionType({
1606
+ type: 'TSFunctionType',
1607
+ loc: prop.loc,
1608
+ params: prop.type === 'MethodDefinition' || prop.type === 'TSAbstractMethodDefinition' ? prop.value.params : prop.params,
1609
+ returnType: prop.type === 'MethodDefinition' || prop.type === 'TSAbstractMethodDefinition' ? prop.value.returnType : prop.returnType,
1610
+ typeParameters: prop.typeParameters
1611
+ }, true);
1612
+
1613
+ if (prop.kind === 'method' || prop.kind === 'constructor') {
1614
+ properties.push(constructFlowNode({
1615
+ type: 'ObjectTypeProperty',
1616
+ kind: 'init',
1617
+ method: true,
1618
+ optional: false,
1619
+ static: false,
1620
+ proto: false,
1621
+ variance: null,
1622
+ key,
1623
+ value
1624
+ }));
1625
+ } else {
1626
+ properties.push(constructFlowNode({
1627
+ type: 'ObjectTypeProperty',
1628
+ kind: prop.kind,
1629
+ method: false,
1630
+ optional: false,
1631
+ static: false,
1632
+ proto: false,
1633
+ variance: null,
1634
+ key,
1635
+ value
1636
+ }));
1637
+ }
1638
+ }
1639
+
1640
+ static TSTypeOperator(node) {
1641
+ switch (node.operator) {
1642
+ case 'unique':
1643
+ return unsupportedAnnotation(node, 'unique operator');
1644
+
1645
+ case 'keyof':
1646
+ return constructFlowNode({
1647
+ type: 'KeyofTypeAnnotation',
1648
+ argument: Transform.TSTypeAnnotationOpt(node.typeAnnotation)
1649
+ });
1650
+
1651
+ case 'readonly':
1652
+ {
1653
+ const child = node.typeAnnotation;
1654
+
1655
+ switch (child == null ? void 0 : child.type) {
1656
+ case 'TSArrayType':
1657
+ return constructFlowNode({
1658
+ type: 'GenericTypeAnnotation',
1659
+ id: constructFlowNode({
1660
+ type: 'Identifier',
1661
+ name: '$ReadOnlyArray',
1662
+ optional: false,
1663
+ typeAnnotation: null
1664
+ }),
1665
+ typeParameters: constructFlowNode({
1666
+ type: 'TypeParameterInstantiation',
1667
+ params: [Transform.TSTypeAnnotation(child.elementType)]
1668
+ })
1669
+ });
1670
+
1671
+ case 'TSTupleType':
1672
+ return constructFlowNode({
1673
+ type: 'GenericTypeAnnotation',
1674
+ id: constructFlowNode({
1675
+ type: 'Identifier',
1676
+ name: '$ReadOnly',
1677
+ optional: false,
1678
+ typeAnnotation: null
1679
+ }),
1680
+ typeParameters: constructFlowNode({
1681
+ type: 'TypeParameterInstantiation',
1682
+ params: [Transform.TSTypeAnnotation(child)]
1683
+ })
1684
+ });
1685
+
1686
+ default:
1687
+ return unsupportedAnnotation(node, 'readonly operator with inner type: ' + ((child == null ? void 0 : child.type) || 'null'));
1688
+ }
1689
+ }
1690
+ }
1691
+ }
1692
+
1693
+ static TSTypeParameter(node) {
1694
+ return constructFlowNode({
1695
+ type: 'TypeParameter',
1696
+ name: node.name.name,
1697
+ bound: node.constraint == null ? null : constructFlowNode({
1698
+ type: 'TypeAnnotation',
1699
+ typeAnnotation: Transform.TSTypeAnnotation(node.constraint)
1700
+ }),
1701
+ default: node.default == null ? null : Transform.TSTypeAnnotation(node.default),
1702
+ usesExtendsBound: false,
1703
+ variance: node.in && node.out || !node.in && !node.out ? null : constructFlowNode({
1704
+ type: 'Variance',
1705
+ kind: node.out ? 'plus' : 'minus'
1706
+ })
1707
+ });
1708
+ }
1709
+
1710
+ static TSTypeParameterDeclaration(node) {
1711
+ return constructFlowNode({
1712
+ type: 'TypeParameterDeclaration',
1713
+ params: node.params.map(node => Transform.TSTypeParameter(node))
1714
+ });
1715
+ }
1716
+
1717
+ static TSTypeParameterDeclarationOpt(node) {
1718
+ return node != null ? Transform.TSTypeParameterDeclaration(node) : null;
1719
+ }
1720
+
1721
+ static TSTypeParameterInstantiation(node) {
1722
+ return constructFlowNode({
1723
+ type: 'TypeParameterInstantiation',
1724
+ params: node.params.map(node => Transform.TSTypeAnnotation(node))
1725
+ });
1726
+ }
1727
+
1728
+ static TSTypeParameterInstantiationOpt(node) {
1729
+ return node != null ? Transform.TSTypeParameterInstantiation(node) : null;
1730
+ }
1731
+
1732
+ static TSTypePredicate(node) {
1733
+ return constructFlowNode({
1734
+ type: 'TypePredicate',
1735
+ parameterName: node.parameterName.type === 'TSThisType' ? constructFlowNode({
1736
+ type: 'Identifier',
1737
+ name: 'this',
1738
+ optional: false,
1739
+ typeAnnotation: null
1740
+ }) : Transform.Identifier(node.parameterName, false),
1741
+ kind: node.asserts ? 'asserts' : null,
1742
+ typeAnnotation: node.typeAnnotation == null ? null : Transform.TSTypeAnnotation(node.typeAnnotation.typeAnnotation)
1743
+ });
1744
+ }
1745
+
1746
+ static TSTypeQuery(node) {
1747
+ var _Transform$TSTypePara;
1748
+
1749
+ return constructFlowNode({
1750
+ type: 'TypeofTypeAnnotation',
1751
+ argument: Transform.EntityNameToTypeofIdentifier(node.exprName),
1752
+ typeArguments: (_Transform$TSTypePara = Transform.TSTypeParameterInstantiationOpt(node.typeParameters)) != null ? _Transform$TSTypePara : undefined
1753
+ });
1754
+ }
1755
+
1756
+ static TSTypeReference(node) {
1757
+ return constructFlowNode({
1758
+ type: 'GenericTypeAnnotation',
1759
+ id: Transform.EntityNameToTypeIdentifier(node.typeName),
1760
+ typeParameters: Transform.TSTypeParameterInstantiationOpt(node.typeParameters)
1761
+ });
1762
+ }
1763
+
1764
+ static TSUndefinedOrVoidType() {
1765
+ return constructFlowNode({
1766
+ type: 'VoidTypeAnnotation'
1767
+ });
1768
+ }
1769
+
1770
+ static TSUnionType(node) {
1771
+ return constructFlowNode({
1772
+ type: 'UnionTypeAnnotation',
1773
+ types: node.types.map(node => Transform.TSTypeAnnotation(node))
1774
+ });
1775
+ }
1776
+
1777
+ static TSUnknownType() {
1778
+ return constructFlowNode({
1779
+ type: 'MixedTypeAnnotation'
1780
+ });
1781
+ }
1782
+
1783
+ static VariableDeclaration(node) {
1784
+ return node.declarations.map(decl => {
1785
+ if (decl.id.type !== 'Identifier') {
1786
+ throw translationError(decl.id, 'Non-identifier variable declaration');
1787
+ }
1788
+
1789
+ const id = Transform.Identifier(decl.id);
1790
+
1791
+ if (id.typeAnnotation == null) {
1792
+ // $FlowExpectedError[cannot-write]
1793
+ id.typeAnnotation = constructFlowNode({
1794
+ type: 'TypeAnnotation',
1795
+ typeAnnotation: constructFlowNode({
1796
+ type: 'AnyTypeAnnotation'
1797
+ })
1798
+ });
1799
+ }
1800
+
1801
+ return constructFlowNode({
1802
+ type: 'DeclareVariable',
1803
+ id,
1804
+ kind: node.kind
1805
+ });
1806
+ });
1807
+ }
1808
+
1809
+ }
1810
+
1811
+ return [Transform, code];
1812
+ };