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