hermes-transform 0.5.0 → 0.8.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.
Files changed (76) hide show
  1. package/LICENSE +1 -1
  2. package/dist/detachedNode.js +25 -49
  3. package/dist/detachedNode.js.flow +3 -3
  4. package/dist/generated/TransformCloneSignatures.js.flow +1728 -9
  5. package/dist/generated/TransformReplaceSignatures.js.flow +921 -780
  6. package/dist/generated/node-types.js +1099 -1156
  7. package/dist/generated/node-types.js.flow +77 -125
  8. package/dist/generated/special-case-node-types.js +106 -85
  9. package/dist/generated/special-case-node-types.js.flow +28 -2
  10. package/dist/getVisitorKeys.js +4 -6
  11. package/dist/getVisitorKeys.js.flow +1 -1
  12. package/dist/index.js +13 -18
  13. package/dist/index.js.flow +8 -2
  14. package/dist/transform/Errors.js +8 -116
  15. package/dist/transform/Errors.js.flow +1 -1
  16. package/dist/transform/MutationContext.js +54 -67
  17. package/dist/transform/MutationContext.js.flow +4 -3
  18. package/dist/transform/TransformContext.js +100 -58
  19. package/dist/transform/TransformContext.js.flow +277 -141
  20. package/dist/transform/comments/comments.js +127 -40
  21. package/dist/transform/comments/comments.js.flow +106 -29
  22. package/dist/transform/comments/prettier/common/util.js +46 -47
  23. package/dist/transform/comments/prettier/common/util.js.flow +1 -1
  24. package/dist/transform/comments/prettier/language-js/comments.js +199 -216
  25. package/dist/transform/comments/prettier/language-js/comments.js.flow +1 -1
  26. package/dist/transform/comments/prettier/language-js/loc.js +10 -9
  27. package/dist/transform/comments/prettier/language-js/loc.js.flow +1 -1
  28. package/dist/transform/comments/prettier/language-js/printer-estree.js +7 -6
  29. package/dist/transform/comments/prettier/language-js/printer-estree.js.flow +1 -1
  30. package/dist/transform/comments/prettier/language-js/utils.js +18 -30
  31. package/dist/transform/comments/prettier/language-js/utils.js.flow +1 -1
  32. package/dist/transform/comments/prettier/main/comments.js +225 -298
  33. package/dist/transform/comments/prettier/main/comments.js.flow +1 -1
  34. package/dist/transform/comments/prettier/utils/get-last.js +2 -4
  35. package/dist/transform/comments/prettier/utils/get-last.js.flow +1 -1
  36. package/dist/transform/getTransformedAST.js +81 -104
  37. package/dist/transform/getTransformedAST.js.flow +18 -13
  38. package/dist/transform/mutations/AddComments.js +43 -0
  39. package/dist/transform/mutations/AddComments.js.flow +50 -0
  40. package/dist/transform/mutations/CloneCommentsTo.js +16 -24
  41. package/dist/transform/mutations/CloneCommentsTo.js.flow +2 -3
  42. package/dist/transform/mutations/InsertStatement.js +28 -30
  43. package/dist/transform/mutations/InsertStatement.js.flow +7 -2
  44. package/dist/transform/mutations/RemoveComment.js +25 -43
  45. package/dist/transform/mutations/RemoveComment.js.flow +1 -1
  46. package/dist/transform/mutations/RemoveNode.js +192 -0
  47. package/dist/transform/mutations/RemoveNode.js.flow +290 -0
  48. package/dist/transform/mutations/RemoveStatement.js +7 -9
  49. package/dist/transform/mutations/RemoveStatement.js.flow +1 -1
  50. package/dist/transform/mutations/ReplaceNode.js +36 -44
  51. package/dist/transform/mutations/ReplaceNode.js.flow +1 -1
  52. package/dist/transform/mutations/ReplaceStatementWithMany.js +11 -13
  53. package/dist/transform/mutations/ReplaceStatementWithMany.js.flow +1 -1
  54. package/dist/transform/mutations/utils/arrayUtils.js +16 -14
  55. package/dist/transform/mutations/utils/arrayUtils.js.flow +16 -1
  56. package/dist/transform/mutations/utils/getStatementParent.js +23 -28
  57. package/dist/transform/mutations/utils/getStatementParent.js.flow +2 -2
  58. package/dist/transform/mutations/utils/isValidModuleDeclarationParent.js +7 -24
  59. package/dist/transform/mutations/utils/isValidModuleDeclarationParent.js.flow +1 -1
  60. package/dist/transform/transform.js +58 -30
  61. package/dist/transform/transform.js.flow +51 -13
  62. package/dist/traverse/NodeEventGenerator.js +91 -165
  63. package/dist/traverse/NodeEventGenerator.js.flow +1 -1
  64. package/dist/traverse/SafeEmitter.js +20 -38
  65. package/dist/traverse/SafeEmitter.js.flow +1 -1
  66. package/dist/traverse/SimpleTraverser.js +67 -98
  67. package/dist/traverse/SimpleTraverser.js.flow +4 -1
  68. package/dist/traverse/esquery.js +6 -6
  69. package/dist/traverse/esquery.js.flow +1 -1
  70. package/dist/traverse/traverse.js +64 -52
  71. package/dist/traverse/traverse.js.flow +63 -10
  72. package/package.json +5 -3
  73. package/dist/transform/mutations/AddLeadingComments.js +0 -47
  74. package/dist/transform/mutations/AddLeadingComments.js.flow +0 -49
  75. package/dist/transform/mutations/AddTrailingComments.js +0 -47
  76. package/dist/transform/mutations/AddTrailingComments.js.flow +0 -49
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -9,9 +9,11 @@
9
9
  */
