flow-api-translator 0.10.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,932 @@
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.default = flowToFlowDef;
16
+
17
+ var _hermesTransform = require("hermes-transform");
18
+
19
+ var _FlowAnalyze = require("./utils/FlowAnalyze");
20
+
21
+ var _TranslationUtils = require("./utils/TranslationUtils");
22
+
23
+ var _ErrorUtils = require("./utils/ErrorUtils");
24
+
25
+ var _hermesEstree = require("hermes-estree");
26
+
27
+ const EMPTY_TRANSLATION_RESULT = [null, []];
28
+
29
+ function convertArray(items, convert) {
30
+ const resultItems = [];
31
+ const deps = [];
32
+
33
+ for (const item of items) {
34
+ const [resultItem, itemDeps] = convert(item);
35
+
36
+ if (resultItem != null) {
37
+ resultItems.push(resultItem);
38
+ deps.push(...itemDeps);
39
+ }
40
+ }
41
+
42
+ return [resultItems, deps];
43
+ }
44
+
45
+ function getTopLevelStatement(node, context) {
46
+ let currentNode = node;
47
+
48
+ while (currentNode != null) {
49
+ var _currentNode$parent;
50
+
51
+ if (((_currentNode$parent = currentNode.parent) == null ? void 0 : _currentNode$parent.type) === 'Program') {
52
+ // $FlowFixMe[incompatible-return]
53
+ return currentNode;
54
+ }
55
+
56
+ currentNode = currentNode.parent;
57
+ }
58
+
59
+ throw (0, _ErrorUtils.translationError)(node, `getTopLevelStatement: Detached node of type "${node.type}" passed`, context);
60
+ }
61
+
62
+ function transferProgramStatementProperties(stmt, orgStmt) {
63
+ // $FlowExpectedError[prop-missing]
64
+ // $FlowExpectedError[incompatible-use]
65
+ stmt.comments = orgStmt.comments; // $FlowExpectedError[incompatible-use]
66
+
67
+ stmt.range = orgStmt.range; // $FlowExpectedError[incompatible-use]
68
+
69
+ stmt.loc = orgStmt.loc;
70
+ }
71
+ /**
72
+ * Consume an abribray Flow AST and convert it into a Type defintion file.
73
+ *
74
+ * To do this all runtime logic will be stripped and only Type that describe the module boundary will remain.
75
+ */
76
+
77
+
78
+ function flowToFlowDef(ast, code, scopeManager, opts) {
79
+ var _ast$interpreter$valu, _ast$interpreter;
80
+
81
+ const context = (0, _TranslationUtils.createTranslationContext)(code, scopeManager, opts);
82
+ const translatedStatements = new Map();
83
+
84
+ function storeTranslatedStatement(stmt, orgStmt) {
85
+ translatedStatements.set(orgStmt, stmt);
86
+ }
87
+
88
+ const seenDeps = new Set();
89
+ const processedStatements = new Set();
90
+ const pendingStatements = new Set();
91
+
92
+ function updatePendingStatements(deps) {
93
+ for (const dep of deps) {
94
+ if (seenDeps.has(dep)) {
95
+ continue;
96
+ }
97
+
98
+ seenDeps.add(dep);
99
+ const variable = context.variableMap.get(dep);
100
+
101
+ if (variable == null) {
102
+ throw new Error(`updatePendingStatements: Variable for dependency "${dep}" not found`);
103
+ }
104
+
105
+ for (const def of variable.defs) {
106
+ const stmt = def.node;
107
+
108
+ if (stmt == null) {
109
+ throw new Error(`updatePendingStatements: Variable parent of "${dep}" not found`);
110
+ }
111
+
112
+ const topLevelStmt = getTopLevelStatement(stmt, context);
113
+
114
+ if (processedStatements.has(topLevelStmt)) {
115
+ continue;
116
+ }
117
+
118
+ pendingStatements.add(topLevelStmt);
119
+ }
120
+ }
121
+ }
122
+
123
+ function updateProcessedStatement(stmt) {
124
+ processedStatements.add(stmt);
125
+ pendingStatements.delete(stmt);
126
+ } // Process all export statements
127
+
128
+
129
+ for (const stmt of ast.body) {
130
+ const resultExport = convertExport(stmt, context);
131
+
132
+ if (resultExport != null) {
133
+ updateProcessedStatement(stmt);
134
+ const [resultExportedStmt, deps] = resultExport;
135
+ storeTranslatedStatement(resultExportedStmt, stmt);
136
+ updatePendingStatements(deps);
137
+ }
138
+ }
139
+
140
+ while (pendingStatements.size > 0) {
141
+ const stmt = pendingStatements.values().next().value;
142
+
143
+ if (stmt == null) {
144
+ throw new Error(`flowToFlowDef: Invalid state, "pendingStatements" cannot be empty`);
145
+ }
146
+
147
+ updateProcessedStatement(stmt);
148
+ const [resultStmt, deps] = convertStatement(stmt, context);
149
+ storeTranslatedStatement(resultStmt, stmt);
150
+ updatePendingStatements(deps);
151
+ }
152
+
153
+ const translatedBody = [];
154
+
155
+ for (const stmt of ast.body) {
156
+ const translatedStatement = translatedStatements.get(stmt);
157
+
158
+ if (translatedStatement != null) {
159
+ const optimizedStatement = stripUnusedDefs(translatedStatement, seenDeps, context);
160
+ transferProgramStatementProperties(optimizedStatement, stmt);
161
+ translatedBody.push(optimizedStatement);
162
+ }
163
+ }
164
+
165
+ return [_hermesTransform.t.Program({
166
+ body: translatedBody,
167
+ sourceType: ast.sourceType,
168
+ interpreter: (_ast$interpreter$valu = (_ast$interpreter = ast.interpreter) == null ? void 0 : _ast$interpreter.value) != null ? _ast$interpreter$valu : null,
169
+ comments: ast.comments,
170
+ tokens: ast.tokens,
171
+ docblock: ast.docblock
172
+ }), code];
173
+ }
174
+
175
+ function convertExport(stmt, context) {
176
+ switch (stmt.type) {
177
+ case 'ExportNamedDeclaration':
178
+ {
179
+ return convertExportNamedDeclaration(stmt, context);
180
+ }
181
+
182
+ case 'ExportDefaultDeclaration':
183
+ {
184
+ return convertExportDefaultDeclaration(stmt, context);
185
+ }
186
+
187
+ case 'ExportAllDeclaration':
188
+ case 'DeclareExportAllDeclaration':
189
+ {
190
+ return [(0, _hermesTransform.asDetachedNode)(stmt), []];
191
+ }
192
+
193
+ case 'DeclareExportDeclaration':
194
+ case 'DeclareModuleExports':
195
+ {
196
+ return [(0, _hermesTransform.asDetachedNode)(stmt), (0, _FlowAnalyze.analyzeTypeDependencies)(stmt, context)];
197
+ }
198
+
199
+ case 'ExpressionStatement':
200
+ {
201
+ const expr = stmt.expression;
202
+
203
+ if (expr.type === 'AssignmentExpression' && expr.left.type === 'MemberExpression') {
204
+ const member = expr.left;
205
+
206
+ if ( // exports.A = 1;
207
+ member.object.type === 'Identifier' && member.object.name === 'exports' || // module.exports.A = 1;
208
+ member.object.type === 'MemberExpression' && member.object.object.type === 'Identifier' && member.object.object.name === 'module' && member.object.property.type === 'Identifier' && member.object.property.name === 'exports') {
209
+ throw (0, _ErrorUtils.translationError)(stmt, `convertExport: Named CommonJS exports not supported. Use either \`module.exports = {...}\` or ES6 exports.`, context);
210
+ }
211
+
212
+ if ( // exports.A = 1;
213
+ member.object.type === 'Identifier' && member.object.name === 'module' && member.property.type === 'Identifier' && member.property.name === 'exports') {
214
+ const [typeAnnotation, deps] = convertExpressionToTypeAnnotation(expr.right, context);
215
+ return [_hermesTransform.t.DeclareModuleExports({
216
+ typeAnnotation: _hermesTransform.t.TypeAnnotation({
217
+ typeAnnotation
218
+ })
219
+ }), deps];
220
+ }
221
+ }
222
+
223
+ return null;
224
+ }
225
+
226
+ default:
227
+ {
228
+ // Skip non exported functions
229
+ return null;
230
+ }
231
+ }
232
+ }
233
+
234
+ function stripUnusedDefs(detachedStmt, usedDeps, context) {
235
+ // $FlowExpectedError[incompatible-type]
236
+ const stmt = detachedStmt;
237
+
238
+ switch (stmt.type) {
239
+ case 'ImportDeclaration':
240
+ {
241
+ const resultSpecfiers = stmt.specifiers.filter(spec => usedDeps.has(spec.local.name));
242
+
243
+ if (resultSpecfiers.length === 0) {
244
+ throw (0, _ErrorUtils.translationError)(stmt, `stripUnusedDefs ImportDeclaration: No specifiers remaining`, context);
245
+ }
246
+
247
+ if (resultSpecfiers.length !== stmt.specifiers.length) {
248
+ return _hermesTransform.t.ImportDeclaration({
249
+ specifiers: resultSpecfiers,
250
+ importKind: stmt.importKind,
251
+ source: stmt.source,
252
+ assertions: stmt.assertions
253
+ });
254
+ }
255
+
256
+ return detachedStmt;
257
+ }
258
+
259
+ default:
260
+ {
261
+ return detachedStmt;
262
+ }
263
+ }
264
+ }
265
+
266
+ function convertStatement(stmt, context) {
267
+ switch (stmt.type) {
268
+ case 'FunctionDeclaration':
269
+ {
270
+ const [result, deps] = convertFunctionDeclation(stmt, context);
271
+ return [result, deps];
272
+ }
273
+
274
+ case 'ClassDeclaration':
275
+ {
276
+ const [result, deps] = convertClassDeclaration(stmt, context);
277
+ return [result, deps];
278
+ }
279
+
280
+ case 'InterfaceDeclaration':
281
+ {
282
+ const [result, deps] = convertInterfaceDeclaration(stmt, context);
283
+ return [result, deps];
284
+ }
285
+
286
+ case 'TypeAlias':
287
+ {
288
+ const [result, deps] = convertTypeAlias(stmt, context);
289
+ return [result, deps];
290
+ }
291
+
292
+ case 'OpaqueType':
293
+ {
294
+ const [result, deps] = convertOpaqueType(stmt, context);
295
+ return [result, deps];
296
+ }
297
+
298
+ case 'ImportDeclaration':
299
+ {
300
+ const [result, deps] = convertImportDeclaration(stmt, context);
301
+ return [result, deps];
302
+ }
303
+
304
+ case 'VariableDeclaration':
305
+ {
306
+ const [result, deps] = convertVariableDeclaration(stmt, context);
307
+ return [result, deps];
308
+ }
309
+
310
+ case 'DeclareClass':
311
+ case 'DeclareVariable':
312
+ case 'DeclareFunction':
313
+ case 'DeclareModule':
314
+ case 'DeclareInterface':
315
+ case 'DeclareTypeAlias':
316
+ case 'DeclareOpaqueType':
317
+ case 'EnumDeclaration':
318
+ {
319
+ return [(0, _hermesTransform.asDetachedNode)(stmt), (0, _FlowAnalyze.analyzeTypeDependencies)(stmt, context)];
320
+ }
321
+
322
+ default:
323
+ {
324
+ throw (0, _ErrorUtils.translationError)(stmt, `Statement: Unsupported statement type of "${stmt.type}"`, context);
325
+ }
326
+ }
327
+ }
328
+
329
+ function convertExpressionToTypeAnnotation(expr, context) {
330
+ switch (expr.type) {
331
+ case 'TypeCastExpression':
332
+ {
333
+ const [resultExpr, deps] = convertTypeCastExpression(expr, context);
334
+ return [resultExpr, deps];
335
+ }
336
+
337
+ case 'Identifier':
338
+ {
339
+ return [_hermesTransform.t.GenericTypeAnnotation({
340
+ id: _hermesTransform.t.Identifier({
341
+ name: expr.name
342
+ })
343
+ }), (0, _FlowAnalyze.analyzeTypeDependencies)(expr, context)];
344
+ }
345
+
346
+ case 'Literal':
347
+ {
348
+ const [resultExpr, deps] = convertLiteral(expr, context);
349
+ return [resultExpr, deps];
350
+ }
351
+
352
+ case 'ObjectExpression':
353
+ {
354
+ const [resultExpr, deps] = convertObjectExpression(expr, context);
355
+ return [resultExpr, deps];
356
+ }
357
+
358
+ case 'ArrowFunctionExpression':
359
+ case 'FunctionExpression':
360
+ {
361
+ const [resultExpr, deps] = convertAFunction(expr, context);
362
+ return [resultExpr, deps];
363
+ }
364
+
365
+ default:
366
+ {
367
+ return [(0, _ErrorUtils.flowFixMeOrError)(expr, `convertExpressionToTypeAnnotation: Unsupported expression of type "${expr.type}", a type annotation is required.`, context), []];
368
+ }
369
+ }
370
+ }
371
+
372
+ function convertObjectExpression(expr, context) {
373
+ const [resultProperties, deps] = convertArray(expr.properties, prop => {
374
+ switch (prop.type) {
375
+ case 'SpreadElement':
376
+ {
377
+ const [resultExpr, deps] = convertExpressionToTypeAnnotation(prop.argument, context);
378
+ return [_hermesTransform.t.ObjectTypeSpreadProperty({
379
+ argument: resultExpr
380
+ }), deps];
381
+ }
382
+
383
+ case 'Property':
384
+ {
385
+ if (prop.key.type !== 'Identifier' && prop.key.type !== 'StringLiteral') {
386
+ throw (0, _ErrorUtils.translationError)(prop.key, `ObjectExpression Property: Unsupported key type of "${prop.key.type}"`, context);
387
+ }
388
+
389
+ if (prop.method === true) {
390
+ if (prop.value.type !== 'ArrowFunctionExpression' && prop.value.type !== 'FunctionExpression') {
391
+ throw (0, _ErrorUtils.translationError)(prop.key, `ObjectExpression Property: Expected method to have a function value, but got ${prop.value.type}`, context);
392
+ }
393
+
394
+ const [resultExpr, deps] = convertAFunction(prop.value, context);
395
+ return [_hermesTransform.t.ObjectTypeMethodSignature({
396
+ // $FlowFixMe[incompatible-call]
397
+ key: (0, _hermesTransform.asDetachedNode)(prop.key),
398
+ value: resultExpr
399
+ }), deps];
400
+ }
401
+
402
+ if (prop.kind === 'get' || prop.kind === 'set') {
403
+ if (prop.value.type !== 'ArrowFunctionExpression' && prop.value.type !== 'FunctionExpression') {
404
+ throw (0, _ErrorUtils.translationError)(prop.key, `ObjectExpression Property: Expected accessor to have a function value, but got ${prop.value.type}`, context);
405
+ }
406
+
407
+ const kind = prop.kind;
408
+ const [resultExpr, deps] = convertAFunction(prop.value, context);
409
+ return [_hermesTransform.t.ObjectTypeAccessorSignature({
410
+ // $FlowFixMe[incompatible-call]
411
+ key: (0, _hermesTransform.asDetachedNode)(prop.key),
412
+ kind,
413
+ value: resultExpr
414
+ }), deps];
415
+ }
416
+
417
+ const [resultExpr, deps] = convertExpressionToTypeAnnotation(prop.value, context);
418
+ return [_hermesTransform.t.ObjectTypePropertySignature({
419
+ // $FlowFixMe[incompatible-call]
420
+ key: (0, _hermesTransform.asDetachedNode)(prop.key),
421
+ value: resultExpr,
422
+ optional: false,
423
+ variance: null
424
+ }), deps];
425
+ }
426
+ }
427
+ });
428
+ return [_hermesTransform.t.ObjectTypeAnnotation({
429
+ inexact: false,
430
+ exact: false,
431
+ properties: resultProperties,
432
+ indexers: [],
433
+ callProperties: [],
434
+ internalSlots: []
435
+ }), deps];
436
+ }
437
+
438
+ function convertLiteral(expr, context) {
439
+ switch (expr.literalType) {
440
+ case 'bigint':
441
+ {
442
+ return [_hermesTransform.t.BigIntLiteralTypeAnnotation({
443
+ raw: expr.raw
444
+ }), []];
445
+ }
446
+
447
+ case 'boolean':
448
+ {
449
+ return [_hermesTransform.t.BooleanLiteralTypeAnnotation({
450
+ raw: expr.raw,
451
+ value: expr.value
452
+ }), []];
453
+ }
454
+
455
+ case 'null':
456
+ {
457
+ return [_hermesTransform.t.NullLiteralTypeAnnotation({}), []];
458
+ }
459
+
460
+ case 'numeric':
461
+ {
462
+ return [_hermesTransform.t.NumberLiteralTypeAnnotation({
463
+ raw: expr.raw,
464
+ value: expr.value
465
+ }), []];
466
+ }
467
+
468
+ case 'string':
469
+ {
470
+ return [_hermesTransform.t.StringLiteralTypeAnnotation({
471
+ raw: expr.raw,
472
+ value: expr.value
473
+ }), []];
474
+ }
475
+
476
+ case 'regexp':
477
+ {
478
+ return [_hermesTransform.t.GenericTypeAnnotation({
479
+ id: _hermesTransform.t.Identifier({
480
+ name: 'RegExp'
481
+ })
482
+ }), []];
483
+ }
484
+
485
+ default:
486
+ {
487
+ throw (0, _ErrorUtils.translationError)(expr, 'convertLiteral: Unsupported literal type.', context);
488
+ }
489
+ }
490
+ }
491
+
492
+ function convertExportDeclaration(decl, opts, context) {
493
+ switch (decl.type) {
494
+ case 'FunctionDeclaration':
495
+ {
496
+ const [declDecl, deps] = convertFunctionDeclation(decl, context);
497
+ return [opts.default ? _hermesTransform.t.DeclareExportDefaultDeclaration({
498
+ declaration: declDecl
499
+ }) : _hermesTransform.t.DeclareExportDeclarationNamedWithDeclaration({
500
+ declaration: declDecl
501
+ }), deps];
502
+ }
503
+
504
+ case 'ClassDeclaration':
505
+ {
506
+ const [declDecl, deps] = convertClassDeclaration(decl, context);
507
+ return [opts.default ? _hermesTransform.t.DeclareExportDefaultDeclaration({
508
+ declaration: declDecl
509
+ }) : _hermesTransform.t.DeclareExportDeclarationNamedWithDeclaration({
510
+ declaration: declDecl
511
+ }), deps];
512
+ }
513
+
514
+ case 'InterfaceDeclaration':
515
+ {
516
+ if (opts.default) {
517
+ throw (0, _ErrorUtils.translationError)(decl, 'ExportDeclaration: Default interface found, invalid AST.', context);
518
+ }
519
+
520
+ const [declDecl, deps] = convertInterfaceDeclaration(decl, context);
521
+ return [_hermesTransform.t.ExportNamedDeclarationWithDeclaration({
522
+ exportKind: 'type',
523
+ declaration: declDecl
524
+ }), deps];
525
+ }
526
+
527
+ case 'TypeAlias':
528
+ {
529
+ if (opts.default) {
530
+ throw (0, _ErrorUtils.translationError)(decl, 'ExportDeclaration: Default type alias found, invalid AST.', context);
531
+ }
532
+
533
+ const [declDecl, deps] = convertTypeAlias(decl, context);
534
+ return [_hermesTransform.t.ExportNamedDeclarationWithDeclaration({
535
+ exportKind: 'type',
536
+ declaration: declDecl
537
+ }), deps];
538
+ }
539
+
540
+ case 'OpaqueType':
541
+ {
542
+ if (opts.default) {
543
+ throw (0, _ErrorUtils.translationError)(decl, 'ExportDeclaration: Default opaque type found, invalid AST.', context);
544
+ }
545
+
546
+ const [declDecl, deps] = convertOpaqueType(decl, context);
547
+ return [_hermesTransform.t.DeclareExportDeclarationNamedWithDeclaration({
548
+ declaration: declDecl
549
+ }), deps];
550
+ }
551
+
552
+ case 'VariableDeclaration':
553
+ {
554
+ if (opts.default) {
555
+ throw (0, _ErrorUtils.translationError)(decl, 'ExportDeclaration: Default VariableDeclaration found, invalid AST.', context);
556
+ }
557
+
558
+ const [declDecl, deps] = convertVariableDeclaration(decl, context);
559
+ return [_hermesTransform.t.DeclareExportDeclarationNamedWithDeclaration({
560
+ declaration: declDecl
561
+ }), deps];
562
+ }
563
+
564
+ case 'EnumDeclaration':
565
+ {
566
+ return [_hermesTransform.t.ExportNamedDeclarationWithDeclaration({
567
+ exportKind: 'value',
568
+ declaration: (0, _hermesTransform.asDetachedNode)(decl)
569
+ }), []];
570
+ }
571
+
572
+ default:
573
+ {
574
+ if ((0, _hermesEstree.isExpression)(decl)) {
575
+ if (!opts.default) {
576
+ throw (0, _ErrorUtils.translationError)(decl, 'ExportDeclaration: Non default expression found, invalid AST.', context);
577
+ }
578
+
579
+ const [declDecl, deps] = convertExpressionToTypeAnnotation(decl, context);
580
+ return [_hermesTransform.t.DeclareExportDefaultDeclaration({
581
+ declaration: declDecl
582
+ }), deps];
583
+ }
584
+
585
+ throw (0, _ErrorUtils.translationError)(decl, `ExportDeclaration: Unsupported declaration of type "${decl.type}".`, context);
586
+ }
587
+ }
588
+ }
589
+
590
+ function convertExportDefaultDeclaration(stmt, context) {
591
+ return convertExportDeclaration(stmt.declaration, {
592
+ default: true
593
+ }, context);
594
+ }
595
+
596
+ function convertExportNamedDeclaration(stmt, context) {
597
+ const decl = stmt.declaration;
598
+
599
+ if (decl != null) {
600
+ return convertExportDeclaration(decl, {
601
+ default: false
602
+ }, context);
603
+ }
604
+
605
+ const resultSpecfiers = stmt.specifiers.map(spec => (0, _hermesTransform.asDetachedNode)(spec));
606
+ const specifiersDeps = stmt.source != null ? [] : stmt.specifiers.flatMap(({
607
+ local
608
+ }) => (0, _FlowAnalyze.analyzeTypeDependencies)(local, context));
609
+ return [_hermesTransform.t.ExportNamedDeclarationWithSpecifiers({
610
+ exportKind: stmt.exportKind,
611
+ source: (0, _hermesTransform.asDetachedNode)(stmt.source),
612
+ specifiers: resultSpecfiers
613
+ }), specifiersDeps];
614
+ }
615
+
616
+ function convertVariableDeclaration(stmt, context) {
617
+ const [first, ...rest] = stmt.declarations;
618
+
619
+ if (rest.length > 0) {
620
+ throw (0, _ErrorUtils.translationError)(stmt, `VariableDeclaration: more than one VariableDeclarators found`, context);
621
+ }
622
+
623
+ const id = first.id;
624
+
625
+ if (id.type !== 'Identifier') {
626
+ throw (0, _ErrorUtils.translationError)(id, `VariableDeclaration: unsupported destructing`, context);
627
+ }
628
+
629
+ const [resultTypeAnnotation, annotDeps] = (() => {
630
+ if (id.typeAnnotation != null) {
631
+ return convertTypeAnnotation(id.typeAnnotation, id, context);
632
+ }
633
+
634
+ const init = first.init;
635
+
636
+ if (init == null) {
637
+ return [(0, _ErrorUtils.flowFixMeOrError)(first, `VariableDeclaration: Type annotation missing`, context), []];
638
+ }
639
+
640
+ return convertExpressionToTypeAnnotation(init, context);
641
+ })();
642
+
643
+ return [_hermesTransform.t.DeclareVariable({
644
+ id: _hermesTransform.t.Identifier({
645
+ name: id.name,
646
+ typeAnnotation: _hermesTransform.t.TypeAnnotation({
647
+ typeAnnotation: resultTypeAnnotation
648
+ }),
649
+ optional: false
650
+ })
651
+ }), annotDeps];
652
+ }
653
+
654
+ function convertImportDeclaration(stmt, context) {
655
+ if (stmt.assertions.length > 0) {
656
+ throw (0, _ErrorUtils.translationError)(stmt, 'ImportDeclaration: assertions not supported', context);
657
+ }
658
+
659
+ return [_hermesTransform.t.ImportDeclaration({
660
+ specifiers: stmt.specifiers,
661
+ importKind: stmt.importKind,
662
+ source: stmt.source,
663
+ assertions: []
664
+ }), []];
665
+ }
666
+
667
+ function convertInterfaceDeclaration(interface_, context) {
668
+ return [(0, _hermesTransform.asDetachedNode)(interface_), (0, _FlowAnalyze.analyzeTypeDependencies)(interface_, context)];
669
+ }
670
+
671
+ function convertClassDeclaration(class_, context) {
672
+ const [resultTypeParams, typeParamsDeps] = convertTypeParameterDeclarationOrNull(class_.typeParameters, context);
673
+ const implementsDeps = class_.implements.flatMap(impl => (0, _FlowAnalyze.analyzeTypeDependencies)(impl, context));
674
+ const [resultSuperClass, superClassDeps] = convertSuperClass(class_.superClass, class_.superTypeParameters, context);
675
+ const [resultClassBody, bodyDeps] = convertClassBody(class_.body, context);
676
+
677
+ if (class_.decorators.length > 0) {
678
+ throw (0, _ErrorUtils.translationError)(class_, 'ClassDeclaration: decorators not supported', context);
679
+ }
680
+
681
+ return [_hermesTransform.t.DeclareClass({
682
+ // $FlowFixMe[incompatible-call]
683
+ id: (0, _hermesTransform.asDetachedNode)(class_.id),
684
+ typeParameters: resultTypeParams,
685
+ implements: class_.implements.map(impl => (0, _hermesTransform.asDetachedNode)(impl)),
686
+ extends: resultSuperClass == null ? [] : [resultSuperClass],
687
+ mixins: [],
688
+ body: resultClassBody
689
+ }), [...typeParamsDeps, ...implementsDeps, ...superClassDeps, ...bodyDeps]];
690
+ }
691
+
692
+ function convertSuperClass(superClass, superTypeParameters, context) {
693
+ if (superClass == null) {
694
+ return EMPTY_TRANSLATION_RESULT;
695
+ }
696
+
697
+ if (superClass.type !== 'Identifier') {
698
+ throw (0, _ErrorUtils.translationError)(superClass, `SuperClass: Non identifier super type of "${superClass.type}" not supported`, context);
699
+ }
700
+
701
+ const [resultTypeParams, typeParamsDeps] = convertTypeParameterInstantiationOrNull(superTypeParameters, context);
702
+ const superDeps = (0, _FlowAnalyze.analyzeTypeDependencies)(superClass, context);
703
+ return [_hermesTransform.t.InterfaceExtends({
704
+ id: (0, _hermesTransform.asDetachedNode)(superClass),
705
+ typeParameters: resultTypeParams
706
+ }), [...typeParamsDeps, ...superDeps]];
707
+ }
708
+
709
+ function convertClassBody(body, context) {
710
+ const [resultProperties, deps] = convertArray(body.body, member => convertClassMember(member, context));
711
+ return [_hermesTransform.t.ObjectTypeAnnotation({
712
+ inexact: false,
713
+ exact: false,
714
+ properties: resultProperties,
715
+ indexers: [],
716
+ callProperties: [],
717
+ internalSlots: []
718
+ }), deps];
719
+ }
720
+
721
+ function convertClassMember(member, context) {
722
+ switch (member.type) {
723
+ case 'PropertyDefinition':
724
+ {
725
+ // PrivateIdentifier's are not exposed so can be stripped.
726
+ if (member.key.type === 'PrivateIdentifier') {
727
+ return EMPTY_TRANSLATION_RESULT;
728
+ }
729
+
730
+ if (member.key.type !== 'Identifier' && member.key.type !== 'StringLiteral') {
731
+ throw (0, _ErrorUtils.translationError)(member.key, `ClassMember PropertyDefinition: Unsupported key type of "${member.key.type}"`, context);
732
+ }
733
+
734
+ const [resultTypeAnnotation, deps] = convertTypeAnnotation(member.typeAnnotation, member, context);
735
+ return [_hermesTransform.t.ObjectTypePropertySignature({
736
+ // $FlowFixMe[incompatible-call]
737
+ key: (0, _hermesTransform.asDetachedNode)(member.key),
738
+ value: resultTypeAnnotation,
739
+ optional: member.optional,
740
+ static: member.static,
741
+ variance: member.variance
742
+ }), deps];
743
+ }
744
+
745
+ case 'MethodDefinition':
746
+ {
747
+ // PrivateIdentifier's are not exposed so can be stripped.
748
+ if (member.key.type === 'PrivateIdentifier') {
749
+ return EMPTY_TRANSLATION_RESULT;
750
+ }
751
+
752
+ if (member.key.type !== 'Identifier' && member.key.type !== 'StringLiteral') {
753
+ throw (0, _ErrorUtils.translationError)(member.key, `ClassMember PropertyDefinition: Unsupported key type of "${member.key.type}"`, context);
754
+ }
755
+
756
+ const [resultValue, deps] = convertAFunction(member.value, context);
757
+
758
+ if (member.kind === 'get' || member.kind === 'set') {
759
+ // accessors are methods - but flow accessor signatures are properties
760
+ const kind = member.kind;
761
+ return [_hermesTransform.t.ObjectTypeAccessorSignature({
762
+ // $FlowFixMe[incompatible-call]
763
+ key: (0, _hermesTransform.asDetachedNode)(member.key),
764
+ value: resultValue,
765
+ static: member.static,
766
+ kind
767
+ }), deps];
768
+ }
769
+
770
+ return [_hermesTransform.t.ObjectTypeMethodSignature({
771
+ // $FlowFixMe[incompatible-call]
772
+ key: (0, _hermesTransform.asDetachedNode)(member.key),
773
+ value: resultValue,
774
+ static: member.static
775
+ }), deps];
776
+ }
777
+
778
+ default:
779
+ {
780
+ throw (0, _ErrorUtils.translationError)(member, `ClassMember: Unsupported member type of "${member.type}"`, context);
781
+ }
782
+ }
783
+ }
784
+
785
+ function convertFunctionDeclation(func, context) {
786
+ const id = func.id;
787
+
788
+ if (id == null) {
789
+ throw (0, _ErrorUtils.translationError)(func, `FunctionDeclaration: Missing name`, context);
790
+ }
791
+
792
+ const [resultFunc, funcDeps] = convertAFunction(func, context);
793
+
794
+ const [resultPredicate, predicateDeps] = (() => {
795
+ if (func.predicate == null) {
796
+ return EMPTY_TRANSLATION_RESULT;
797
+ }
798
+
799
+ const body = func.body.body;
800
+ const predicateExpr = body.length === 1 && body[0].type === 'ReturnStatement' && body[0].argument != null ? body[0].argument : null;
801
+
802
+ if (predicateExpr == null) {
803
+ throw (0, _ErrorUtils.translationError)(func, 'FunctionDeclation: Invalid predicate function.', context);
804
+ }
805
+
806
+ return [_hermesTransform.t.DeclaredPredicate({
807
+ value: (0, _hermesTransform.asDetachedNode)(predicateExpr)
808
+ }), (0, _FlowAnalyze.analyzeTypeDependencies)(predicateExpr, context)];
809
+ })();
810
+
811
+ return [_hermesTransform.t.DeclareFunction({
812
+ name: id.name,
813
+ functionType: resultFunc,
814
+ predicate: resultPredicate
815
+ }), [...funcDeps, ...predicateDeps]];
816
+ }
817
+
818
+ function convertAFunction(func, context) {
819
+ const returnType = (0, _FlowAnalyze.analyzeFunctionReturn)(func);
820
+ const [resultReturnType, returnDeps] = convertTypeAnnotation(returnType, func, context);
821
+ const [resultParams, restParam, paramsDeps] = convertFunctionParameters(func.params, context);
822
+ const [resultTypeParams, typeParamsDeps] = convertTypeParameterDeclarationOrNull(func.typeParameters, context);
823
+ return [_hermesTransform.t.FunctionTypeAnnotation({
824
+ params: resultParams,
825
+ returnType: resultReturnType,
826
+ rest: restParam,
827
+ typeParameters: resultTypeParams
828
+ }), [...paramsDeps, ...returnDeps, ...typeParamsDeps]];
829
+ }
830
+
831
+ function convertFunctionParameters(params, context) {
832
+ return params.reduce(([resultParams, restParam, paramsDeps], param) => {
833
+ switch (param.type) {
834
+ case 'Identifier':
835
+ case 'ArrayPattern':
836
+ case 'ObjectPattern':
837
+ {
838
+ const [resultParam, deps] = convertBindingNameToFunctionTypeParam(param, context);
839
+ return [[...resultParams, resultParam], restParam, [...paramsDeps, ...deps]];
840
+ }
841
+
842
+ case 'AssignmentPattern':
843
+ {
844
+ const [resultParam, deps] = convertBindingNameToFunctionTypeParam(param.left, context);
845
+ return [[...resultParams, resultParam], restParam, [...paramsDeps, ...deps]];
846
+ }
847
+
848
+ case 'RestElement':
849
+ {
850
+ if (restParam != null) {
851
+ throw (0, _ErrorUtils.translationError)(param, `FunctionParameter: Multiple rest elements found`, context);
852
+ }
853
+
854
+ const [resultParam, deps] = convertBindingNameToFunctionTypeParam( // $FlowFixMe[incompatible-call] I dont think these other cases are possible
855
+ param.argument, context);
856
+ return [resultParams, resultParam, [...paramsDeps, ...deps]];
857
+ }
858
+ }
859
+ }, [[], null, []]);
860
+ }
861
+
862
+ function convertBindingNameToFunctionTypeParam(pat, context) {
863
+ const name = pat.type === 'Identifier' ? pat.name : null;
864
+ const [resultParamTypeAnnotation, paramDeps] = convertTypeAnnotation(pat.typeAnnotation, pat, context);
865
+ return [_hermesTransform.t.FunctionTypeParam({
866
+ name: name != null ? _hermesTransform.t.Identifier({
867
+ name
868
+ }) : null,
869
+ typeAnnotation: resultParamTypeAnnotation,
870
+ optional: pat.type === 'Identifier' ? pat.optional : false
871
+ }), paramDeps];
872
+ }
873
+
874
+ function convertTypeAlias(typeAlias, context) {
875
+ const [typeAnnotationType, rightDeps] = convertTypeAnnotationType(typeAlias.right, typeAlias, context);
876
+ const [typeParameters, typeParamsDeps] = convertTypeParameterDeclarationOrNull(typeAlias.typeParameters, context);
877
+ return [_hermesTransform.t.TypeAlias({
878
+ right: typeAnnotationType,
879
+ id: (0, _hermesTransform.asDetachedNode)(typeAlias.id),
880
+ typeParameters
881
+ }), [...rightDeps, ...typeParamsDeps]];
882
+ }
883
+
884
+ function convertOpaqueType(opaqueType, context) {
885
+ const [resultSupertype, supertypeDeps] = convertTypeAnnotationTypeOrNull(opaqueType.supertype, context);
886
+ const [typeParameters, typeParamsDeps] = convertTypeParameterDeclarationOrNull(opaqueType.typeParameters, context);
887
+ return [_hermesTransform.t.DeclareOpaqueType({
888
+ id: (0, _hermesTransform.asDetachedNode)(opaqueType.id),
889
+ typeParameters,
890
+ supertype: resultSupertype
891
+ }), [...typeParamsDeps, ...supertypeDeps]];
892
+ }
893
+
894
+ function convertTypeCastExpression(typeCast, context) {
895
+ return convertTypeAnnotation(typeCast.typeAnnotation, typeCast, context);
896
+ }
897
+
898
+ function convertTypeAnnotation(annot, container, context) {
899
+ return convertTypeAnnotationType(annot == null ? void 0 : annot.typeAnnotation, container, context);
900
+ }
901
+
902
+ function convertTypeAnnotationType(annot, container, context) {
903
+ if (annot == null) {
904
+ return [(0, _ErrorUtils.flowFixMeOrError)(container, `TypeAnnotationType: Type annotation missing`, context), []];
905
+ }
906
+
907
+ return [(0, _hermesTransform.asDetachedNode)(annot), (0, _FlowAnalyze.analyzeTypeDependencies)(annot, context)];
908
+ }
909
+
910
+ function convertTypeAnnotationTypeOrNull(annot, context) {
911
+ if (annot == null) {
912
+ return EMPTY_TRANSLATION_RESULT;
913
+ }
914
+
915
+ return [(0, _hermesTransform.asDetachedNode)(annot), (0, _FlowAnalyze.analyzeTypeDependencies)(annot, context)];
916
+ }
917
+
918
+ function convertTypeParameterDeclarationOrNull(decl, context) {
919
+ if (decl == null) {
920
+ return EMPTY_TRANSLATION_RESULT;
921
+ }
922
+
923
+ return [(0, _hermesTransform.asDetachedNode)(decl), (0, _FlowAnalyze.analyzeTypeDependencies)(decl, context)];
924
+ }
925
+
926
+ function convertTypeParameterInstantiationOrNull(inst, context) {
927
+ if (inst == null) {
928
+ return EMPTY_TRANSLATION_RESULT;
929
+ }
930
+
931
+ return [(0, _hermesTransform.asDetachedNode)(inst), (0, _FlowAnalyze.analyzeTypeDependencies)(inst, context)];
932
+ }