hermes-transform 0.8.0 → 0.9.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/ESLINT_LICENCE +19 -0
- package/PRETTIER_LICENCE +7 -0
- package/dist/detachedNode.js +96 -20
- package/dist/detachedNode.js.flow +105 -17
- package/dist/generated/TransformModifySignatures.js.flow +1113 -0
- package/dist/generated/node-types.js +627 -852
- package/dist/generated/node-types.js.flow +969 -1154
- package/dist/generated/special-case-node-types.js +71 -77
- package/dist/generated/special-case-node-types.js.flow +104 -88
- package/dist/transform/TransformContext.js +34 -11
- package/dist/transform/TransformContext.js.flow +90 -33
- package/dist/transform/comments/comments.js +23 -5
- package/dist/transform/comments/comments.js.flow +23 -3
- package/dist/transform/getTransformedAST.js +15 -0
- package/dist/transform/getTransformedAST.js.flow +19 -1
- package/dist/transform/mutations/InsertStatement.js +1 -0
- package/dist/transform/mutations/InsertStatement.js.flow +1 -0
- package/dist/transform/mutations/ReplaceNode.js +7 -2
- package/dist/transform/mutations/ReplaceNode.js.flow +5 -2
- package/dist/transform/mutations/ReplaceStatementWithMany.js.flow +5 -2
- package/dist/traverse/NodeEventGenerator.js.flow +1 -1
- package/dist/traverse/traverse.js.flow +1 -1
- package/package.json +8 -4
|
@@ -18,8 +18,9 @@ import type {
|
|
|
18
18
|
Statement,
|
|
19
19
|
TypeAnnotationType,
|
|
20
20
|
} from 'hermes-estree';
|
|
21
|
-
import type {DetachedNode} from '../detachedNode';
|
|
21
|
+
import type {DetachedNode, MaybeDetachedNode} from '../detachedNode';
|
|
22
22
|
import type {TransformCloneSignatures} from '../generated/TransformCloneSignatures';
|
|
23
|
+
import type {TransformModifySignatures} from '../generated/TransformModifySignatures';
|
|
23
24
|
import type {TransformReplaceSignatures} from '../generated/TransformReplaceSignatures';
|
|
24
25
|
import type {TraversalContext} from '../traverse/traverse';
|
|
25
26
|
import type {AddCommentsMutation} from './mutations/AddComments';
|
|
@@ -29,9 +30,12 @@ import type {RemoveCommentMutation} from './mutations/RemoveComment';
|
|
|
29
30
|
import type {RemoveNodeMutation} from './mutations/RemoveNode';
|
|
30
31
|
import type {RemoveStatementMutation} from './mutations/RemoveStatement';
|
|
31
32
|
import type {ReplaceNodeMutation} from './mutations/ReplaceNode';
|
|
32
|
-
import type {
|
|
33
|
+
import type {
|
|
34
|
+
ReplaceStatementWithManyMutation,
|
|
35
|
+
ReplaceStatementWithManyMutationNodes,
|
|
36
|
+
} from './mutations/ReplaceStatementWithMany';
|
|
33
37
|
|
|
34
|
-
import {deepCloneNode, shallowCloneNode} from '../detachedNode';
|
|
38
|
+
import {asDetachedNode, deepCloneNode, shallowCloneNode} from '../detachedNode';
|
|
35
39
|
import {
|
|
36
40
|
CommentPlacement,
|
|
37
41
|
getCommentsForNode,
|
|
@@ -103,6 +107,8 @@ type TransformCloneAPIs = $ReadOnly<{
|
|
|
103
107
|
shallowCloneArray: {
|
|
104
108
|
<T: ESNode>(node: $ReadOnlyArray<T>): $ReadOnlyArray<DetachedNode<T>>,
|
|
105
109
|
<T: ESNode>(node: ?$ReadOnlyArray<T>): ?$ReadOnlyArray<DetachedNode<T>>,
|
|
110
|
+
<T: ESNode>(node: $ReadOnlyArray<?T>): $ReadOnlyArray<DetachedNode<?T>>,
|
|
111
|
+
<T: ESNode>(node: ?$ReadOnlyArray<?T>): ?$ReadOnlyArray<DetachedNode<?T>>,
|
|
106
112
|
},
|
|
107
113
|
|
|
108
114
|
/**
|
|
@@ -148,14 +154,14 @@ type TransformCommentAPIs = $ReadOnly<{
|
|
|
148
154
|
*/
|
|
149
155
|
cloneCommentsTo: (
|
|
150
156
|
target: ESNode,
|
|
151
|
-
destination:
|
|
157
|
+
destination: MaybeDetachedNode<ESNode>,
|
|
152
158
|
) => void,
|
|
153
159
|
|
|
154
160
|
/**
|
|
155
161
|
* Add comments on the line before a specified node.
|
|
156
162
|
*/
|
|
157
163
|
addLeadingComments: (
|
|
158
|
-
node:
|
|
164
|
+
node: MaybeDetachedNode<ESNode>,
|
|
159
165
|
comments: SingleOrArray<Comment>,
|
|
160
166
|
) => void,
|
|
161
167
|
|
|
@@ -163,7 +169,7 @@ type TransformCommentAPIs = $ReadOnly<{
|
|
|
163
169
|
* Add comments inline before a specified node.
|
|
164
170
|
*/
|
|
165
171
|
addLeadingInlineComments: (
|
|
166
|
-
node:
|
|
172
|
+
node: MaybeDetachedNode<ESNode>,
|
|
167
173
|
comments: SingleOrArray<Comment>,
|
|
168
174
|
) => void,
|
|
169
175
|
|
|
@@ -171,7 +177,7 @@ type TransformCommentAPIs = $ReadOnly<{
|
|
|
171
177
|
* Add comments on the line after a specified node.
|
|
172
178
|
*/
|
|
173
179
|
addTrailingComments: (
|
|
174
|
-
node:
|
|
180
|
+
node: MaybeDetachedNode<ESNode>,
|
|
175
181
|
comments: SingleOrArray<Comment>,
|
|
176
182
|
) => void,
|
|
177
183
|
|
|
@@ -179,7 +185,7 @@ type TransformCommentAPIs = $ReadOnly<{
|
|
|
179
185
|
* Add comments inline after a specified node.
|
|
180
186
|
*/
|
|
181
187
|
addTrailingInlineComments: (
|
|
182
|
-
node:
|
|
188
|
+
node: MaybeDetachedNode<ESNode>,
|
|
183
189
|
comments: SingleOrArray<Comment>,
|
|
184
190
|
) => void,
|
|
185
191
|
|
|
@@ -197,7 +203,7 @@ type TransformInsertAPIs = $ReadOnly<{
|
|
|
197
203
|
insertAfterStatement: (
|
|
198
204
|
target: InsertStatementMutation['target'],
|
|
199
205
|
nodeToInsert: SingleOrArray<
|
|
200
|
-
|
|
206
|
+
MaybeDetachedNode<InsertStatementMutation['target']>,
|
|
201
207
|
>,
|
|
202
208
|
) => void,
|
|
203
209
|
|
|
@@ -208,11 +214,19 @@ type TransformInsertAPIs = $ReadOnly<{
|
|
|
208
214
|
insertBeforeStatement: (
|
|
209
215
|
target: InsertStatementMutation['target'],
|
|
210
216
|
nodeToInsert: SingleOrArray<
|
|
211
|
-
|
|
217
|
+
MaybeDetachedNode<InsertStatementMutation['target']>,
|
|
212
218
|
>,
|
|
213
219
|
) => void,
|
|
214
220
|
}>;
|
|
215
221
|
|
|
222
|
+
type TransformModifyAPIs = $ReadOnly<{
|
|
223
|
+
/**
|
|
224
|
+
* Modifies a given node in place.
|
|
225
|
+
* This is equivalent to doing a replace with a shallow clone with overrides.
|
|
226
|
+
*/
|
|
227
|
+
modifyNodeInPlace: TransformModifySignatures,
|
|
228
|
+
}>;
|
|
229
|
+
|
|
216
230
|
type TransformRemoveAPIs = $ReadOnly<{
|
|
217
231
|
/**
|
|
218
232
|
* Removes a given node from the AST.
|
|
@@ -236,37 +250,37 @@ type TransformReplaceAPIs = $ReadOnly<{
|
|
|
236
250
|
// Expressions may be replaced with other expressions
|
|
237
251
|
(
|
|
238
252
|
target: Expression,
|
|
239
|
-
nodeToReplaceWith:
|
|
253
|
+
nodeToReplaceWith: MaybeDetachedNode<Expression>,
|
|
240
254
|
options?: ReplaceNodeOptions,
|
|
241
255
|
): void,
|
|
242
256
|
// Module declarations may be replaced with statements or other module declarations
|
|
243
257
|
(
|
|
244
258
|
target: ModuleDeclaration,
|
|
245
|
-
nodeToReplaceWith:
|
|
259
|
+
nodeToReplaceWith: MaybeDetachedNode<ModuleDeclaration | Statement>,
|
|
246
260
|
options?: ReplaceNodeOptions,
|
|
247
261
|
): void,
|
|
248
262
|
// Statement maybe be replaced with statements or module declarations
|
|
249
263
|
(
|
|
250
264
|
target: Statement,
|
|
251
|
-
nodeToReplaceWith:
|
|
265
|
+
nodeToReplaceWith: MaybeDetachedNode<ModuleDeclaration | Statement>,
|
|
252
266
|
options?: ReplaceNodeOptions,
|
|
253
267
|
): void,
|
|
254
268
|
// Types maybe be replaced with other types
|
|
255
269
|
(
|
|
256
270
|
target: TypeAnnotationType,
|
|
257
|
-
nodeToReplaceWith:
|
|
271
|
+
nodeToReplaceWith: MaybeDetachedNode<TypeAnnotationType>,
|
|
258
272
|
options?: ReplaceNodeOptions,
|
|
259
273
|
): void,
|
|
260
274
|
// Class members may be replaced with other class members
|
|
261
275
|
(
|
|
262
276
|
target: ClassMember,
|
|
263
|
-
nodeToReplaceWith:
|
|
277
|
+
nodeToReplaceWith: MaybeDetachedNode<ClassMember>,
|
|
264
278
|
options?: ReplaceNodeOptions,
|
|
265
279
|
): void,
|
|
266
280
|
// Function params amy be replace with other function params
|
|
267
281
|
(
|
|
268
282
|
target: FunctionParameter,
|
|
269
|
-
nodeToReplaceWith:
|
|
283
|
+
nodeToReplaceWith: MaybeDetachedNode<FunctionParameter>,
|
|
270
284
|
options?: ReplaceNodeOptions,
|
|
271
285
|
): void,
|
|
272
286
|
} & TransformReplaceSignatures, // allow like-for-like replacements as well
|
|
@@ -277,7 +291,9 @@ type TransformReplaceAPIs = $ReadOnly<{
|
|
|
277
291
|
*/
|
|
278
292
|
replaceStatementWithMany: (
|
|
279
293
|
target: ReplaceStatementWithManyMutation['target'],
|
|
280
|
-
nodesToReplaceWith:
|
|
294
|
+
nodesToReplaceWith: $ReadOnlyArray<
|
|
295
|
+
MaybeDetachedNode<ReplaceStatementWithManyMutationNodes>,
|
|
296
|
+
>,
|
|
281
297
|
options?: {
|
|
282
298
|
/**
|
|
283
299
|
* Moves the comments from the target node to the first node in the array.
|
|
@@ -296,6 +312,7 @@ export type TransformContextAdditions = $ReadOnly<{
|
|
|
296
312
|
...TransformCommentAPIs,
|
|
297
313
|
...TransformCloneAPIs,
|
|
298
314
|
...TransformInsertAPIs,
|
|
315
|
+
...TransformModifyAPIs,
|
|
299
316
|
...TransformRemoveAPIs,
|
|
300
317
|
...TransformReplaceAPIs,
|
|
301
318
|
}>;
|
|
@@ -321,14 +338,15 @@ export function getTransformContext(): TransformContextAdditions {
|
|
|
321
338
|
return null;
|
|
322
339
|
}
|
|
323
340
|
|
|
324
|
-
return shallowCloneNode(node);
|
|
341
|
+
return shallowCloneNode(node, {});
|
|
325
342
|
}: TransformCloneAPIs['shallowCloneNode']),
|
|
326
343
|
|
|
327
|
-
// $FlowExpectedError[incompatible-exact]
|
|
328
344
|
shallowCloneNodeWithOverrides: ((
|
|
329
345
|
node: ?ESNode,
|
|
330
|
-
newProps?: $ReadOnly<{...}
|
|
331
|
-
):
|
|
346
|
+
newProps?: $ReadOnly<{...}> = {},
|
|
347
|
+
): // $FlowExpectedError[incompatible-cast]
|
|
348
|
+
// $FlowExpectedError[prop-missing]
|
|
349
|
+
?DetachedNode<ESNode> => {
|
|
332
350
|
if (node == null) {
|
|
333
351
|
return null;
|
|
334
352
|
}
|
|
@@ -337,14 +355,20 @@ export function getTransformContext(): TransformContextAdditions {
|
|
|
337
355
|
}: TransformCloneAPIs['shallowCloneNodeWithOverrides']),
|
|
338
356
|
|
|
339
357
|
shallowCloneArray: (<T: ESNode>(
|
|
340
|
-
nodes: ?$ReadOnlyArray
|
|
358
|
+
nodes: ?$ReadOnlyArray<?T>,
|
|
341
359
|
): // $FlowExpectedError[incompatible-cast]
|
|
342
|
-
?$ReadOnlyArray<DetachedNode
|
|
360
|
+
?$ReadOnlyArray<DetachedNode<?ESNode>> => {
|
|
343
361
|
if (nodes == null) {
|
|
344
362
|
return null;
|
|
345
363
|
}
|
|
346
364
|
|
|
347
|
-
return nodes.map(node =>
|
|
365
|
+
return nodes.map(node => {
|
|
366
|
+
if (node == null) {
|
|
367
|
+
// $FlowExpectedError[incompatible-call]
|
|
368
|
+
return node;
|
|
369
|
+
}
|
|
370
|
+
return shallowCloneNode<T>(node, {});
|
|
371
|
+
});
|
|
348
372
|
}: TransformCloneAPIs['shallowCloneArray']),
|
|
349
373
|
|
|
350
374
|
deepCloneNode: ((
|
|
@@ -355,14 +379,15 @@ export function getTransformContext(): TransformContextAdditions {
|
|
|
355
379
|
return null;
|
|
356
380
|
}
|
|
357
381
|
|
|
358
|
-
return deepCloneNode(node);
|
|
382
|
+
return deepCloneNode(node, {});
|
|
359
383
|
}: TransformCloneAPIs['deepCloneNode']),
|
|
360
384
|
|
|
361
|
-
// $FlowExpectedError[incompatible-exact]
|
|
362
385
|
deepCloneNodeWithOverrides: ((
|
|
363
386
|
node: ?ESNode,
|
|
364
|
-
newProps?: $ReadOnly<{...}
|
|
365
|
-
):
|
|
387
|
+
newProps?: $ReadOnly<{...}> = {},
|
|
388
|
+
): // $FlowExpectedError[incompatible-cast]
|
|
389
|
+
// $FlowExpectedError[prop-missing]
|
|
390
|
+
?DetachedNode<ESNode> => {
|
|
366
391
|
if (node == null) {
|
|
367
392
|
return null;
|
|
368
393
|
}
|
|
@@ -444,13 +469,25 @@ export function getTransformContext(): TransformContextAdditions {
|
|
|
444
469
|
const insertAPIs: TransformInsertAPIs = {
|
|
445
470
|
insertAfterStatement: ((target, nodesToInsert): void => {
|
|
446
471
|
pushMutation(
|
|
447
|
-
createInsertStatementMutation(
|
|
472
|
+
createInsertStatementMutation(
|
|
473
|
+
'after',
|
|
474
|
+
target,
|
|
475
|
+
toArray(nodesToInsert).map(n =>
|
|
476
|
+
asDetachedNode(n, {useDeepClone: true}),
|
|
477
|
+
),
|
|
478
|
+
),
|
|
448
479
|
);
|
|
449
480
|
}: TransformInsertAPIs['insertBeforeStatement']),
|
|
450
481
|
|
|
451
482
|
insertBeforeStatement: ((target, nodesToInsert): void => {
|
|
452
483
|
pushMutation(
|
|
453
|
-
createInsertStatementMutation(
|
|
484
|
+
createInsertStatementMutation(
|
|
485
|
+
'before',
|
|
486
|
+
target,
|
|
487
|
+
toArray(nodesToInsert).map(n =>
|
|
488
|
+
asDetachedNode(n, {useDeepClone: true}),
|
|
489
|
+
),
|
|
490
|
+
),
|
|
454
491
|
);
|
|
455
492
|
}: TransformInsertAPIs['insertBeforeStatement']),
|
|
456
493
|
};
|
|
@@ -466,11 +503,15 @@ export function getTransformContext(): TransformContextAdditions {
|
|
|
466
503
|
const replaceAPIs: TransformReplaceAPIs = {
|
|
467
504
|
replaceNode: ((
|
|
468
505
|
target: ESNode,
|
|
469
|
-
nodeToReplaceWith:
|
|
506
|
+
nodeToReplaceWith: MaybeDetachedNode<ESNode>,
|
|
470
507
|
options?: ReplaceNodeOptions,
|
|
471
508
|
): void => {
|
|
472
509
|
pushMutation(
|
|
473
|
-
createReplaceNodeMutation(
|
|
510
|
+
createReplaceNodeMutation(
|
|
511
|
+
target,
|
|
512
|
+
asDetachedNode(nodeToReplaceWith),
|
|
513
|
+
options,
|
|
514
|
+
),
|
|
474
515
|
);
|
|
475
516
|
}: TransformReplaceAPIs['replaceNode']),
|
|
476
517
|
|
|
@@ -482,12 +523,27 @@ export function getTransformContext(): TransformContextAdditions {
|
|
|
482
523
|
pushMutation(
|
|
483
524
|
createReplaceStatementWithManyMutation(
|
|
484
525
|
target,
|
|
485
|
-
nodesToReplaceWith,
|
|
526
|
+
nodesToReplaceWith.map(n => asDetachedNode(n)),
|
|
486
527
|
options,
|
|
487
528
|
),
|
|
488
529
|
);
|
|
489
530
|
}: TransformReplaceAPIs['replaceStatementWithMany']),
|
|
490
531
|
};
|
|
532
|
+
const modifyAPIs: TransformModifyAPIs = {
|
|
533
|
+
modifyNodeInPlace: ((
|
|
534
|
+
node: ?ESNode,
|
|
535
|
+
newProps?: $ReadOnly<{...}> = {},
|
|
536
|
+
options?: ReplaceNodeOptions,
|
|
537
|
+
): void => {
|
|
538
|
+
if (node == null) {
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
const cloned = shallowCloneNode(node, newProps, {preserveLocation: true});
|
|
543
|
+
// $FlowExpectedError[incompatible-call]
|
|
544
|
+
replaceAPIs.replaceNode(node, cloned, options);
|
|
545
|
+
}: TransformModifyAPIs['modifyNodeInPlace']),
|
|
546
|
+
};
|
|
491
547
|
|
|
492
548
|
return {
|
|
493
549
|
mutations,
|
|
@@ -500,6 +556,7 @@ export function getTransformContext(): TransformContextAdditions {
|
|
|
500
556
|
...cloneAPIs,
|
|
501
557
|
...commentAPIs,
|
|
502
558
|
...insertAPIs,
|
|
559
|
+
...modifyAPIs,
|
|
503
560
|
...removeAPIs,
|
|
504
561
|
...replaceAPIs,
|
|
505
562
|
};
|
|
@@ -11,6 +11,8 @@ exports.attachComments = attachComments;
|
|
|
11
11
|
exports.cloneComment = cloneComment;
|
|
12
12
|
exports.cloneCommentWithMarkers = cloneCommentWithMarkers;
|
|
13
13
|
exports.getCommentsForNode = getCommentsForNode;
|
|
14
|
+
exports.getLeadingCommentsForNode = getLeadingCommentsForNode;
|
|
15
|
+
exports.getTrailingCommentsForNode = getTrailingCommentsForNode;
|
|
14
16
|
exports.isLeadingComment = isLeadingComment;
|
|
15
17
|
exports.isTrailingComment = isTrailingComment;
|
|
16
18
|
exports.moveCommentsToNewNode = moveCommentsToNewNode;
|
|
@@ -62,13 +64,21 @@ function setCommentsOnNode(node, comments) {
|
|
|
62
64
|
node.comments = comments;
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
function addCommentsToNode(node, comments) {
|
|
67
|
+
function addCommentsToNode(node, comments, side = 'trailing') {
|
|
66
68
|
var _node$comments;
|
|
67
69
|
|
|
68
|
-
// $FlowExpectedError - this property is secretly added by prettier.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
node.comments
|
|
70
|
+
// $FlowExpectedError[prop-missing] - this property is secretly added by prettier.
|
|
71
|
+
// $FlowExpectedError[cannot-write]
|
|
72
|
+
// $FlowExpectedError[incompatible-use]
|
|
73
|
+
node.comments = (_node$comments = node.comments) != null ? _node$comments : [];
|
|
74
|
+
|
|
75
|
+
if (side === 'leading') {
|
|
76
|
+
// $FlowExpectedError[incompatible-cast]
|
|
77
|
+
node.comments.unshift(...comments);
|
|
78
|
+
} else {
|
|
79
|
+
// $FlowExpectedError[incompatible-cast]
|
|
80
|
+
node.comments.push(...comments);
|
|
81
|
+
}
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
function getCommentsForNode(node) {
|
|
@@ -88,6 +98,14 @@ function isTrailingComment(comment) {
|
|
|
88
98
|
return comment.trailing === true;
|
|
89
99
|
}
|
|
90
100
|
|
|
101
|
+
function getLeadingCommentsForNode(node) {
|
|
102
|
+
return getCommentsForNode(node).filter(isLeadingComment);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function getTrailingCommentsForNode(node) {
|
|
106
|
+
return getCommentsForNode(node).filter(isTrailingComment);
|
|
107
|
+
}
|
|
108
|
+
|
|
91
109
|
function addComment(node, comment, placement) {
|
|
92
110
|
switch (placement) {
|
|
93
111
|
case CommentPlacement.LEADING_OWN_LINE:
|
|
@@ -65,11 +65,19 @@ export function setCommentsOnNode(
|
|
|
65
65
|
export function addCommentsToNode(
|
|
66
66
|
node: ESNode | DetachedNode<ESNode>,
|
|
67
67
|
comments: $ReadOnlyArray<Comment>,
|
|
68
|
+
side?: 'leading' | 'trailing' = 'trailing',
|
|
68
69
|
): void {
|
|
69
|
-
// $FlowExpectedError - this property is secretly added by prettier.
|
|
70
|
+
// $FlowExpectedError[prop-missing] - this property is secretly added by prettier.
|
|
71
|
+
// $FlowExpectedError[cannot-write]
|
|
72
|
+
// $FlowExpectedError[incompatible-use]
|
|
70
73
|
node.comments = node.comments ?? [];
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
if (side === 'leading') {
|
|
75
|
+
// $FlowExpectedError[incompatible-cast]
|
|
76
|
+
(node.comments: Array<Comment>).unshift(...comments);
|
|
77
|
+
} else {
|
|
78
|
+
// $FlowExpectedError[incompatible-cast]
|
|
79
|
+
(node.comments: Array<Comment>).push(...comments);
|
|
80
|
+
}
|
|
73
81
|
}
|
|
74
82
|
|
|
75
83
|
export function getCommentsForNode(
|
|
@@ -88,6 +96,18 @@ export function isTrailingComment(comment: Comment): boolean {
|
|
|
88
96
|
return comment.trailing === true;
|
|
89
97
|
}
|
|
90
98
|
|
|
99
|
+
export function getLeadingCommentsForNode(
|
|
100
|
+
node: ESNode | DetachedNode<ESNode>,
|
|
101
|
+
): $ReadOnlyArray<Comment> {
|
|
102
|
+
return getCommentsForNode(node).filter(isLeadingComment);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function getTrailingCommentsForNode(
|
|
106
|
+
node: ESNode | DetachedNode<ESNode>,
|
|
107
|
+
): $ReadOnlyArray<Comment> {
|
|
108
|
+
return getCommentsForNode(node).filter(isTrailingComment);
|
|
109
|
+
}
|
|
110
|
+
|
|
91
111
|
export function addComment(
|
|
92
112
|
node: ESNode | DetachedNode<ESNode>,
|
|
93
113
|
comment: Comment,
|
|
@@ -122,6 +122,21 @@ function getTransformedAST(code, visitors) {
|
|
|
122
122
|
if (mutationRoot) {
|
|
123
123
|
(0, _detachedNode.updateAllParentPointers)(mutationRoot);
|
|
124
124
|
}
|
|
125
|
+
} // if the very first node in the program is replaced, it will take the docblock with it
|
|
126
|
+
// this is bad as it means we'll lose `@format`, ``, licence, etc.
|
|
127
|
+
// so this hack just makes sure that we keep the docblock
|
|
128
|
+
// note that we do this **BEFORE** the comment mutations in case someone intentionally
|
|
129
|
+
// wants to remove the docblock comment for some weird reason
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
if (ast.docblock != null && ast.body.length > 0) {
|
|
133
|
+
const firstNode = ast.body[0];
|
|
134
|
+
const docblockComment = ast.docblock.comment;
|
|
135
|
+
const leadingComments = (0, _comments.getLeadingCommentsForNode)(firstNode);
|
|
136
|
+
|
|
137
|
+
if (!leadingComments.includes(docblockComment)) {
|
|
138
|
+
(0, _comments.addCommentsToNode)(firstNode, [docblockComment], 'leading');
|
|
139
|
+
}
|
|
125
140
|
} // remove the comments
|
|
126
141
|
// this is done at the end because it requires a complete traversal of the AST
|
|
127
142
|
// so that we can find relevant node's attachment array
|
|
@@ -19,7 +19,11 @@ import {updateAllParentPointers} from '../detachedNode';
|
|
|
19
19
|
import {traverseWithContext} from '../traverse/traverse';
|
|
20
20
|
import {MutationContext} from './MutationContext';
|
|
21
21
|
import {getTransformContext} from './TransformContext';
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
addCommentsToNode,
|
|
24
|
+
attachComments,
|
|
25
|
+
getLeadingCommentsForNode,
|
|
26
|
+
} from './comments/comments';
|
|
23
27
|
import {performAddCommentsMutation} from './mutations/AddComments';
|
|
24
28
|
import {performCloneCommentsToMutation} from './mutations/CloneCommentsTo';
|
|
25
29
|
import {performInsertStatementMutation} from './mutations/InsertStatement';
|
|
@@ -120,6 +124,20 @@ export function getTransformedAST(
|
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
126
|
|
|
127
|
+
// if the very first node in the program is replaced, it will take the docblock with it
|
|
128
|
+
// this is bad as it means we'll lose `@format`, `@flow`, licence, etc.
|
|
129
|
+
// so this hack just makes sure that we keep the docblock
|
|
130
|
+
// note that we do this **BEFORE** the comment mutations in case someone intentionally
|
|
131
|
+
// wants to remove the docblock comment for some weird reason
|
|
132
|
+
if (ast.docblock != null && ast.body.length > 0) {
|
|
133
|
+
const firstNode = ast.body[0];
|
|
134
|
+
const docblockComment = ast.docblock.comment;
|
|
135
|
+
const leadingComments = getLeadingCommentsForNode(firstNode);
|
|
136
|
+
if (!leadingComments.includes(docblockComment)) {
|
|
137
|
+
addCommentsToNode(firstNode, [docblockComment], 'leading');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
123
141
|
// remove the comments
|
|
124
142
|
// this is done at the end because it requires a complete traversal of the AST
|
|
125
143
|
// so that we can find relevant node's attachment array
|
|
@@ -12,6 +12,8 @@ var _comments = require("../comments/comments");
|
|
|
12
12
|
|
|
13
13
|
var _Errors = require("../Errors");
|
|
14
14
|
|
|
15
|
+
var _detachedNode = require("../../detachedNode");
|
|
16
|
+
|
|
15
17
|
var _getVisitorKeys = require("../../getVisitorKeys");
|
|
16
18
|
|
|
17
19
|
/**
|
|
@@ -71,7 +73,10 @@ function getParentKey(target) {
|
|
|
71
73
|
}
|
|
72
74
|
} else if (Array.isArray(parent[key])) {
|
|
73
75
|
for (let i = 0; i < parent[key].length; i += 1) {
|
|
74
|
-
|
|
76
|
+
const current = parent[key][i];
|
|
77
|
+
const originalNode = (0, _detachedNode.getOriginalNode)(current);
|
|
78
|
+
|
|
79
|
+
if (current === target || originalNode === target) {
|
|
75
80
|
return {
|
|
76
81
|
type: 'array',
|
|
77
82
|
parent,
|
|
@@ -84,5 +89,5 @@ function getParentKey(target) {
|
|
|
84
89
|
} // this shouldn't happen ever
|
|
85
90
|
|
|
86
91
|
|
|
87
|
-
throw new _Errors.InvalidReplacementError(`Expected to find the ${target.type} as a direct child of the ${
|
|
92
|
+
throw new _Errors.InvalidReplacementError(`Expected to find the ${target.type} as a direct child of the ${parent.type}.`);
|
|
88
93
|
}
|
|
@@ -15,6 +15,7 @@ import type {DetachedNode} from '../../detachedNode';
|
|
|
15
15
|
import {replaceInArray} from './utils/arrayUtils';
|
|
16
16
|
import {moveCommentsToNewNode} from '../comments/comments';
|
|
17
17
|
import {InvalidReplacementError} from '../Errors';
|
|
18
|
+
import {getOriginalNode} from '../../detachedNode';
|
|
18
19
|
import {getVisitorKeys, isNode} from '../../getVisitorKeys';
|
|
19
20
|
|
|
20
21
|
export type ReplaceNodeMutation = $ReadOnly<{
|
|
@@ -99,7 +100,9 @@ function getParentKey(target: ESNode): $ReadOnly<
|
|
|
99
100
|
}
|
|
100
101
|
} else if (Array.isArray(parent[key])) {
|
|
101
102
|
for (let i = 0; i < parent[key].length; i += 1) {
|
|
102
|
-
|
|
103
|
+
const current = parent[key][i];
|
|
104
|
+
const originalNode = getOriginalNode(current);
|
|
105
|
+
if (current === target || originalNode === target) {
|
|
103
106
|
return {type: 'array', parent, key, targetIndex: i};
|
|
104
107
|
}
|
|
105
108
|
}
|
|
@@ -108,6 +111,6 @@ function getParentKey(target: ESNode): $ReadOnly<
|
|
|
108
111
|
|
|
109
112
|
// this shouldn't happen ever
|
|
110
113
|
throw new InvalidReplacementError(
|
|
111
|
-
`Expected to find the ${target.type} as a direct child of the ${
|
|
114
|
+
`Expected to find the ${target.type} as a direct child of the ${parent.type}.`,
|
|
112
115
|
);
|
|
113
116
|
}
|
|
@@ -19,11 +19,14 @@ import {moveCommentsToNewNode} from '../comments/comments';
|
|
|
19
19
|
import {InvalidReplacementError} from '../Errors';
|
|
20
20
|
import * as t from '../../generated/node-types';
|
|
21
21
|
|
|
22
|
+
export type ReplaceStatementWithManyMutationNodes =
|
|
23
|
+
| ModuleDeclaration
|
|
24
|
+
| Statement;
|
|
22
25
|
export type ReplaceStatementWithManyMutation = $ReadOnly<{
|
|
23
26
|
type: 'replaceStatementWithMany',
|
|
24
|
-
target:
|
|
27
|
+
target: ReplaceStatementWithManyMutationNodes,
|
|
25
28
|
nodesToReplaceWith: $ReadOnlyArray<
|
|
26
|
-
DetachedNode<
|
|
29
|
+
DetachedNode<ReplaceStatementWithManyMutationNodes>,
|
|
27
30
|
>,
|
|
28
31
|
keepComments: boolean,
|
|
29
32
|
}>;
|
|
@@ -34,7 +34,7 @@ type ParsedSelector = $ReadOnly<{
|
|
|
34
34
|
|
|
35
35
|
const ESQUERY_OPTIONS: ESQueryOptions = Object.freeze({
|
|
36
36
|
visitorKeys: VisitorKeys,
|
|
37
|
-
fallback: node => {
|
|
37
|
+
fallback: (node: ESNode) => {
|
|
38
38
|
throw new Error(`No visitor keys found for node type "${node.type}".`);
|
|
39
39
|
},
|
|
40
40
|
});
|
|
@@ -140,7 +140,7 @@ export function traverseWithContext<T = TraversalContextBase>(
|
|
|
140
140
|
scopeManager.getDeclaredVariables(node),
|
|
141
141
|
|
|
142
142
|
getBinding: (name: string) => {
|
|
143
|
-
let currentScope = getScope();
|
|
143
|
+
let currentScope: null | Scope = getScope();
|
|
144
144
|
|
|
145
145
|
while (currentScope != null) {
|
|
146
146
|
for (const variable of currentScope.variables) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hermes-transform",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Tools built on top of Hermes-ESTree to enable codebase transformation",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,13 +12,17 @@
|
|
|
12
12
|
"@babel/code-frame": "^7.16.0",
|
|
13
13
|
"esquery": "^1.4.0",
|
|
14
14
|
"flow-enums-runtime": "^0.0.6",
|
|
15
|
-
"hermes-eslint": "0.
|
|
16
|
-
"hermes-estree": "0.
|
|
15
|
+
"hermes-eslint": "0.9.0",
|
|
16
|
+
"hermes-estree": "0.9.0"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"prettier": "^2.4.1"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
|
-
"dist"
|
|
22
|
+
"dist",
|
|
23
|
+
"LICENCE",
|
|
24
|
+
"ESLINT_LICENCE",
|
|
25
|
+
"PRETTIER_LICENCE",
|
|
26
|
+
"README.md"
|
|
23
27
|
]
|
|
24
28
|
}
|