hermes-transform 0.6.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.
Files changed (42) hide show
  1. package/ESLINT_LICENCE +19 -0
  2. package/PRETTIER_LICENCE +7 -0
  3. package/dist/detachedNode.js +96 -20
  4. package/dist/detachedNode.js.flow +105 -17
  5. package/dist/generated/TransformCloneSignatures.js.flow +33 -66
  6. package/dist/generated/TransformModifySignatures.js.flow +1113 -0
  7. package/dist/generated/TransformReplaceSignatures.js.flow +19 -40
  8. package/dist/generated/node-types.js +638 -905
  9. package/dist/generated/node-types.js.flow +998 -1256
  10. package/dist/generated/special-case-node-types.js +71 -77
  11. package/dist/generated/special-case-node-types.js.flow +104 -88
  12. package/dist/index.js.flow +2 -1
  13. package/dist/transform/MutationContext.js +2 -2
  14. package/dist/transform/MutationContext.js.flow +3 -2
  15. package/dist/transform/TransformContext.js +56 -43
  16. package/dist/transform/TransformContext.js.flow +154 -95
  17. package/dist/transform/comments/comments.js +133 -28
  18. package/dist/transform/comments/comments.js.flow +125 -28
  19. package/dist/transform/getTransformedAST.js +20 -12
  20. package/dist/transform/getTransformedAST.js.flow +32 -14
  21. package/dist/transform/mutations/{AddLeadingComments.js → AddComments.js} +11 -8
  22. package/dist/transform/mutations/AddComments.js.flow +50 -0
  23. package/dist/transform/mutations/CloneCommentsTo.js +1 -2
  24. package/dist/transform/mutations/CloneCommentsTo.js.flow +1 -2
  25. package/dist/transform/mutations/InsertStatement.js +3 -1
  26. package/dist/transform/mutations/InsertStatement.js.flow +7 -1
  27. package/dist/transform/mutations/RemoveNode.js +10 -3
  28. package/dist/transform/mutations/RemoveNode.js.flow +14 -3
  29. package/dist/transform/mutations/ReplaceNode.js +7 -2
  30. package/dist/transform/mutations/ReplaceNode.js.flow +5 -2
  31. package/dist/transform/mutations/ReplaceStatementWithMany.js.flow +5 -2
  32. package/dist/transform/mutations/utils/arrayUtils.js +14 -0
  33. package/dist/transform/mutations/utils/arrayUtils.js.flow +15 -0
  34. package/dist/transform/transform.js +38 -6
  35. package/dist/transform/transform.js.flow +40 -6
  36. package/dist/traverse/NodeEventGenerator.js.flow +1 -1
  37. package/dist/traverse/traverse.js +27 -3
  38. package/dist/traverse/traverse.js.flow +63 -10
  39. package/package.json +9 -4
  40. package/dist/transform/mutations/AddLeadingComments.js.flow +0 -49
  41. package/dist/transform/mutations/AddTrailingComments.js +0 -40
  42. package/dist/transform/mutations/AddTrailingComments.js.flow +0 -49
@@ -5,15 +5,11 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.getTransformContext = getTransformContext;
7
7
 
8
- var _codeFrame = require("@babel/code-frame");
9
-
10
8
  var _detachedNode = require("../detachedNode");
11
9
 
12
10
  var _comments = require("./comments/comments");
13
11
 
14
- var _AddLeadingComments = require("./mutations/AddLeadingComments");
15
-
16
- var _AddTrailingComments = require("./mutations/AddTrailingComments");
12
+ var _AddComments = require("./mutations/AddComments");
17
13
 
18
14
  var _CloneCommentsTo = require("./mutations/CloneCommentsTo");
19
15
 
@@ -38,7 +34,7 @@ var _ReplaceStatementWithMany = require("./mutations/ReplaceStatementWithMany");
38
34
  *
39
35
  * @format
40
36
  */
