flow-api-translator 0.28.1 → 0.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/TSDefToFlowDef.js.flow +1 -1
- package/dist/flowDefToTSDef.js +17 -9
- package/dist/flowDefToTSDef.js.flow +44 -38
- package/dist/flowToFlowDef.js +8 -8
- package/dist/flowToFlowDef.js.flow +47 -35
- package/dist/src/TSDefToFlowDef.js +1807 -0
- package/dist/src/flowDefToTSDef.js +3853 -0
- package/dist/src/flowImportTo.js +73 -0
- package/dist/src/flowToFlowDef.js +1220 -0
- package/dist/src/flowToJS.js +39 -0
- package/dist/src/index.js +114 -0
- package/dist/src/utils/DocblockUtils.js +33 -0
- package/dist/src/utils/ErrorUtils.js +103 -0
- package/dist/src/utils/FlowAnalyze.js +55 -0
- package/dist/src/utils/TranslationUtils.js +42 -0
- package/dist/src/utils/ts-estree-ast-types.js +30 -0
- package/dist/utils/ts-estree-ast-types.js.flow +1 -1
- package/package.json +5 -5
|
@@ -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
|
+
};
|