10
10
 
11
11
  import type {
12
+ ClassMember,
12
13
  Comment,
13
14
  ESNode,
14
15
  Expression,
16
+ FunctionParameter,
15
17
  ModuleDeclaration,
16
18
  Statement,
17
19
  TypeAnnotationType,
@@ -19,36 +21,38 @@ import type {
19
21
  import type {DetachedNode} from '../detachedNode';
20
22
  import type {TransformCloneSignatures} from '../generated/TransformCloneSignatures';
21
23
  import type {TransformReplaceSignatures} from '../generated/TransformReplaceSignatures';
22
- import type {AddLeadingCommentsMutation} from './mutations/AddLeadingComments';
23
- import type {AddTrailingCommentsMutation} from './mutations/AddTrailingComments';
24
+ import type {TraversalContext} from '../traverse/traverse';
25
+ import type {AddCommentsMutation} from './mutations/AddComments';
24
26
  import type {CloneCommentsToMutation} from './mutations/CloneCommentsTo';
25
27
  import type {InsertStatementMutation} from './mutations/InsertStatement';
26
28
  import type {RemoveCommentMutation} from './mutations/RemoveComment';
29
+ import type {RemoveNodeMutation} from './mutations/RemoveNode';
27
30
  import type {RemoveStatementMutation} from './mutations/RemoveStatement';
28
31
  import type {ReplaceNodeMutation} from './mutations/ReplaceNode';
29
32
  import type {ReplaceStatementWithManyMutation} from './mutations/ReplaceStatementWithMany';
30
33
 
31
34
  import {deepCloneNode, shallowCloneNode} from '../detachedNode';
32
35
  import {
36
+ CommentPlacement,
33
37
  getCommentsForNode,
34
38
  isLeadingComment,
35
39
  isTrailingComment,
36
40
  } from './comments/comments';
37
- import {createAddLeadingCommentsMutation} from './mutations/AddLeadingComments';
38
- import {createAddTrailingCommentsMutation} from './mutations/AddTrailingComments';
41
+ import {createAddCommentsMutation} from './mutations/AddComments';
39
42
  import {createCloneCommentsToMutation} from './mutations/CloneCommentsTo';
40
43
  import {createInsertStatementMutation} from './mutations/InsertStatement';
41
44
  import {createRemoveCommentMutation} from './mutations/RemoveComment';
45
+ import {createRemoveNodeMutation} from './mutations/RemoveNode';
42
46
  import {createRemoveStatementMutation} from './mutations/RemoveStatement';
43
47
  import {createReplaceNodeMutation} from './mutations/ReplaceNode';
44
48
  import {createReplaceStatementWithManyMutation} from './mutations/ReplaceStatementWithMany';
45
49
 
46
50
  type Mutation = $ReadOnly<
47
- | AddLeadingCommentsMutation
48
- | AddTrailingCommentsMutation
51
+ | AddCommentsMutation
49
52
  | CloneCommentsToMutation
50
53
  | InsertStatementMutation
51
54
  | RemoveCommentMutation
55
+ | RemoveNodeMutation
52
56
  | RemoveStatementMutation
53
57
  | ReplaceNodeMutation
54
58
  | ReplaceStatementWithManyMutation,
@@ -65,12 +69,10 @@ type ReplaceNodeOptions = $ReadOnly<{
65
69
  keepComments?: boolean,
66
70
  }>;
67
71
 
68
- export type TransformContext = $ReadOnly<{
69
- mutations: $ReadOnlyArray<Mutation>,
70
- astWasMutated: boolean,
71
-
72
+ type TransformCloneAPIs = $ReadOnly<{
72
73
  /**
73
- * Shallowly clones the given node and applies the given overrides.
74
+ * Shallowly clones the given node.
75
+ *
74
76
  * !!! Be careful about using this !!!
75
77
  * This does not clone children nodes. This means that if you keep
76
78
  * the original node in the AST then you will have two trees in the
@@ -84,12 +86,17 @@ export type TransformContext = $ReadOnly<{
84
86
  * If you want to literally duplicate a node to place somewhere else
85
87
  * in the AST, then use `deepCloneNode` instead.
86
88
  */
87
- shallowCloneNode: TransformCloneSignatures & {
88
- // generic passthrough cases with no options
89
+ shallowCloneNode: {
89
90
  <T: ESNode>(node: T): DetachedNode<T>,
90
91
  <T: ESNode>(node: ?T): DetachedNode<T> | null,
91
92
  },
92
93
 
94
+ /**
95
+ * Shallowly clones the given node and applies the given overrides.
96
+ * {@see shallowCloneNode}
97
+ */
98
+ shallowCloneNodeWithOverrides: TransformCloneSignatures,
99
+
93
100
  /**
94
101
  * {@see shallowCloneNode}
95
102
  */
@@ -99,25 +106,99 @@ export type TransformContext = $ReadOnly<{
99
106
  },
100
107
 
101
108
  /**
102
- * Deeply clones the node and all its children, then applies the
103
- * given overrides.
109
+ * Deeply clones the node and all its children.
110
+ *
104
111
  * !!! Be careful about using this !!!
105
112
  * Because this is a deep clone, using it high up in the AST can
106
113
  * result in a lot of work being done.
107
114
  */
108
- deepCloneNode: TransformCloneSignatures & {
109
- // generic passthrough cases with no options
115
+ deepCloneNode: {
110
116
  <T: ESNode>(node: T): DetachedNode<T>,
111
117
  <T: ESNode>(node: ?T): DetachedNode<T> | null,
112
118
  },
113
119
 
120
+ /**
121
+ * Deeply clones the node and all its children, then applies the
122
+ * given overrides.
123
+ * {@see deepCloneNode}
124
+ */
125
+ deepCloneNodeWithOverrides: TransformCloneSignatures,
126
+ }>;
127
+
128
+ type TransformCommentAPIs = $ReadOnly<{
129
+ /**
130
+ * Gets all of the comments attached to the given node.
131
+ */
132
+ getComments: (node: ESNode) => Array<Comment>,
133
+
134
+ /**
135
+ * Gets the leading comments attached to the given node.
136
+ */
137
+ getLeadingComments: (node: ESNode) => Array<Comment>,
138
+
139
+ /**
140
+ * Gets the trailing comments attached to the given node.
141
+ */
142
+ getTrailingComments: (node: ESNode) => Array<Comment>,
143
+
144
+ /**
145
+ * Clones all of the comments from the target node to the destination node.
146
+ * As its name suggest - this will clone the comments, duplicating them
147
+ * entirely. It will not remove the comments from the target node afterward.
148
+ */
149
+ cloneCommentsTo: (
150
+ target: ESNode,
151
+ destination: ESNode | DetachedNode<ESNode>,
152
+ ) => void,
153
+
154
+ /**
155
+ * Add comments on the line before a specified node.
156
+ */
157
+ addLeadingComments: (
158
+ node: ESNode | DetachedNode<ESNode>,
159
+ comments: SingleOrArray<Comment>,
160
+ ) => void,
161
+
162
+ /**
163
+ * Add comments inline before a specified node.
164
+ */
165
+ addLeadingInlineComments: (
166
+ node: ESNode | DetachedNode<ESNode>,
167
+ comments: SingleOrArray<Comment>,
168
+ ) => void,
169
+
170
+ /**
171
+ * Add comments on the line after a specified node.
172
+ */
173
+ addTrailingComments: (
174
+ node: ESNode | DetachedNode<ESNode>,
175
+ comments: SingleOrArray<Comment>,
176
+ ) => void,
177
+
178
+ /**
179
+ * Add comments inline after a specified node.
180
+ */
181
+ addTrailingInlineComments: (
182
+ node: ESNode | DetachedNode<ESNode>,
183
+ comments: SingleOrArray<Comment>,
184
+ ) => void,
185
+
186
+ /**
187
+ * Removes the specified comments
188
+ */
189
+ removeComments: (comments: SingleOrArray<Comment>) => void,
190
+ }>;
191
+
192
+ type TransformInsertAPIs = $ReadOnly<{
114
193
  /**
115
194
  * Insert `nodeToInsert` after the `target` statement.
116
195
  * The inserted nodes will be kept in the order given.
117
196
  */
118
197
  insertAfterStatement: (
119
- target: ModuleDeclaration | Statement,
120
- nodeToInsert: SingleOrArray<DetachedNode<ModuleDeclaration | Statement>>,
198
+ target: InsertStatementMutation['target'],
199
+ nodeToInsert: SingleOrArray<
200
+ DetachedNode<InsertStatementMutation['target']>,
201
+ >,
121
202
  ) => void,
122
203
 
123
204
  /**
@@ -125,39 +206,69 @@ export type TransformContext = $ReadOnly<{
125
206
  * The inserted nodes will be kept in the order given.
126
207
  */
127
208
  insertBeforeStatement: (
128
- target: ModuleDeclaration | Statement,
129
- nodeToInsert: SingleOrArray<DetachedNode<ModuleDeclaration | Statement>>,
209
+ target: InsertStatementMutation['target'],
210
+ nodeToInsert: SingleOrArray<
211
+ DetachedNode<InsertStatementMutation['target']>,
212
+ >,
130
213
  ) => void,
214
+ }>;
215
+
216
+ type TransformRemoveAPIs = $ReadOnly<{
217
+ /**
218
+ * Removes a given node from the AST.
219
+ * The set of thigns that can be removed is intentionally restricted by types.
220
+ * This represents the set of "misc nodes" that are known to be safe to remove without outright breaking the AST.
221
+ */
222
+ removeNode: (node: RemoveNodeMutation['node']) => void,
131
223
 
224
+ /**
225
+ * Removes a given statement from the AST.
226
+ */
227
+ removeStatement: (node: RemoveStatementMutation['node']) => void,
228
+ }>;
229
+
230
+ type TransformReplaceAPIs = $ReadOnly<{
132
231
  /**
133
232
  * Replace the `target` node with the `nodeToReplaceWith` node.
134
233
  * This simply does an in-place replacement in the AST.
135
234
  */
136
235
  replaceNode: {
137
- // expressions must be replaced with other expressions
236
+ // Expressions may be replaced with other expressions
138
237
  (
139
238
  target: Expression,
140
239
  nodeToReplaceWith: DetachedNode<Expression>,
141
240
  options?: ReplaceNodeOptions,
142
241
  ): void,
143
- // module declarations must be replaced with statements or other module declarations
242
+ // Module declarations may be replaced with statements or other module declarations
144
243
  (
145
244
  target: ModuleDeclaration,
146
245
  nodeToReplaceWith: DetachedNode<ModuleDeclaration | Statement>,
147
246
  options?: ReplaceNodeOptions,
148
247
  ): void,
149
- // Statement must be replaced with statements or module declarations
248
+ // Statement maybe be replaced with statements or module declarations
150
249
  (
151
250
  target: Statement,
152
251
  nodeToReplaceWith: DetachedNode<ModuleDeclaration | Statement>,
153
252
  options?: ReplaceNodeOptions,
154
253
  ): void,
155
- // Types must be replaced with types
254
+ // Types maybe be replaced with other types
156
255
  (
157
256
  target: TypeAnnotationType,
158
257
  nodeToReplaceWith: DetachedNode<TypeAnnotationType>,
159
258
  options?: ReplaceNodeOptions,
160
259
  ): void,
260
+ // Class members may be replaced with other class members
261
+ (
262
+ target: ClassMember,
263
+ nodeToReplaceWith: DetachedNode<ClassMember>,
264
+ options?: ReplaceNodeOptions,
265
+ ): void,
266
+ // Function params amy be replace with other function params
267
+ (
268
+ target: FunctionParameter,
269
+ nodeToReplaceWith: DetachedNode<FunctionParameter>,
270
+ options?: ReplaceNodeOptions,
271
+ ): void,
161
272
  } & TransformReplaceSignatures, // allow like-for-like replacements as well
162
273
 
163
274
  /**
@@ -165,10 +276,8 @@ export type TransformContext = $ReadOnly<{
165
276
  * The nodes will be kept in the order given.
166
277
  */
167
278
  replaceStatementWithMany: (
168
- target: ModuleDeclaration | Statement,
169
- nodesToReplaceWith: $ReadOnlyArray<
170
- DetachedNode<ModuleDeclaration | Statement>,
171
- >,
279
+ target: ReplaceStatementWithManyMutation['target'],
280
+ nodesToReplaceWith: ReplaceStatementWithManyMutation['nodesToReplaceWith'],
172
281
  options?: {
173
282
  /**
174
283
  * Moves the comments from the target node to the first node in the array.
@@ -178,64 +287,21 @@ export type TransformContext = $ReadOnly<{
178
287
  keepComments?: boolean,
179
288
  },
180
289
  ) => void,
290
+ }>;
181
291
 
182
- /**
183
- * Removes a given node from the AST.
184
- */
185
- removeStatement: (node: ModuleDeclaration | Statement) => void,
186
-
187
- //
188
- // Comment APIs
189
- //
190
-
191
- /**
192
- * Gets all of the comments attached to the given node.
193
- */
194
- getComments: (node: ESNode) => Array<Comment>,
195
-
196
- /**
197
- * Gets the leading comments attached to the given node.
198
- */
199
- getLeadingComments: (node: ESNode) => Array<Comment>,
200
-
201
- /**
202
- * Gets the trailing comments attached to the given node.
203
- */
204
- getTrailingComments: (node: ESNode) => Array<Comment>,
205
-
206
- /**
207
- * Clones all of the comments from the target node to the destination node.
208
- * As its name suggest - this will clone the comments, duplicating them
209
- * entirely. It will not remove the comments from the target node afterward.
210
- */
211
- cloneCommentsTo: (
212
- target: ESNode,
213
- destination: ESNode | DetachedNode<ESNode>,
214
- ) => void,
215
-
216
- /**
217
- * Add leading comments to the specified node.
218
- */
219
- addLeadingComments: (
220
- node: ESNode | DetachedNode<ESNode>,
221
- comments: SingleOrArray<Comment>,
222
- ) => void,
223
-
224
- /**
225
- * Add trailing comments to the specified node.
226
- */
227
- addTrailingComments: (
228
- node: ESNode | DetachedNode<ESNode>,
229
- comments: SingleOrArray<Comment>,
230
- ) => void,
292
+ export type TransformContextAdditions = $ReadOnly<{
293
+ mutations: $ReadOnlyArray<Mutation>,
294
+ astWasMutated: boolean,
231
295
 
232
- /**
233
- * Removes the specified comments
234
- */
235
- removeComments: (comments: SingleOrArray<Comment>) => void,
296
+ ...TransformCommentAPIs,
297
+ ...TransformCloneAPIs,
298
+ ...TransformInsertAPIs,
299
+ ...TransformRemoveAPIs,
300
+ ...TransformReplaceAPIs,
236
301
  }>;
302
+ export type TransformContext = TraversalContext<TransformContextAdditions>;
237
303
 
238
- export function getTransformContext(): TransformContext {
304
+ export function getTransformContext(): TransformContextAdditions {
239
305
  /**
240
306
  * The mutations in order of collection.
241
307
  */
@@ -246,27 +312,29 @@ export function getTransformContext(): TransformContext {
246
312
  }
247
313
  }
248
314
 
249
- return {
250
- mutations,
315
+ const cloneAPIs: TransformCloneAPIs = {
316
+ shallowCloneNode: ((
317
+ node: ?ESNode,
318
+ ): // $FlowExpectedError[incompatible-cast]
319
+ ?DetachedNode<ESNode> => {
320
+ if (node == null) {
321
+ return null;
322
+ }
251
323
 
252
- // $FlowExpectedError[unsafe-getters-setters]
253
- get astWasMutated(): boolean {
254
- return mutations.length > 0;
255
- },
324
+ return shallowCloneNode(node);
325
+ }: TransformCloneAPIs['shallowCloneNode']),
256
326
 
257
327
  // $FlowExpectedError[incompatible-exact]
258
- shallowCloneNode: ((
328
+ shallowCloneNodeWithOverrides: ((
259
329
  node: ?ESNode,
260
330
  newProps?: $ReadOnly<{...}>,
261
- ): // $FlowExpectedError[incompatible-cast]
262
- // $FlowExpectedError[prop-missing]
263
- ?DetachedNode<ESNode> => {
331
+ ): ?DetachedNode<ESNode> => {
264
332
  if (node == null) {
265
333
  return null;
266
334
  }
267
335
 
268
336
  return shallowCloneNode(node, newProps);
269
- }: TransformContext['shallowCloneNode']),
337
+ }: TransformCloneAPIs['shallowCloneNodeWithOverrides']),
270
338
 
271
339
  shallowCloneArray: (<T: ESNode>(
272
340
  nodes: ?$ReadOnlyArray<T>,
@@ -277,48 +345,139 @@ export function getTransformContext(): TransformContext {
277
345
  }
278
346
 
279
347
  return nodes.map(node => shallowCloneNode<T>(node));
280
- }: TransformContext['shallowCloneArray']),
348
+ }: TransformCloneAPIs['shallowCloneArray']),
281
349
 
282
- // $FlowExpectedError[incompatible-exact]
283
350
  deepCloneNode: ((
284
351
  node: ?ESNode,
285
- newProps?: $ReadOnly<{...}>,
286
352
  ): // $FlowExpectedError[incompatible-cast]
287
- // $FlowExpectedError[prop-missing]
288
353
  ?DetachedNode<ESNode> => {
289
354
  if (node == null) {
290
355
  return null;
291
356
  }
292
357
 
358
+ return deepCloneNode(node);
359
+ }: TransformCloneAPIs['deepCloneNode']),
360
+
361
+ // $FlowExpectedError[incompatible-exact]
362
+ deepCloneNodeWithOverrides: ((
363
+ node: ?ESNode,
364
+ newProps?: $ReadOnly<{...}>,
365
+ ): ?DetachedNode<ESNode> => {
366
+ if (node == null) {
367
+ return null;
368
+ }
369
+
293
370
  return deepCloneNode(node, newProps);
294
- }: TransformContext['deepCloneNode']),
371
+ }: TransformCloneAPIs['deepCloneNodeWithOverrides']),
372
+ };
373
+ const commentAPIs: TransformCommentAPIs = {
374
+ getComments: ((node): Array<Comment> => {
375
+ return [...getCommentsForNode(node)];
376
+ }: TransformCommentAPIs['getComments']),
377
+
378
+ getLeadingComments: ((node): Array<Comment> => {
379
+ return getCommentsForNode(node).filter(isLeadingComment);
380
+ }: TransformCommentAPIs['getLeadingComments']),
381
+
382
+ getTrailingComments: ((node): Array<Comment> => {
383
+ return getCommentsForNode(node).filter(isTrailingComment);
384
+ }: TransformCommentAPIs['getTrailingComments']),
385
+
386
+ cloneCommentsTo: ((target, destination): void => {
387
+ pushMutation(createCloneCommentsToMutation(target, destination));
388
+ }: TransformCommentAPIs['cloneCommentsTo']),
389
+
390
+ addLeadingComments: ((node, comments): void => {
391
+ pushMutation(
392
+ createAddCommentsMutation(
393
+ node,
394
+ toArray(comments).map(comment => ({
395
+ comment,
396
+ placement: CommentPlacement.LEADING_OWN_LINE,
397
+ })),
398
+ ),
399
+ );
400
+ }: TransformCommentAPIs['addLeadingComments']),
401
+
402
+ addLeadingInlineComments: ((node, comments): void => {
403
+ pushMutation(
404
+ createAddCommentsMutation(
405
+ node,
406
+ toArray(comments).map(comment => ({
407
+ comment,
408
+ placement: CommentPlacement.LEADING_INLINE,
409
+ })),
410
+ ),
411
+ );
412
+ }: TransformCommentAPIs['addLeadingInlineComments']),
413
+
414
+ addTrailingComments: ((node, comments): void => {
415
+ pushMutation(
416
+ createAddCommentsMutation(
417
+ node,
418
+ toArray(comments).map(comment => ({
419
+ comment,
420
+ placement: CommentPlacement.TRAILING_OWN_LINE,
421
+ })),
422
+ ),
423
+ );
424
+ }: TransformCommentAPIs['addTrailingComments']),
425
+
426
+ addTrailingInlineComments: ((node, comments): void => {
427
+ pushMutation(
428
+ createAddCommentsMutation(
429
+ node,
430
+ toArray(comments).map(comment => ({
431
+ comment,
432
+ placement: CommentPlacement.TRAILING_INLINE,
433
+ })),
434
+ ),
435
+ );
436
+ }: TransformCommentAPIs['addTrailingInlineComments']),
295
437
 
438
+ removeComments: ((comments): void => {
439
+ toArray(comments).forEach(comment => {
440
+ pushMutation(createRemoveCommentMutation(comment));
441
+ });
442
+ }: TransformCommentAPIs['removeComments']),
443
+ };
444
+ const insertAPIs: TransformInsertAPIs = {
296
445
  insertAfterStatement: ((target, nodesToInsert): void => {
297
446
  pushMutation(
298
447
  createInsertStatementMutation('after', target, toArray(nodesToInsert)),
299
448
  );
300
- }: TransformContext['insertBeforeStatement']),
449
+ }: TransformInsertAPIs['insertBeforeStatement']),
301
450
 
302
451
  insertBeforeStatement: ((target, nodesToInsert): void => {
303
452
  pushMutation(
304
453
  createInsertStatementMutation('before', target, toArray(nodesToInsert)),
305
454
  );
306
- }: TransformContext['insertBeforeStatement']),
455
+ }: TransformInsertAPIs['insertBeforeStatement']),
456
+ };
457
+ const removeAPIs: TransformRemoveAPIs = {
458
+ removeNode: ((node): void => {
459
+ pushMutation(createRemoveNodeMutation(node));
460
+ }: TransformRemoveAPIs['removeNode']),
307
461
 
462
+ removeStatement: ((node): void => {
463
+ pushMutation(createRemoveStatementMutation(node));
464
+ }: TransformRemoveAPIs['removeStatement']),
465
+ };
466
+ const replaceAPIs: TransformReplaceAPIs = {
308
467
  replaceNode: ((
309
468
  target: ESNode,
310
469
  nodeToReplaceWith: DetachedNode<ESNode>,
311
- options?: $ReadOnly<{keepComments?: boolean}>,
470
+ options?: ReplaceNodeOptions,
312
471
  ): void => {
313
472
  pushMutation(
314
473
  createReplaceNodeMutation(target, nodeToReplaceWith, options),
315
474
  );
316
- }: TransformContext['replaceNode']),
475
+ }: TransformReplaceAPIs['replaceNode']),
317
476
 
318
477
  replaceStatementWithMany: ((
319
478
  target,
320
479
  nodesToReplaceWith,
321
- options?: $ReadOnly<{keepComments?: boolean}>,
480
+ options?: ReplaceNodeOptions,
322
481
  ): void => {
323
482
  pushMutation(
324
483
  createReplaceStatementWithManyMutation(
@@ -327,45 +486,22 @@ export function getTransformContext(): TransformContext {
327
486
  options,
328
487
  ),
329
488
  );
330
- }: TransformContext['replaceStatementWithMany']),
331
-
332
- removeStatement: ((node): void => {
333
- pushMutation(createRemoveStatementMutation(node));
334
- }: TransformContext['removeStatement']),
335
-
336
- //
337
- // Comment APIs
338
- //
339
-
340
- getComments: ((node): Array<Comment> => {
341
- return [...getCommentsForNode(node)];
342
- }: TransformContext['getComments']),
343
-
344
- getLeadingComments: ((node): Array<Comment> => {
345
- return getCommentsForNode(node).filter(isLeadingComment);
346
- }: TransformContext['getLeadingComments']),
347
-
348
- getTrailingComments: ((node): Array<Comment> => {
349
- return getCommentsForNode(node).filter(isTrailingComment);
350
- }: TransformContext['getTrailingComments']),
351
-
352
- cloneCommentsTo: ((target, destination): void => {
353
- pushMutation(createCloneCommentsToMutation(target, destination));
354
- }: TransformContext['cloneCommentsTo']),
489
+ }: TransformReplaceAPIs['replaceStatementWithMany']),
490
+ };
355
491
 
356
- addLeadingComments: ((node, comments): void => {
357
- pushMutation(createAddLeadingCommentsMutation(node, toArray(comments)));
358
- }: TransformContext['addLeadingComments']),
492
+ return {
493
+ mutations,
359
494
 
360
- addTrailingComments: ((node, comments): void => {
361
- pushMutation(createAddTrailingCommentsMutation(node, toArray(comments)));
362
- }: TransformContext['addTrailingComments']),
495
+ // $FlowExpectedError[unsafe-getters-setters]
496
+ get astWasMutated(): boolean {
497
+ return mutations.length > 0;
498
+ },
363
499
 
364
- removeComments: ((comments): void => {
365
- toArray(comments).forEach(comment => {
366
- pushMutation(createRemoveCommentMutation(comment));
367
- });
368
- }: TransformContext['removeComments']),
500
+ ...cloneAPIs,
501
+ ...commentAPIs,
502
+ ...insertAPIs,
503
+ ...removeAPIs,
504
+ ...replaceAPIs,
369
505
  };
370
506
  }
371
507