41
- function getTransformContext(code) {
37
+ function getTransformContext() {
42
38
  /**
43
39
  * The mutations in order of collection.
44
40
  */
@@ -51,16 +47,14 @@ function getTransformContext(code) {
51
47
  }
52
48
 
53
49
  const cloneAPIs = {
54
- // $FlowExpectedError[incompatible-exact]
55
50
  shallowCloneNode: node => {
56
51
  if (node == null) {
57
52
  return null;
58
53
  }
59
54
 
60
- return (0, _detachedNode.shallowCloneNode)(node);
55
+ return (0, _detachedNode.shallowCloneNode)(node, {});
61
56
  },
62
- // $FlowExpectedError[incompatible-exact]
63
- shallowCloneNodeWithOverrides: (node, newProps) => {
57
+ shallowCloneNodeWithOverrides: (node, newProps = {}) => {
64
58
  if (node == null) {
65
59
  return null;
66
60
  }
@@ -72,18 +66,23 @@ function getTransformContext(code) {
72
66
  return null;
73
67
  }
74
68
 
75
- return nodes.map(node => (0, _detachedNode.shallowCloneNode)(node));
69
+ return nodes.map(node => {
70
+ if (node == null) {
71
+ // $FlowExpectedError[incompatible-call]
72
+ return node;
73
+ }
74
+
75
+ return (0, _detachedNode.shallowCloneNode)(node, {});
76
+ });
76
77
  },
77
- // $FlowExpectedError[incompatible-exact]
78
78
  deepCloneNode: node => {
79
79
  if (node == null) {
80
80
  return null;
81
81
  }
82
82
 
83
- return (0, _detachedNode.deepCloneNode)(node);
83
+ return (0, _detachedNode.deepCloneNode)(node, {});
84
84
  },
85
- // $FlowExpectedError[incompatible-exact]
86
- deepCloneNodeWithOverrides: (node, newProps) => {
85
+ deepCloneNodeWithOverrides: (node, newProps = {}) => {
87
86
  if (node == null) {
88
87
  return null;
89
88
  }
@@ -105,10 +104,28 @@ function getTransformContext(code) {
105
104
  pushMutation((0, _CloneCommentsTo.createCloneCommentsToMutation)(target, destination));
106
105
  },
107
106
  addLeadingComments: (node, comments) => {
108
- pushMutation((0, _AddLeadingComments.createAddLeadingCommentsMutation)(node, toArray(comments)));
107
+ pushMutation((0, _AddComments.createAddCommentsMutation)(node, toArray(comments).map(comment => ({
108
+ comment,
109
+ placement: _comments.CommentPlacement.LEADING_OWN_LINE
110
+ }))));
111
+ },
112
+ addLeadingInlineComments: (node, comments) => {
113
+ pushMutation((0, _AddComments.createAddCommentsMutation)(node, toArray(comments).map(comment => ({
114
+ comment,
115
+ placement: _comments.CommentPlacement.LEADING_INLINE
116
+ }))));
109
117
  },
110
118
  addTrailingComments: (node, comments) => {
111
- pushMutation((0, _AddTrailingComments.createAddTrailingCommentsMutation)(node, toArray(comments)));
119
+ pushMutation((0, _AddComments.createAddCommentsMutation)(node, toArray(comments).map(comment => ({
120
+ comment,
121
+ placement: _comments.CommentPlacement.TRAILING_OWN_LINE
122
+ }))));
123
+ },
124
+ addTrailingInlineComments: (node, comments) => {
125
+ pushMutation((0, _AddComments.createAddCommentsMutation)(node, toArray(comments).map(comment => ({
126
+ comment,
127
+ placement: _comments.CommentPlacement.TRAILING_INLINE
128
+ }))));
112
129
  },
113
130
  removeComments: comments => {
114
131
  toArray(comments).forEach(comment => {
@@ -118,10 +135,14 @@ function getTransformContext(code) {
118
135
  };
119
136
  const insertAPIs = {
120
137
  insertAfterStatement: (target, nodesToInsert) => {
121
- pushMutation((0, _InsertStatement.createInsertStatementMutation)('after', target, toArray(nodesToInsert)));
138
+ pushMutation((0, _InsertStatement.createInsertStatementMutation)('after', target, toArray(nodesToInsert).map(n => (0, _detachedNode.asDetachedNode)(n, {
139
+ useDeepClone: true
140
+ }))));
122
141
  },
123
142
  insertBeforeStatement: (target, nodesToInsert) => {
124
- pushMutation((0, _InsertStatement.createInsertStatementMutation)('before', target, toArray(nodesToInsert)));
143
+ pushMutation((0, _InsertStatement.createInsertStatementMutation)('before', target, toArray(nodesToInsert).map(n => (0, _detachedNode.asDetachedNode)(n, {
144
+ useDeepClone: true
145
+ }))));
125
146
  }
126
147
  };
127
148
  const removeAPIs = {
@@ -134,10 +155,23 @@ function getTransformContext(code) {
134
155
  };
135
156
  const replaceAPIs = {
136
157
  replaceNode: (target, nodeToReplaceWith, options) => {
137
- pushMutation((0, _ReplaceNode.createReplaceNodeMutation)(target, nodeToReplaceWith, options));
158
+ pushMutation((0, _ReplaceNode.createReplaceNodeMutation)(target, (0, _detachedNode.asDetachedNode)(nodeToReplaceWith), options));
138
159
  },
139
160
  replaceStatementWithMany: (target, nodesToReplaceWith, options) => {
140
- pushMutation((0, _ReplaceStatementWithMany.createReplaceStatementWithManyMutation)(target, nodesToReplaceWith, options));
161
+ pushMutation((0, _ReplaceStatementWithMany.createReplaceStatementWithManyMutation)(target, nodesToReplaceWith.map(n => (0, _detachedNode.asDetachedNode)(n)), options));
162
+ }
163
+ };
164
+ const modifyAPIs = {
165
+ modifyNodeInPlace: (node, newProps = {}, options) => {
166
+ if (node == null) {
167
+ return;
168
+ }
169
+
170
+ const cloned = (0, _detachedNode.shallowCloneNode)(node, newProps, {
171
+ preserveLocation: true
172
+ }); // $FlowExpectedError[incompatible-call]
173
+
174
+ replaceAPIs.replaceNode(node, cloned, options);
141
175
  }
142
176
  };
143
177
  return {
@@ -148,31 +182,10 @@ function getTransformContext(code) {
148
182
  return mutations.length > 0;
149
183
  },
150
184
 
151
- buildCodeFrame: (node, message) => {
152
- // babel uses 1-indexed columns
153
- const locForBabel = {
154
- start: {
155
- line: node.loc.start.line,
156
- column: node.loc.start.column + 1
157
- },
158
- end: {
159
- line: node.loc.end.line,
160
- column: node.loc.end.column + 1
161
- }
162
- };
163
- return (0, _codeFrame.codeFrameColumns)(code, locForBabel, {
164
- linesAbove: 0,
165
- linesBelow: 0,
166
- highlightCode: process.env.NODE_ENV !== 'test',
167
- message: message
168
- });
169
- },
170
- buildSimpleCodeFrame: (node, message) => {
171
- return `[${node.type}:${node.loc.start.line}:${node.loc.start.column}] ${message}`;
172
- },
173
185
  ...cloneAPIs,
174
186
  ...commentAPIs,
175
187
  ...insertAPIs,
188
+ ...modifyAPIs,
176
189
  ...removeAPIs,
177
190
  ...replaceAPIs
178
191
  };
@@ -18,28 +18,31 @@ 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
- import type {AddLeadingCommentsMutation} from './mutations/AddLeadingComments';
25
- import type {AddTrailingCommentsMutation} from './mutations/AddTrailingComments';
25
+ import type {TraversalContext} from '../traverse/traverse';
26
+ import type {AddCommentsMutation} from './mutations/AddComments';
26
27
  import type {CloneCommentsToMutation} from './mutations/CloneCommentsTo';
27
28
  import type {InsertStatementMutation} from './mutations/InsertStatement';
28
29
  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 {ReplaceStatementWithManyMutation} from './mutations/ReplaceStatementWithMany';
33
+ import type {
34
+ ReplaceStatementWithManyMutation,
35
+ ReplaceStatementWithManyMutationNodes,
36
+ } from './mutations/ReplaceStatementWithMany';
33
37
 
34
- import {codeFrameColumns} from '@babel/code-frame';
35
- import {deepCloneNode, shallowCloneNode} from '../detachedNode';
38
+ import {asDetachedNode, deepCloneNode, shallowCloneNode} from '../detachedNode';
36
39
  import {
40
+ CommentPlacement,
37
41
  getCommentsForNode,
38
42
  isLeadingComment,
39
43
  isTrailingComment,
40
44
  } from './comments/comments';
41
- import {createAddLeadingCommentsMutation} from './mutations/AddLeadingComments';
42
- import {createAddTrailingCommentsMutation} from './mutations/AddTrailingComments';
45
+ import {createAddCommentsMutation} from './mutations/AddComments';
43
46
  import {createCloneCommentsToMutation} from './mutations/CloneCommentsTo';
44
47
  import {createInsertStatementMutation} from './mutations/InsertStatement';
45
48
  import {createRemoveCommentMutation} from './mutations/RemoveComment';
@@ -49,8 +52,7 @@ import {createReplaceNodeMutation} from './mutations/ReplaceNode';
49
52
  import {createReplaceStatementWithManyMutation} from './mutations/ReplaceStatementWithMany';
50
53
 
51
54
  type Mutation = $ReadOnly<
52
- | AddLeadingCommentsMutation
53
- | AddTrailingCommentsMutation
55
+ | AddCommentsMutation
54
56
  | CloneCommentsToMutation
55
57
  | InsertStatementMutation
56
58
  | RemoveCommentMutation
@@ -105,6 +107,8 @@ type TransformCloneAPIs = $ReadOnly<{
105
107
  shallowCloneArray: {
106
108
  <T: ESNode>(node: $ReadOnlyArray<T>): $ReadOnlyArray<DetachedNode<T>>,
107
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>>,
108
112
  },
109
113
 
110
114
  /**
@@ -150,22 +154,38 @@ type TransformCommentAPIs = $ReadOnly<{
150
154
  */
151
155
  cloneCommentsTo: (
152
156
  target: ESNode,
153
- destination: ESNode | DetachedNode<ESNode>,
157
+ destination: MaybeDetachedNode<ESNode>,
154
158
  ) => void,
155
159
 
156
160
  /**
157
- * Add leading comments to the specified node.
161
+ * Add comments on the line before a specified node.
158
162
  */
159
163
  addLeadingComments: (
160
- node: ESNode | DetachedNode<ESNode>,
164
+ node: MaybeDetachedNode<ESNode>,
165
+ comments: SingleOrArray<Comment>,
166
+ ) => void,
167
+
168
+ /**
169
+ * Add comments inline before a specified node.
170
+ */
171
+ addLeadingInlineComments: (
172
+ node: MaybeDetachedNode<ESNode>,
161
173
  comments: SingleOrArray<Comment>,
162
174
  ) => void,
163
175
 
164
176
  /**
165
- * Add trailing comments to the specified node.
177
+ * Add comments on the line after a specified node.
166
178
  */
167
179
  addTrailingComments: (
168
- node: ESNode | DetachedNode<ESNode>,
180
+ node: MaybeDetachedNode<ESNode>,
181
+ comments: SingleOrArray<Comment>,
182
+ ) => void,
183
+
184
+ /**
185
+ * Add comments inline after a specified node.
186
+ */
187
+ addTrailingInlineComments: (
188
+ node: MaybeDetachedNode<ESNode>,
169
189
  comments: SingleOrArray<Comment>,
170
190
  ) => void,
171
191
 
@@ -183,7 +203,7 @@ type TransformInsertAPIs = $ReadOnly<{
183
203
  insertAfterStatement: (
184
204
  target: InsertStatementMutation['target'],
185
205
  nodeToInsert: SingleOrArray<
186
- DetachedNode<InsertStatementMutation['target']>,
206
+ MaybeDetachedNode<InsertStatementMutation['target']>,
187
207
  >,
188
208
  ) => void,
189
209
 
@@ -194,11 +214,19 @@ type TransformInsertAPIs = $ReadOnly<{
194
214
  insertBeforeStatement: (
195
215
  target: InsertStatementMutation['target'],
196
216
  nodeToInsert: SingleOrArray<
197
- DetachedNode<InsertStatementMutation['target']>,
217
+ MaybeDetachedNode<InsertStatementMutation['target']>,
198
218
  >,
199
219
  ) => void,
200
220
  }>;
201
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
+
202
230
  type TransformRemoveAPIs = $ReadOnly<{
203
231
  /**
204
232
  * Removes a given node from the AST.
@@ -222,37 +250,37 @@ type TransformReplaceAPIs = $ReadOnly<{
222
250
  // Expressions may be replaced with other expressions
223
251
  (
224
252
  target: Expression,
225
- nodeToReplaceWith: DetachedNode<Expression>,
253
+ nodeToReplaceWith: MaybeDetachedNode<Expression>,
226
254
  options?: ReplaceNodeOptions,
227
255
  ): void,
228
256
  // Module declarations may be replaced with statements or other module declarations
229
257
  (
230
258
  target: ModuleDeclaration,
231
- nodeToReplaceWith: DetachedNode<ModuleDeclaration | Statement>,
259
+ nodeToReplaceWith: MaybeDetachedNode<ModuleDeclaration | Statement>,
232
260
  options?: ReplaceNodeOptions,
233
261
  ): void,
234
262
  // Statement maybe be replaced with statements or module declarations
235
263
  (
236
264
  target: Statement,
237
- nodeToReplaceWith: DetachedNode<ModuleDeclaration | Statement>,
265
+ nodeToReplaceWith: MaybeDetachedNode<ModuleDeclaration | Statement>,
238
266
  options?: ReplaceNodeOptions,
239
267
  ): void,
240
268
  // Types maybe be replaced with other types
241
269
  (
242
270
  target: TypeAnnotationType,
243
- nodeToReplaceWith: DetachedNode<TypeAnnotationType>,
271
+ nodeToReplaceWith: MaybeDetachedNode<TypeAnnotationType>,
244
272
  options?: ReplaceNodeOptions,
245
273
  ): void,
246
274
  // Class members may be replaced with other class members
247
275
  (
248
276
  target: ClassMember,
249
- nodeToReplaceWith: DetachedNode<ClassMember>,
277
+ nodeToReplaceWith: MaybeDetachedNode<ClassMember>,
250
278
  options?: ReplaceNodeOptions,
251
279
  ): void,
252
280
  // Function params amy be replace with other function params
253
281
  (
254
282
  target: FunctionParameter,
255
- nodeToReplaceWith: DetachedNode<FunctionParameter>,
283
+ nodeToReplaceWith: MaybeDetachedNode<FunctionParameter>,
256
284
  options?: ReplaceNodeOptions,
257
285
  ): void,
258
286
  } & TransformReplaceSignatures, // allow like-for-like replacements as well
@@ -263,7 +291,9 @@ type TransformReplaceAPIs = $ReadOnly<{
263
291
  */
264
292
  replaceStatementWithMany: (
265
293
  target: ReplaceStatementWithManyMutation['target'],
266
- nodesToReplaceWith: ReplaceStatementWithManyMutation['nodesToReplaceWith'],
294
+ nodesToReplaceWith: $ReadOnlyArray<
295
+ MaybeDetachedNode<ReplaceStatementWithManyMutationNodes>,
296
+ >,
267
297
  options?: {
268
298
  /**
269
299
  * Moves the comments from the target node to the first node in the array.
@@ -275,43 +305,20 @@ type TransformReplaceAPIs = $ReadOnly<{
275
305
  ) => void,
276
306
  }>;
277
307
 
278
- export type TransformContext = $ReadOnly<{
308
+ export type TransformContextAdditions = $ReadOnly<{
279
309
  mutations: $ReadOnlyArray<Mutation>,
280
310
  astWasMutated: boolean,
281
311
 
282
- /**
283
- * Creates a full code frame for the node along with the message.
284
- *
285
- * i.e. `context.buildCodeFrame(node, 'foo')` will create a string like:
286
- * ```
287
- * 56 | function () {
288
- * | ^^^^^^^^^^^^^
289
- * 57 | }.bind(this)
290
- * | ^^ foo
291
- * ```
292
- */
293
- buildCodeFrame: (node: ESNode, message: string) => string,
294
-
295
- /**
296
- * Creates a simple code frame for the node along with the message.
297
- * Use this if you want a condensed marker for your message.
298
- *
299
- * i.e. `context.logWithNode(node, 'foo')` will create a string like:
300
- * ```
301
- * [FunctionExpression:56:44] foo
302
- * ```
303
- * (where 56:44 represents L56, Col44)
304
- */
305
- buildSimpleCodeFrame: (node: ESNode, message: string) => string,
306
-
307
312
  ...TransformCommentAPIs,
308
313
  ...TransformCloneAPIs,
309
314
  ...TransformInsertAPIs,
315
+ ...TransformModifyAPIs,
310
316
  ...TransformRemoveAPIs,
311
317
  ...TransformReplaceAPIs,
312
318
  }>;
319
+ export type TransformContext = TraversalContext<TransformContextAdditions>;
313
320
 
314
- export function getTransformContext(code: string): TransformContext {
321
+ export function getTransformContext(): TransformContextAdditions {
315
322
  /**
316
323
  * The mutations in order of collection.
317
324
  */
@@ -323,7 +330,6 @@ export function getTransformContext(code: string): TransformContext {
323
330
  }
324
331
 
325
332
  const cloneAPIs: TransformCloneAPIs = {
326
- // $FlowExpectedError[incompatible-exact]
327
333
  shallowCloneNode: ((
328
334
  node: ?ESNode,
329
335
  ): // $FlowExpectedError[incompatible-cast]
@@ -332,14 +338,14 @@ export function getTransformContext(code: string): TransformContext {
332
338
  return null;
333
339
  }
334
340
 
335
- return shallowCloneNode(node);
341
+ return shallowCloneNode(node, {});
336
342
  }: TransformCloneAPIs['shallowCloneNode']),
337
343
 
338
- // $FlowExpectedError[incompatible-exact]
339
344
  shallowCloneNodeWithOverrides: ((
340
345
  node: ?ESNode,
341
- newProps?: $ReadOnly<{...}>,
346
+ newProps?: $ReadOnly<{...}> = {},
342
347
  ): // $FlowExpectedError[incompatible-cast]
348
+ // $FlowExpectedError[prop-missing]
343
349
  ?DetachedNode<ESNode> => {
344
350
  if (node == null) {
345
351
  return null;
@@ -349,17 +355,22 @@ export function getTransformContext(code: string): TransformContext {
349
355
  }: TransformCloneAPIs['shallowCloneNodeWithOverrides']),
350
356
 
351
357
  shallowCloneArray: (<T: ESNode>(
352
- nodes: ?$ReadOnlyArray<T>,
358
+ nodes: ?$ReadOnlyArray<?T>,
353
359
  ): // $FlowExpectedError[incompatible-cast]
354
- ?$ReadOnlyArray<DetachedNode<ESNode>> => {
360
+ ?$ReadOnlyArray<DetachedNode<?ESNode>> => {
355
361
  if (nodes == null) {
356
362
  return null;
357
363
  }
358
364
 
359
- return nodes.map(node => shallowCloneNode<T>(node));
365
+ return nodes.map(node => {
366
+ if (node == null) {
367
+ // $FlowExpectedError[incompatible-call]
368
+ return node;
369
+ }
370
+ return shallowCloneNode<T>(node, {});
371
+ });
360
372
  }: TransformCloneAPIs['shallowCloneArray']),
361
373
 
362
- // $FlowExpectedError[incompatible-exact]
363
374
  deepCloneNode: ((
364
375
  node: ?ESNode,
365
376
  ): // $FlowExpectedError[incompatible-cast]
@@ -368,14 +379,14 @@ export function getTransformContext(code: string): TransformContext {
368
379
  return null;
369
380
  }
370
381
 
371
- return deepCloneNode(node);
382
+ return deepCloneNode(node, {});
372
383
  }: TransformCloneAPIs['deepCloneNode']),
373
384
 
374
- // $FlowExpectedError[incompatible-exact]
375
385
  deepCloneNodeWithOverrides: ((
376
386
  node: ?ESNode,
377
- newProps?: $ReadOnly<{...}>,
387
+ newProps?: $ReadOnly<{...}> = {},
378
388
  ): // $FlowExpectedError[incompatible-cast]
389
+ // $FlowExpectedError[prop-missing]
379
390
  ?DetachedNode<ESNode> => {
380
391
  if (node == null) {
381
392
  return null;
@@ -402,13 +413,53 @@ export function getTransformContext(code: string): TransformContext {
402
413
  }: TransformCommentAPIs['cloneCommentsTo']),
403
414
 
404
415
  addLeadingComments: ((node, comments): void => {
405
- pushMutation(createAddLeadingCommentsMutation(node, toArray(comments)));
416
+ pushMutation(
417
+ createAddCommentsMutation(
418
+ node,
419
+ toArray(comments).map(comment => ({
420
+ comment,
421
+ placement: CommentPlacement.LEADING_OWN_LINE,
422
+ })),
423
+ ),
424
+ );
406
425
  }: TransformCommentAPIs['addLeadingComments']),
407
426
 
427
+ addLeadingInlineComments: ((node, comments): void => {
428
+ pushMutation(
429
+ createAddCommentsMutation(
430
+ node,
431
+ toArray(comments).map(comment => ({
432
+ comment,
433
+ placement: CommentPlacement.LEADING_INLINE,
434
+ })),
435
+ ),
436
+ );
437
+ }: TransformCommentAPIs['addLeadingInlineComments']),
438
+
408
439
  addTrailingComments: ((node, comments): void => {
409
- pushMutation(createAddTrailingCommentsMutation(node, toArray(comments)));
440
+ pushMutation(
441
+ createAddCommentsMutation(
442
+ node,
443
+ toArray(comments).map(comment => ({
444
+ comment,
445
+ placement: CommentPlacement.TRAILING_OWN_LINE,
446
+ })),
447
+ ),
448
+ );
410
449
  }: TransformCommentAPIs['addTrailingComments']),
411
450
 
451
+ addTrailingInlineComments: ((node, comments): void => {
452
+ pushMutation(
453
+ createAddCommentsMutation(
454
+ node,
455
+ toArray(comments).map(comment => ({
456
+ comment,
457
+ placement: CommentPlacement.TRAILING_INLINE,
458
+ })),
459
+ ),
460
+ );
461
+ }: TransformCommentAPIs['addTrailingInlineComments']),
462
+
412
463
  removeComments: ((comments): void => {
413
464
  toArray(comments).forEach(comment => {
414
465
  pushMutation(createRemoveCommentMutation(comment));
@@ -418,13 +469,25 @@ export function getTransformContext(code: string): TransformContext {
418
469
  const insertAPIs: TransformInsertAPIs = {
419
470
  insertAfterStatement: ((target, nodesToInsert): void => {
420
471
  pushMutation(
421
- createInsertStatementMutation('after', target, toArray(nodesToInsert)),
472
+ createInsertStatementMutation(
473
+ 'after',
474
+ target,
475
+ toArray(nodesToInsert).map(n =>
476
+ asDetachedNode(n, {useDeepClone: true}),
477
+ ),
478
+ ),
422
479
  );
423
480
  }: TransformInsertAPIs['insertBeforeStatement']),
424
481
 
425
482
  insertBeforeStatement: ((target, nodesToInsert): void => {
426
483
  pushMutation(
427
- createInsertStatementMutation('before', target, toArray(nodesToInsert)),
484
+ createInsertStatementMutation(
485
+ 'before',
486
+ target,
487
+ toArray(nodesToInsert).map(n =>
488
+ asDetachedNode(n, {useDeepClone: true}),
489
+ ),
490
+ ),
428
491
  );
429
492
  }: TransformInsertAPIs['insertBeforeStatement']),
430
493
  };
@@ -440,28 +503,47 @@ export function getTransformContext(code: string): TransformContext {
440
503
  const replaceAPIs: TransformReplaceAPIs = {
441
504
  replaceNode: ((
442
505
  target: ESNode,
443
- nodeToReplaceWith: DetachedNode<ESNode>,
444
- options?: $ReadOnly<{keepComments?: boolean}>,
506
+ nodeToReplaceWith: MaybeDetachedNode<ESNode>,
507
+ options?: ReplaceNodeOptions,
445
508
  ): void => {
446
509
  pushMutation(
447
- createReplaceNodeMutation(target, nodeToReplaceWith, options),
510
+ createReplaceNodeMutation(
511
+ target,
512
+ asDetachedNode(nodeToReplaceWith),
513
+ options,
514
+ ),
448
515
  );
449
516
  }: TransformReplaceAPIs['replaceNode']),
450
517
 
451
518
  replaceStatementWithMany: ((
452
519
  target,
453
520
  nodesToReplaceWith,
454
- options?: $ReadOnly<{keepComments?: boolean}>,
521
+ options?: ReplaceNodeOptions,
455
522
  ): void => {
456
523
  pushMutation(
457
524
  createReplaceStatementWithManyMutation(
458
525
  target,
459
- nodesToReplaceWith,
526
+ nodesToReplaceWith.map(n => asDetachedNode(n)),
460
527
  options,
461
528
  ),
462
529
  );
463
530
  }: TransformReplaceAPIs['replaceStatementWithMany']),
464
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
+ };
465
547
 
466
548
  return {
467
549
  mutations,
@@ -471,33 +553,10 @@ export function getTransformContext(code: string): TransformContext {
471
553
  return mutations.length > 0;
472
554
  },
473
555
 
474
- buildCodeFrame: (node: ESNode, message: string): string => {
475
- // babel uses 1-indexed columns
476
- const locForBabel = {
477
- start: {
478
- line: node.loc.start.line,
479
- column: node.loc.start.column + 1,
480
- },
481
- end: {
482
- line: node.loc.end.line,
483
- column: node.loc.end.column + 1,
484
- },
485
- };
486
- return codeFrameColumns(code, locForBabel, {
487
- linesAbove: 0,
488
- linesBelow: 0,
489
- highlightCode: process.env.NODE_ENV !== 'test',
490
- message: message,
491
- });
492
- },
493
-
494
- buildSimpleCodeFrame: (node: ESNode, message: string): string => {
495
- return `[${node.type}:${node.loc.start.line}:${node.loc.start.column}] ${message}`;
496
- },
497
-
498
556
  ...cloneAPIs,
499
557
  ...commentAPIs,
500
558
  ...insertAPIs,
559
+ ...modifyAPIs,
501
560
  ...removeAPIs,
502
561
  ...replaceAPIs,
503
562
  };