flow-api-translator 0.330.0 → 0.332.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/dist/TSDefToFlowDef.js +17 -7
- package/dist/TSDefToFlowDef.js.flow +18 -2
- package/dist/flowDefToTSDef.js +293 -80
- package/dist/flowDefToTSDef.js.flow +441 -123
- package/dist/flowToFlowDef.js +121 -2
- package/dist/flowToFlowDef.js.flow +244 -2
- package/dist/index.js +7 -6
- package/dist/index.js.flow +16 -4
- package/dist/src/TSDefToFlowDef.js +17 -7
- package/dist/src/flowDefToTSDef.js +293 -80
- package/dist/src/flowToFlowDef.js +121 -2
- package/dist/src/index.js +7 -6
- package/dist/src/utils/TSNodeUtils.js +20 -0
- package/dist/utils/TSNodeUtils.js +20 -0
- package/dist/utils/TSNodeUtils.js.flow +46 -1
- package/dist/utils/TranslationUtils.js.flow +16 -0
- package/package.json +5 -5
package/dist/flowToFlowDef.js
CHANGED
|
@@ -10,6 +10,120 @@ var _TranslationUtils = require("./utils/TranslationUtils");
|
|
|
10
10
|
var _ErrorUtils = require("./utils/ErrorUtils");
|
|
11
11
|
var _flowEstree = require("flow-estree");
|
|
12
12
|
const EMPTY_TRANSLATION_RESULT = [null, []];
|
|
13
|
+
function isDocComment(comment) {
|
|
14
|
+
return comment.type === 'Block' && comment.value.startsWith('*') && !/@(flow|noflow|format)\b/.test(comment.value) && !comment.value.includes('Copyright');
|
|
15
|
+
}
|
|
16
|
+
function findDefaultExport(body) {
|
|
17
|
+
for (const statement of body) {
|
|
18
|
+
if (statement.type === 'ExportDefaultDeclaration' || statement.type === 'DeclareExportDeclaration' && statement.default === true) {
|
|
19
|
+
return statement;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
function getExportedIdentifierName(defaultExport) {
|
|
25
|
+
const declaration = defaultExport.declaration;
|
|
26
|
+
if (declaration == null) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
let node = declaration;
|
|
30
|
+
while (node.type === 'AsExpression' || node.type === 'TypeCastExpression') {
|
|
31
|
+
node = node.expression;
|
|
32
|
+
}
|
|
33
|
+
if (node.type === 'TypeofTypeAnnotation') {
|
|
34
|
+
return node.argument.type === 'Identifier' ? node.argument.name : null;
|
|
35
|
+
}
|
|
36
|
+
return node.type === 'Identifier' ? node.name : null;
|
|
37
|
+
}
|
|
38
|
+
function findDeclarationByName(body, name) {
|
|
39
|
+
for (const statement of body) {
|
|
40
|
+
const declaration = statement.type === 'ExportNamedDeclaration' && statement.declaration != null ? statement.declaration : statement;
|
|
41
|
+
if ((declaration.type === 'ClassDeclaration' || declaration.type === 'FunctionDeclaration' || declaration.type === 'ComponentDeclaration') && declaration.id != null && declaration.id.name === name) {
|
|
42
|
+
return {
|
|
43
|
+
kind: declaration.type,
|
|
44
|
+
statement
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (declaration.type === 'VariableDeclaration' || declaration.type === 'DeclareVariable') {
|
|
48
|
+
for (const declarator of declaration.declarations) {
|
|
49
|
+
if (declarator.id.type === 'Identifier' && declarator.id.name === name) {
|
|
50
|
+
return {
|
|
51
|
+
kind: declaration.type,
|
|
52
|
+
statement
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
function findDisplayName(body, name) {
|
|
61
|
+
for (const statement of body) {
|
|
62
|
+
if (statement.type === 'ExpressionStatement' && statement.expression.type === 'AssignmentExpression') {
|
|
63
|
+
const {
|
|
64
|
+
left,
|
|
65
|
+
right
|
|
66
|
+
} = statement.expression;
|
|
67
|
+
if (left.type === 'MemberExpression' && left.object.type === 'Identifier' && left.object.name === name && left.property.type === 'Identifier' && left.property.name === 'displayName' && right.type === 'Literal' && typeof right.value === 'string') {
|
|
68
|
+
return right.value;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
function applyDefaultExportDocPlacement(body, translatedStatements, placement, code) {
|
|
75
|
+
if (placement === 'declaration') {
|
|
76
|
+
return code;
|
|
77
|
+
}
|
|
78
|
+
const defaultExport = findDefaultExport(body);
|
|
79
|
+
if (defaultExport == null || (0, _flowTransform.getLeadingCommentsForNode)(defaultExport).some(isDocComment)) {
|
|
80
|
+
return code;
|
|
81
|
+
}
|
|
82
|
+
const exportedName = getExportedIdentifierName(defaultExport);
|
|
83
|
+
if (exportedName == null) {
|
|
84
|
+
return code;
|
|
85
|
+
}
|
|
86
|
+
const exportedDeclaration = findDeclarationByName(body, exportedName);
|
|
87
|
+
if ((exportedDeclaration == null ? void 0 : exportedDeclaration.kind) === 'ClassDeclaration') {
|
|
88
|
+
return code;
|
|
89
|
+
}
|
|
90
|
+
const sources = [];
|
|
91
|
+
if (exportedDeclaration != null) {
|
|
92
|
+
sources.push(exportedDeclaration);
|
|
93
|
+
}
|
|
94
|
+
const displayName = findDisplayName(body, exportedName);
|
|
95
|
+
if (displayName != null && displayName !== exportedName) {
|
|
96
|
+
const displayNameDeclaration = findDeclarationByName(body, displayName);
|
|
97
|
+
if (displayNameDeclaration != null) {
|
|
98
|
+
sources.push(displayNameDeclaration);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const translatedDefaultExport = translatedStatements.get(defaultExport);
|
|
102
|
+
if (translatedDefaultExport == null) {
|
|
103
|
+
return code;
|
|
104
|
+
}
|
|
105
|
+
for (const source of sources) {
|
|
106
|
+
const docComments = (0, _flowTransform.getLeadingCommentsForNode)(source.statement).filter(isDocComment);
|
|
107
|
+
if (docComments.length === 0) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
let mutatedCode = code;
|
|
111
|
+
const clonedComments = docComments.map(comment => {
|
|
112
|
+
const clonedComment = (0, _flowTransform.cloneCommentWithMarkers)(comment);
|
|
113
|
+
mutatedCode = (0, _flowTransform.makeCommentOwnLine)(mutatedCode, clonedComment);
|
|
114
|
+
return clonedComment;
|
|
115
|
+
});
|
|
116
|
+
(0, _flowTransform.setCommentsOnNode)(translatedDefaultExport, [...(0, _flowTransform.getCommentsForNode)(translatedDefaultExport), ...clonedComments]);
|
|
117
|
+
if (placement === 'export') {
|
|
118
|
+
const translatedSource = translatedStatements.get(source.statement);
|
|
119
|
+
if (translatedSource != null) {
|
|
120
|
+
(0, _flowTransform.setCommentsOnNode)(translatedSource, (0, _flowTransform.getCommentsForNode)(translatedSource).filter(comment => !docComments.includes(comment)));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return mutatedCode;
|
|
124
|
+
}
|
|
125
|
+
return code;
|
|
126
|
+
}
|
|
13
127
|
function convertArray(items, convert) {
|
|
14
128
|
const resultItems = [];
|
|
15
129
|
const deps = [];
|
|
@@ -39,7 +153,7 @@ function transferProgramStatementProperties(stmt, orgStmt) {
|
|
|
39
153
|
stmt.loc = orgStmt.loc;
|
|
40
154
|
}
|
|
41
155
|
function flowToFlowDef(ast, code, scopeManager, opts) {
|
|
42
|
-
var _ast$interpreter$valu, _ast$interpreter;
|
|
156
|
+
var _opts$defaultExportDo, _ast$interpreter$valu, _ast$interpreter;
|
|
43
157
|
const context = (0, _TranslationUtils.createTranslationContext)(code, scopeManager, opts);
|
|
44
158
|
const translatedStatements = new Map();
|
|
45
159
|
function storeTranslatedStatement(stmt, orgStmt) {
|
|
@@ -100,9 +214,11 @@ function flowToFlowDef(ast, code, scopeManager, opts) {
|
|
|
100
214
|
if (translatedStatement != null) {
|
|
101
215
|
const optimizedStatement = stripUnusedDefs(translatedStatement, seenDeps, context);
|
|
102
216
|
transferProgramStatementProperties(optimizedStatement, stmt);
|
|
217
|
+
storeTranslatedStatement(optimizedStatement, stmt);
|
|
103
218
|
translatedBody.push(optimizedStatement);
|
|
104
219
|
}
|
|
105
220
|
}
|
|
221
|
+
const outputCode = applyDefaultExportDocPlacement(ast.body, translatedStatements, (_opts$defaultExportDo = opts.defaultExportDocPlacement) != null ? _opts$defaultExportDo : 'declaration', code);
|
|
106
222
|
return [_flowTransform.t.Program({
|
|
107
223
|
body: translatedBody,
|
|
108
224
|
sourceType: ast.sourceType,
|
|
@@ -110,7 +226,7 @@ function flowToFlowDef(ast, code, scopeManager, opts) {
|
|
|
110
226
|
comments: ast.comments,
|
|
111
227
|
tokens: ast.tokens,
|
|
112
228
|
docblock: ast.docblock
|
|
113
|
-
}),
|
|
229
|
+
}), outputCode];
|
|
114
230
|
}
|
|
115
231
|
function convertExport(stmt, context) {
|
|
116
232
|
switch (stmt.type) {
|
|
@@ -740,6 +856,9 @@ function convertSuperClass(superClass, superTypeArguments, context) {
|
|
|
740
856
|
{
|
|
741
857
|
const typeAnnotation = superClass.type === 'TypeCastExpression' ? superClass.typeAnnotation.typeAnnotation : superClass.typeAnnotation;
|
|
742
858
|
if (typeAnnotation.type === 'GenericTypeAnnotation') {
|
|
859
|
+
if (typeAnnotation.id.type === 'ImportType') {
|
|
860
|
+
throw (0, _ErrorUtils.translationError)(superClass, 'SuperClass: Import type not supported', context);
|
|
861
|
+
}
|
|
743
862
|
return convertSuperClassHelper((0, _flowTransform.asDetachedNode)(typeAnnotation.id), typeAnnotation, superTypeArguments, context);
|
|
744
863
|
}
|
|
745
864
|
if (typeAnnotation.type === 'TypeofTypeAnnotation') {
|
|
@@ -22,8 +22,10 @@ import type {
|
|
|
22
22
|
ComponentDeclaration,
|
|
23
23
|
ComponentParameter,
|
|
24
24
|
ComponentTypeParameter,
|
|
25
|
+
Comment,
|
|
25
26
|
DeclareClass,
|
|
26
27
|
DeclareComponent,
|
|
28
|
+
DeclareExportDeclaration,
|
|
27
29
|
DeclareHook,
|
|
28
30
|
DeclareFunction,
|
|
29
31
|
DeclareOpaqueType,
|
|
@@ -68,6 +70,7 @@ import type {
|
|
|
68
70
|
import type {ScopeManager} from 'flow-eslint';
|
|
69
71
|
import type {DetachedNode} from 'flow-transform';
|
|
70
72
|
import type {
|
|
73
|
+
DefaultExportDocPlacement,
|
|
71
74
|
Dep,
|
|
72
75
|
TranslationContext,
|
|
73
76
|
TranslationOptions,
|
|
@@ -79,7 +82,14 @@ import {
|
|
|
79
82
|
analyzeTypeDependencies,
|
|
80
83
|
} from './utils/FlowAnalyze';
|
|
81
84
|
import {createTranslationContext} from './utils/TranslationUtils';
|
|
82
|
-
import {
|
|
85
|
+
import {
|
|
86
|
+
asDetachedNode,
|
|
87
|
+
cloneCommentWithMarkers,
|
|
88
|
+
getCommentsForNode,
|
|
89
|
+
getLeadingCommentsForNode,
|
|
90
|
+
makeCommentOwnLine,
|
|
91
|
+
setCommentsOnNode,
|
|
92
|
+
} from 'flow-transform';
|
|
83
93
|
import {translationError, flowFixMeOrError} from './utils/ErrorUtils';
|
|
84
94
|
import {
|
|
85
95
|
isExpression,
|
|
@@ -103,6 +113,223 @@ type TranslatedResult<T> = [DetachedNode<T>, TranslatedDeps];
|
|
|
103
113
|
|
|
104
114
|
type ProgramStatement = Statement | ModuleDeclaration;
|
|
105
115
|
|
|
116
|
+
type DefaultExport = ExportDefaultDeclaration | DeclareExportDeclaration;
|
|
117
|
+
|
|
118
|
+
type DeclarationMatch = {
|
|
119
|
+
kind: string,
|
|
120
|
+
statement: ProgramStatement,
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* A JSDoc-style block comment (`/** ... *\/`), excluding the license/pragma
|
|
125
|
+
* docblock, which describes the module rather than the exported value.
|
|
126
|
+
*/
|
|
127
|
+
function isDocComment(comment: Comment): boolean {
|
|
128
|
+
return (
|
|
129
|
+
comment.type === 'Block' &&
|
|
130
|
+
comment.value.startsWith('*') &&
|
|
131
|
+
!/@(flow|noflow|format)\b/.test(comment.value) &&
|
|
132
|
+
!comment.value.includes('Copyright')
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function findDefaultExport(
|
|
137
|
+
body: ReadonlyArray<ProgramStatement>,
|
|
138
|
+
): ?DefaultExport {
|
|
139
|
+
for (const statement of body) {
|
|
140
|
+
if (
|
|
141
|
+
statement.type === 'ExportDefaultDeclaration' ||
|
|
142
|
+
(statement.type === 'DeclareExportDeclaration' &&
|
|
143
|
+
statement.default === true)
|
|
144
|
+
) {
|
|
145
|
+
return statement;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Name of the exported identifier, unwrapping `as` casts and the `typeof X`
|
|
153
|
+
* form. Returns `null` for inline/anonymous declarations.
|
|
154
|
+
*/
|
|
155
|
+
function getExportedIdentifierName(defaultExport: DefaultExport): ?string {
|
|
156
|
+
const declaration = defaultExport.declaration;
|
|
157
|
+
if (declaration == null) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
let node: ESNode = declaration;
|
|
162
|
+
while (node.type === 'AsExpression' || node.type === 'TypeCastExpression') {
|
|
163
|
+
node = node.expression;
|
|
164
|
+
}
|
|
165
|
+
if (node.type === 'TypeofTypeAnnotation') {
|
|
166
|
+
return node.argument.type === 'Identifier' ? node.argument.name : null;
|
|
167
|
+
}
|
|
168
|
+
return node.type === 'Identifier' ? node.name : null;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function findDeclarationByName(
|
|
172
|
+
body: ReadonlyArray<ProgramStatement>,
|
|
173
|
+
name: string,
|
|
174
|
+
): ?DeclarationMatch {
|
|
175
|
+
for (const statement of body) {
|
|
176
|
+
const declaration =
|
|
177
|
+
statement.type === 'ExportNamedDeclaration' &&
|
|
178
|
+
statement.declaration != null
|
|
179
|
+
? statement.declaration
|
|
180
|
+
: statement;
|
|
181
|
+
|
|
182
|
+
if (
|
|
183
|
+
(declaration.type === 'ClassDeclaration' ||
|
|
184
|
+
declaration.type === 'FunctionDeclaration' ||
|
|
185
|
+
declaration.type === 'ComponentDeclaration') &&
|
|
186
|
+
declaration.id != null &&
|
|
187
|
+
declaration.id.name === name
|
|
188
|
+
) {
|
|
189
|
+
return {kind: declaration.type, statement};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// `DeclareVariable` is `declare const X` in an already-declaration input
|
|
193
|
+
if (
|
|
194
|
+
declaration.type === 'VariableDeclaration' ||
|
|
195
|
+
declaration.type === 'DeclareVariable'
|
|
196
|
+
) {
|
|
197
|
+
for (const declarator of declaration.declarations) {
|
|
198
|
+
if (
|
|
199
|
+
declarator.id.type === 'Identifier' &&
|
|
200
|
+
declarator.id.name === name
|
|
201
|
+
) {
|
|
202
|
+
return {kind: declaration.type, statement};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function findDisplayName(
|
|
211
|
+
body: ReadonlyArray<ProgramStatement>,
|
|
212
|
+
name: string,
|
|
213
|
+
): ?string {
|
|
214
|
+
for (const statement of body) {
|
|
215
|
+
if (
|
|
216
|
+
statement.type === 'ExpressionStatement' &&
|
|
217
|
+
statement.expression.type === 'AssignmentExpression'
|
|
218
|
+
) {
|
|
219
|
+
const {left, right} = statement.expression;
|
|
220
|
+
if (
|
|
221
|
+
left.type === 'MemberExpression' &&
|
|
222
|
+
left.object.type === 'Identifier' &&
|
|
223
|
+
left.object.name === name &&
|
|
224
|
+
left.property.type === 'Identifier' &&
|
|
225
|
+
left.property.name === 'displayName' &&
|
|
226
|
+
right.type === 'Literal' &&
|
|
227
|
+
typeof right.value === 'string'
|
|
228
|
+
) {
|
|
229
|
+
return right.value;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Associate a declaration's documentation with the module's default export.
|
|
238
|
+
*
|
|
239
|
+
* Stripping the runtime implementation leaves the documentation on the
|
|
240
|
+
* declaration the `export default` aliases via `typeof`, which is not the
|
|
241
|
+
* symbol TypeScript resolves a default re-export to. Returns the (possibly
|
|
242
|
+
* mutated) source text, since cloned comments need a range that makes prettier
|
|
243
|
+
* print them on their own line.
|
|
244
|
+
*/
|
|
245
|
+
function applyDefaultExportDocPlacement(
|
|
246
|
+
body: ReadonlyArray<ProgramStatement>,
|
|
247
|
+
translatedStatements: Map<ProgramStatement, DetachedNode<ProgramStatement>>,
|
|
248
|
+
placement: DefaultExportDocPlacement,
|
|
249
|
+
code: string,
|
|
250
|
+
): string {
|
|
251
|
+
if (placement === 'declaration') {
|
|
252
|
+
return code;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const defaultExport = findDefaultExport(body);
|
|
256
|
+
if (
|
|
257
|
+
defaultExport == null ||
|
|
258
|
+
// Leave already-documented (and inline) default exports untouched.
|
|
259
|
+
getLeadingCommentsForNode(defaultExport).some(isDocComment)
|
|
260
|
+
) {
|
|
261
|
+
return code;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const exportedName = getExportedIdentifierName(defaultExport);
|
|
265
|
+
if (exportedName == null) {
|
|
266
|
+
return code;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const exportedDeclaration = findDeclarationByName(body, exportedName);
|
|
270
|
+
// A directly-exported class keeps its declaration, where TypeScript already
|
|
271
|
+
// resolves the documentation; moving it would hide it.
|
|
272
|
+
if (exportedDeclaration?.kind === 'ClassDeclaration') {
|
|
273
|
+
return code;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Statements whose leading comment may document the default export, in
|
|
277
|
+
// priority order.
|
|
278
|
+
const sources: Array<DeclarationMatch> = [];
|
|
279
|
+
if (exportedDeclaration != null) {
|
|
280
|
+
sources.push(exportedDeclaration);
|
|
281
|
+
}
|
|
282
|
+
// Renamed wrappers (e.g. `memo`-wrapped) carry the documentation on the
|
|
283
|
+
// declaration matching the display name.
|
|
284
|
+
const displayName = findDisplayName(body, exportedName);
|
|
285
|
+
if (displayName != null && displayName !== exportedName) {
|
|
286
|
+
const displayNameDeclaration = findDeclarationByName(body, displayName);
|
|
287
|
+
if (displayNameDeclaration != null) {
|
|
288
|
+
sources.push(displayNameDeclaration);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const translatedDefaultExport = translatedStatements.get(defaultExport);
|
|
293
|
+
if (translatedDefaultExport == null) {
|
|
294
|
+
return code;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
for (const source of sources) {
|
|
298
|
+
const docComments = getLeadingCommentsForNode(source.statement).filter(
|
|
299
|
+
isDocComment,
|
|
300
|
+
);
|
|
301
|
+
if (docComments.length === 0) {
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
let mutatedCode = code;
|
|
306
|
+
const clonedComments = docComments.map(comment => {
|
|
307
|
+
const clonedComment = cloneCommentWithMarkers(comment);
|
|
308
|
+
mutatedCode = makeCommentOwnLine(mutatedCode, clonedComment);
|
|
309
|
+
return clonedComment;
|
|
310
|
+
});
|
|
311
|
+
setCommentsOnNode(translatedDefaultExport, [
|
|
312
|
+
...getCommentsForNode(translatedDefaultExport),
|
|
313
|
+
...clonedComments,
|
|
314
|
+
]);
|
|
315
|
+
|
|
316
|
+
if (placement === 'export') {
|
|
317
|
+
const translatedSource = translatedStatements.get(source.statement);
|
|
318
|
+
if (translatedSource != null) {
|
|
319
|
+
setCommentsOnNode(
|
|
320
|
+
translatedSource,
|
|
321
|
+
getCommentsForNode(translatedSource).filter(
|
|
322
|
+
comment => !docComments.includes(comment),
|
|
323
|
+
),
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return mutatedCode;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return code;
|
|
331
|
+
}
|
|
332
|
+
|
|
106
333
|
function convertArray<TIn, TOut>(
|
|
107
334
|
items: ReadonlyArray<TIn>,
|
|
108
335
|
convert: TIn => TranslatedResultOrNull<TOut>,
|
|
@@ -246,10 +473,18 @@ export default function flowToFlowDef(
|
|
|
246
473
|
context,
|
|
247
474
|
);
|
|
248
475
|
transferProgramStatementProperties(optimizedStatement, stmt);
|
|
476
|
+
storeTranslatedStatement(optimizedStatement, stmt);
|
|
249
477
|
translatedBody.push(optimizedStatement);
|
|
250
478
|
}
|
|
251
479
|
}
|
|
252
480
|
|
|
481
|
+
const outputCode = applyDefaultExportDocPlacement(
|
|
482
|
+
ast.body,
|
|
483
|
+
translatedStatements,
|
|
484
|
+
opts.defaultExportDocPlacement ?? 'declaration',
|
|
485
|
+
code,
|
|
486
|
+
);
|
|
487
|
+
|
|
253
488
|
return [
|
|
254
489
|
t.Program({
|
|
255
490
|
body: translatedBody,
|
|
@@ -259,7 +494,7 @@ export default function flowToFlowDef(
|
|
|
259
494
|
tokens: ast.tokens,
|
|
260
495
|
docblock: ast.docblock,
|
|
261
496
|
}),
|
|
262
|
-
|
|
497
|
+
outputCode,
|
|
263
498
|
];
|
|
264
499
|
}
|
|
265
500
|
|
|
@@ -1193,6 +1428,13 @@ function convertSuperClass(
|
|
|
1193
1428
|
: superClass.typeAnnotation;
|
|
1194
1429
|
|
|
1195
1430
|
if (typeAnnotation.type === 'GenericTypeAnnotation') {
|
|
1431
|
+
if (typeAnnotation.id.type === 'ImportType') {
|
|
1432
|
+
throw translationError(
|
|
1433
|
+
superClass,
|
|
1434
|
+
'SuperClass: Import type not supported',
|
|
1435
|
+
context,
|
|
1436
|
+
);
|
|
1437
|
+
}
|
|
1196
1438
|
return convertSuperClassHelper(
|
|
1197
1439
|
asDetachedNode(typeAnnotation.id),
|
|
1198
1440
|
typeAnnotation,
|
package/dist/index.js
CHANGED
|
@@ -24,21 +24,22 @@ async function translateFlowToFlowDef(code, prettierOptions = {}, opts) {
|
|
|
24
24
|
scopeManager
|
|
25
25
|
} = await (0, _flowTransform.parse)(code);
|
|
26
26
|
const [flowDefAst, mutatedCode] = (0, _flowToFlowDef.default)(ast, code, scopeManager, {
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
...opts,
|
|
28
|
+
recoverFromErrors: true
|
|
29
29
|
});
|
|
30
30
|
return (0, _flowTransform.print)(flowDefAst, mutatedCode, prettierOptions);
|
|
31
31
|
}
|
|
32
|
-
async function translateFlowToTSDef(code, prettierOptions = {}) {
|
|
33
|
-
const flowDefCode = await translateFlowToFlowDef(code, prettierOptions);
|
|
34
|
-
return translateFlowDefToTSDef(flowDefCode, prettierOptions);
|
|
32
|
+
async function translateFlowToTSDef(code, prettierOptions = {}, opts) {
|
|
33
|
+
const flowDefCode = await translateFlowToFlowDef(code, prettierOptions, opts);
|
|
34
|
+
return translateFlowDefToTSDef(flowDefCode, prettierOptions, opts);
|
|
35
35
|
}
|
|
36
|
-
async function translateFlowDefToTSDef(code, prettierOptions = {}) {
|
|
36
|
+
async function translateFlowDefToTSDef(code, prettierOptions = {}, opts) {
|
|
37
37
|
const {
|
|
38
38
|
ast,
|
|
39
39
|
scopeManager
|
|
40
40
|
} = await (0, _flowTransform.parse)(code);
|
|
41
41
|
const [tsAST, mutatedCode] = (0, _flowDefToTSDef.flowDefToTSDef)(code, ast, scopeManager, {
|
|
42
|
+
...opts,
|
|
42
43
|
recoverFromErrors: true
|
|
43
44
|
});
|
|
44
45
|
return (0, _flowTransform.print)(tsAST, mutatedCode, {
|
package/dist/index.js.flow
CHANGED
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
'use strict';
|
|
12
12
|
|
|
13
13
|
import type {MapperOptions} from './flowImportTo';
|
|
14
|
+
import type {
|
|
15
|
+
DefaultExportDocPlacement,
|
|
16
|
+
TranslationOptions,
|
|
17
|
+
} from './utils/TranslationUtils';
|
|
14
18
|
|
|
15
19
|
import {parse, print} from 'flow-transform';
|
|
16
20
|
import {parse as parseTS} from '@typescript-eslint/parser';
|
|
@@ -21,16 +25,21 @@ import {flowToJS} from './flowToJS';
|
|
|
21
25
|
import {flowImportTo} from './flowImportTo';
|
|
22
26
|
import {TSDefToFlowDef} from './TSDefToFlowDef';
|
|
23
27
|
|
|
28
|
+
// `recoverFromErrors` is deliberately not exposed: the entry points always recover.
|
|
29
|
+
export type TranslateOptions = Omit<TranslationOptions, 'recoverFromErrors'>;
|
|
30
|
+
|
|
31
|
+
export type {DefaultExportDocPlacement};
|
|
32
|
+
|
|
24
33
|
export async function translateFlowToFlowDef(
|
|
25
34
|
code: string,
|
|
26
35
|
prettierOptions: {...} = {},
|
|
27
|
-
opts?:
|
|
36
|
+
opts?: TranslateOptions,
|
|
28
37
|
): Promise<string> {
|
|
29
38
|
const {ast, scopeManager} = await parse(code);
|
|
30
39
|
|
|
31
40
|
const [flowDefAst, mutatedCode] = flowToFlowDef(ast, code, scopeManager, {
|
|
41
|
+
...opts,
|
|
32
42
|
recoverFromErrors: true,
|
|
33
|
-
mungeUnderscores: opts?.mungeUnderscores,
|
|
34
43
|
});
|
|
35
44
|
|
|
36
45
|
return print(flowDefAst, mutatedCode, prettierOptions);
|
|
@@ -39,18 +48,21 @@ export async function translateFlowToFlowDef(
|
|
|
39
48
|
export async function translateFlowToTSDef(
|
|
40
49
|
code: string,
|
|
41
50
|
prettierOptions: {...} = {},
|
|
51
|
+
opts?: TranslateOptions,
|
|
42
52
|
): Promise<string> {
|
|
43
|
-
const flowDefCode = await translateFlowToFlowDef(code, prettierOptions);
|
|
53
|
+
const flowDefCode = await translateFlowToFlowDef(code, prettierOptions, opts);
|
|
44
54
|
|
|
45
|
-
return translateFlowDefToTSDef(flowDefCode, prettierOptions);
|
|
55
|
+
return translateFlowDefToTSDef(flowDefCode, prettierOptions, opts);
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
export async function translateFlowDefToTSDef(
|
|
49
59
|
code: string,
|
|
50
60
|
prettierOptions: {...} = {},
|
|
61
|
+
opts?: TranslateOptions,
|
|
51
62
|
): Promise<string> {
|
|
52
63
|
const {ast, scopeManager} = await parse(code);
|
|
53
64
|
const [tsAST, mutatedCode] = flowDefToTSDef(code, ast, scopeManager, {
|
|
65
|
+
...opts,
|
|
54
66
|
recoverFromErrors: true,
|
|
55
67
|
});
|
|
56
68
|
|
|
@@ -264,11 +264,15 @@ const getTransforms = (originalCode, opts) => {
|
|
|
264
264
|
value: node.source.value,
|
|
265
265
|
raw: node.source.raw
|
|
266
266
|
});
|
|
267
|
-
const specifiers = node.specifiers.map(specifier =>
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
267
|
+
const specifiers = node.specifiers.map(specifier => {
|
|
268
|
+
var _specifier$exportKind;
|
|
269
|
+
return constructFlowNode({
|
|
270
|
+
type: 'ExportSpecifier',
|
|
271
|
+
local: Transform.Identifier(specifier.local),
|
|
272
|
+
exported: Transform.Identifier(specifier.exported),
|
|
273
|
+
exportKind: (_specifier$exportKind = specifier.exportKind) != null ? _specifier$exportKind : 'value'
|
|
274
|
+
});
|
|
275
|
+
});
|
|
272
276
|
return constructFlowNode({
|
|
273
277
|
type: 'DeclareExportDeclaration',
|
|
274
278
|
declaration: null,
|
|
@@ -318,7 +322,8 @@ const getTransforms = (originalCode, opts) => {
|
|
|
318
322
|
specifiers: [constructFlowNode({
|
|
319
323
|
type: 'ExportSpecifier',
|
|
320
324
|
local: decl.id,
|
|
321
|
-
exported: decl.id
|
|
325
|
+
exported: decl.id,
|
|
326
|
+
exportKind: 'value'
|
|
322
327
|
})]
|
|
323
328
|
})];
|
|
324
329
|
}
|
|
@@ -814,6 +819,9 @@ const getTransforms = (originalCode, opts) => {
|
|
|
814
819
|
const namesRev = [];
|
|
815
820
|
while (qualifier.type !== 'Identifier') {
|
|
816
821
|
namesRev.push(qualifier.id.name);
|
|
822
|
+
if (qualifier.qualification.type === 'ImportType') {
|
|
823
|
+
return unsupportedAnnotation(node, 'nested import types in import type qualifiers');
|
|
824
|
+
}
|
|
817
825
|
qualifier = qualifier.qualification;
|
|
818
826
|
}
|
|
819
827
|
namesRev.push(qualifier.name);
|
|
@@ -949,10 +957,12 @@ const getTransforms = (originalCode, opts) => {
|
|
|
949
957
|
keyTparam,
|
|
950
958
|
propType: Transform.TSTypeAnnotationOpt(node.typeAnnotation),
|
|
951
959
|
sourceType,
|
|
952
|
-
|
|
960
|
+
nameType: node.nameType == null ? null : Transform.TSTypeAnnotation(node.nameType),
|
|
961
|
+
variance: node.readonly != null && node.readonly !== false ? constructFlowNode({
|
|
953
962
|
type: 'Variance',
|
|
954
963
|
kind: 'plus'
|
|
955
964
|
}) : null,
|
|
965
|
+
varianceOp: node.readonly === '+' ? '+' : node.readonly === '-' ? '-' : null,
|
|
956
966
|
optional: node.optional === '+' ? 'PlusOptional' : node.optional === '-' ? 'MinusOptional' : Boolean(node.optional) ? 'Optional' : null
|
|
957
967
|
});
|
|
958
968
|
return constructFlowNode({
|