hermes-transform 0.28.0 → 0.29.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 (51) hide show
  1. package/dist/detachedNode.js +1 -0
  2. package/dist/detachedNode.js.flow +1 -0
  3. package/dist/generated/node-types.js +1 -12
  4. package/dist/generated/node-types.js.flow +2 -19
  5. package/dist/generated/special-case-node-types/misc.js +11 -0
  6. package/dist/generated/special-case-node-types/misc.js.flow +18 -0
  7. package/dist/src/detachedNode.js +178 -0
  8. package/dist/src/generated/node-types.js +2212 -0
  9. package/dist/src/generated/special-case-node-types/Comment.js +36 -0
  10. package/dist/src/generated/special-case-node-types/DeclareExportDeclaration.js +58 -0
  11. package/dist/src/generated/special-case-node-types/DeclareHook.js +33 -0
  12. package/dist/src/generated/special-case-node-types/ExportNamedDeclaration.js +44 -0
  13. package/dist/src/generated/special-case-node-types/Literal.js +97 -0
  14. package/dist/src/generated/special-case-node-types/ObjectTypeProperty.js +74 -0
  15. package/dist/src/generated/special-case-node-types/Property.js +136 -0
  16. package/dist/src/generated/special-case-node-types/misc.js +158 -0
  17. package/dist/src/generated/special-case-node-types.js +69 -0
  18. package/dist/src/index.js +53 -0
  19. package/dist/src/transform/Errors.js +43 -0
  20. package/dist/src/transform/MutationContext.js +81 -0
  21. package/dist/src/transform/TransformContext.js +213 -0
  22. package/dist/src/transform/comments/comments.js +308 -0
  23. package/dist/src/transform/comments/prettier/common/util.js +364 -0
  24. package/dist/src/transform/comments/prettier/language-js/comments.js +788 -0
  25. package/dist/src/transform/comments/prettier/language-js/loc.js +42 -0
  26. package/dist/src/transform/comments/prettier/language-js/printer-estree.js +32 -0
  27. package/dist/src/transform/comments/prettier/language-js/utils.js +119 -0
  28. package/dist/src/transform/comments/prettier/main/comments.js +440 -0
  29. package/dist/src/transform/comments/prettier/utils/get-last.js +13 -0
  30. package/dist/src/transform/mutations/AddComments.js +43 -0
  31. package/dist/src/transform/mutations/CloneCommentsTo.js +31 -0
  32. package/dist/src/transform/mutations/InsertStatement.js +91 -0
  33. package/dist/src/transform/mutations/ModifyNodeInPlace.js +59 -0
  34. package/dist/src/transform/mutations/RemoveComment.js +78 -0
  35. package/dist/src/transform/mutations/RemoveNode.js +205 -0
  36. package/dist/src/transform/mutations/RemoveStatement.js +59 -0
  37. package/dist/src/transform/mutations/ReplaceNode.js +92 -0
  38. package/dist/src/transform/mutations/ReplaceStatementWithMany.js +79 -0
  39. package/dist/src/transform/mutations/utils/getStatementParent.js +143 -0
  40. package/dist/src/transform/mutations/utils/isValidModuleDeclarationParent.js +43 -0
  41. package/dist/src/transform/parse.js +56 -0
  42. package/dist/src/transform/print.js +134 -0
  43. package/dist/src/transform/transform.js +36 -0
  44. package/dist/src/transform/transformAST.js +134 -0
  45. package/dist/src/traverse/NodeEventGenerator.js +353 -0
  46. package/dist/src/traverse/SafeEmitter.js +52 -0
  47. package/dist/src/traverse/esquery.js +37 -0
  48. package/dist/src/traverse/traverse.js +150 -0
  49. package/dist/transform/comments/prettier/language-js/comments.js +29 -1
  50. package/dist/transform/mutations/utils/getStatementParent.js.flow +7 -5
  51. package/package.json +5 -5
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createCloneCommentsToMutation = createCloneCommentsToMutation;
7
+ exports.performCloneCommentsToMutation = performCloneCommentsToMutation;
8
+
9
+ var _comments = require("../comments/comments");
10
+
11
+ /**
12
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
13
+ *
14
+ * This source code is licensed under the MIT license found in the
15
+ * LICENSE file in the root directory of this source tree.
16
+ *
17
+ *
18
+ * @format
19
+ */
20
+ function createCloneCommentsToMutation(target, destination) {
21
+ return {
22
+ type: 'cloneCommentsTo',
23
+ target,
24
+ destination
25
+ };
26
+ }
27
+
28
+ function performCloneCommentsToMutation(_mutationContext, mutation) {
29
+ (0, _comments.cloneCommentsToNewNode)(mutation.target, mutation.destination);
30
+ return null;
31
+ }
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createInsertStatementMutation = createInsertStatementMutation;
7
+ exports.performInsertStatementMutation = performInsertStatementMutation;
8
+
9
+ var _hermesParser = require("hermes-parser");
10
+
11
+ var _getStatementParent = require("./utils/getStatementParent");
12
+
13
+ var _isValidModuleDeclarationParent = require("./utils/isValidModuleDeclarationParent");
14
+
15
+ var _Errors = require("../Errors");
16
+
17
+ var t = _interopRequireWildcard(require("../../generated/node-types"));
18
+
19
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
20
+
21
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
22
+
23
+ /**
24
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
25
+ *
26
+ * This source code is licensed under the MIT license found in the
27
+ * LICENSE file in the root directory of this source tree.
28
+ *
29
+ *
30
+ * @format
31
+ */
32
+ function createInsertStatementMutation(side, target, nodesToInsert) {
33
+ if (nodesToInsert.length === 0) {
34
+ return null;
35
+ }
36
+
37
+ return {
38
+ type: 'insertStatement',
39
+ side,
40
+ target,
41
+ nodesToInsert
42
+ };
43
+ }
44
+
45
+ function performInsertStatementMutation(mutationContext, mutation) {
46
+ mutationContext.assertNotDeleted(mutation.target, `Attempted to insert ${mutation.side} a deleted ${mutation.target.type} node. This likely means that you attempted to mutate around the target after it was deleted/replaced.`);
47
+ const insertionParent = (0, _getStatementParent.getStatementParent)(mutation.target); // enforce that if we are inserting module declarations - they are being inserted in a valid location
48
+
49
+ if (!(0, _isValidModuleDeclarationParent.isValidModuleDeclarationParent)(insertionParent.parent, mutation.nodesToInsert)) {
50
+ throw new _Errors.InvalidInsertionError(`import/export cannot be inserted into a ${insertionParent.parent.type}.`);
51
+ }
52
+
53
+ mutationContext.markMutation(insertionParent.parent, insertionParent.key);
54
+
55
+ if (insertionParent.type === 'array') {
56
+ const parent = insertionParent.parent;
57
+
58
+ switch (mutation.side) {
59
+ case 'before':
60
+ {
61
+ parent[insertionParent.key] = _hermesParser.astArrayMutationHelpers.insertInArray(parent[insertionParent.key], insertionParent.targetIndex, mutation.nodesToInsert);
62
+ break;
63
+ }
64
+
65
+ case 'after':
66
+ {
67
+ parent[insertionParent.key] = _hermesParser.astArrayMutationHelpers.insertInArray(parent[insertionParent.key], insertionParent.targetIndex + 1, mutation.nodesToInsert);
68
+ break;
69
+ }
70
+ }
71
+
72
+ return insertionParent.parent;
73
+ }
74
+
75
+ const statementsToInsert = // $FlowExpectedError[incompatible-cast] -- this is enforced by isValidModuleDeclarationParent above
76
+ mutation.nodesToInsert;
77
+ const {
78
+ parent,
79
+ key
80
+ } = insertionParent; // $FlowExpectedError[prop-missing]
81
+
82
+ const statementToWrap = parent[key]; // we need to wrap this key in a BlockStatement so we can insert the new statement
83
+
84
+ const blockStatement = t.BlockStatement({
85
+ body: mutation.side === 'before' ? [...statementsToInsert, statementToWrap] : [statementToWrap, ...statementsToInsert],
86
+ parent: insertionParent.parent
87
+ });
88
+ insertionParent.parent[insertionParent.key] = blockStatement;
89
+ statementToWrap.parent = blockStatement;
90
+ return insertionParent.parent;
91
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createModifyNodeInPlaceMutation = createModifyNodeInPlaceMutation;
7
+ exports.performModifyNodeInPlaceMutation = performModifyNodeInPlaceMutation;
8
+
9
+ var _hermesParser = require("hermes-parser");
10
+
11
+ /**
12
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
13
+ *
14
+ * This source code is licensed under the MIT license found in the
15
+ * LICENSE file in the root directory of this source tree.
16
+ *
17
+ *
18
+ * @format
19
+ */
20
+ function createModifyNodeInPlaceMutation(target, newProps) {
21
+ return {
22
+ type: 'modifyNodeInPlace',
23
+ target,
24
+ newProps
25
+ };
26
+ }
27
+
28
+ function performModifyNodeInPlaceMutation(mutationContext, mutation) {
29
+ const {
30
+ target,
31
+ newProps
32
+ } = mutation;
33
+
34
+ for (const [key, newPropValue] of Object.entries(newProps)) {
35
+ const prevPropValue = target[key]; // If the value did not change, skip.
36
+
37
+ if (prevPropValue === newPropValue) {
38
+ continue;
39
+ } // Mark removed nodes as deleted
40
+
41
+
42
+ if ((0, _hermesParser.isNode)(prevPropValue)) {
43
+ mutationContext.markDeletion(prevPropValue);
44
+ } else if (Array.isArray(prevPropValue)) {
45
+ for (const prevPropValueItem of prevPropValue) {
46
+ if ((0, _hermesParser.isNode)(prevPropValueItem)) {
47
+ mutationContext.markDeletion(prevPropValueItem);
48
+ }
49
+ }
50
+ } // Mark node property as mutated.
51
+
52
+
53
+ mutationContext.markMutation(target, key); // Assign new property.
54
+
55
+ target[key] = newPropValue;
56
+ }
57
+
58
+ return target;
59
+ }
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createRemoveCommentMutation = createRemoveCommentMutation;
7
+ exports.performRemoveCommentMutations = performRemoveCommentMutations;
8
+
9
+ var _hermesParser = require("hermes-parser");
10
+
11
+ var _comments = require("../comments/comments");
12
+
13
+ /**
14
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
15
+ *
16
+ * This source code is licensed under the MIT license found in the
17
+ * LICENSE file in the root directory of this source tree.
18
+ *
19
+ *
20
+ * @format
21
+ */
22
+ function createRemoveCommentMutation(comment) {
23
+ return {
24
+ type: 'removeComment',
25
+ comment
26
+ };
27
+ }
28
+
29
+ function performRemoveCommentMutations(ast, mutations) {
30
+ if (mutations.length === 0) {
31
+ return;
32
+ }
33
+
34
+ const commentsToRemove = new Set(mutations.map(m => m.comment));
35
+
36
+ _hermesParser.SimpleTraverser.traverse(ast, {
37
+ enter(node) {
38
+ if (node === ast) {
39
+ return;
40
+ }
41
+
42
+ const nodeCommentsSet = new Set((0, _comments.getCommentsForNode)(node));
43
+
44
+ if (nodeCommentsSet.size === 0) {
45
+ return;
46
+ }
47
+
48
+ const matchedComments = intersectSets(commentsToRemove, nodeCommentsSet);
49
+
50
+ for (const comment of matchedComments) {
51
+ commentsToRemove.delete(comment);
52
+ nodeCommentsSet.delete(comment);
53
+ }
54
+
55
+ (0, _comments.setCommentsOnNode)(node, Array.from(nodeCommentsSet));
56
+
57
+ if (commentsToRemove.size === 0) {
58
+ // no more comments to process - so we can exit traversal
59
+ throw _hermesParser.SimpleTraverserBreak;
60
+ }
61
+ },
62
+
63
+ leave() {}
64
+
65
+ });
66
+ }
67
+
68
+ function intersectSets(first, other) {
69
+ const ret = new Set();
70
+
71
+ for (const value of first) {
72
+ if (other.has(value)) {
73
+ ret.add(value);
74
+ }
75
+ }
76
+
77
+ return ret;
78
+ }
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createRemoveNodeMutation = createRemoveNodeMutation;
7
+ exports.performRemoveNodeMutation = performRemoveNodeMutation;
8
+
9
+ var _hermesParser = require("hermes-parser");
10
+
11
+ var _Errors = require("../Errors");
12
+
13
+ /**
14
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
15
+ *
16
+ * This source code is licensed under the MIT license found in the
17
+ * LICENSE file in the root directory of this source tree.
18
+ *
19
+ *
20
+ * @format
21
+ */
22
+ function createRemoveNodeMutation(node) {
23
+ return {
24
+ type: 'removeNode',
25
+ node
26
+ };
27
+ }
28
+
29
+ const VALID_ENUM_MEMBER_PARENTS = ['EnumBooleanBody', 'EnumNumberBody', 'EnumBigIntBody', 'EnumStringBody', 'EnumSymbolBody'];
30
+ const VALID_FUNCTION_PARAMETER_PARENTS = ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression'];
31
+ const VALID_PROPERTY_PARENTS = ['ObjectExpression', 'ObjectPattern'];
32
+ const VALID_COMPONENT_TYPE_PARAMETER_PARENTS = ['DeclareComponent', 'ComponentTypeAnnotation'];
33
+
34
+ function getRemovalParent(node) {
35
+ const key = (() => {
36
+ function getErrorMessage(expectedParents) {
37
+ return `Tried to remove ${node.type} from parent of type ${node.parent.type}.\nHowever ${node.type} can only be safely removed from parent of type ${expectedParents.join(' | ')}.`;
38
+ }
39
+
40
+ function assertParent(expectedParents_) {
41
+ const expectedParents = typeof expectedParents_ === 'string' ? [expectedParents_] : expectedParents_;
42
+
43
+ if (!expectedParents.includes(node.parent.type)) {
44
+ return new _Errors.InvalidRemovalError(getErrorMessage(expectedParents));
45
+ }
46
+ }
47
+
48
+ switch (node.type) {
49
+ // ClassMember
50
+ case 'PropertyDefinition':
51
+ case 'MethodDefinition':
52
+ assertParent('ClassBody');
53
+ return 'body';
54
+
55
+ case 'EnumBooleanMember':
56
+ case 'EnumDefaultedMember':
57
+ case 'EnumNumberMember':
58
+ case 'EnumStringMember':
59
+ assertParent(VALID_ENUM_MEMBER_PARENTS);
60
+ return 'members';
61
+ // Components
62
+
63
+ case 'ComponentParameter':
64
+ assertParent('ComponentDeclaration');
65
+ return 'params';
66
+
67
+ case 'ComponentTypeParameter':
68
+ assertParent(VALID_COMPONENT_TYPE_PARAMETER_PARENTS);
69
+ return 'params';
70
+ // FunctionParameter
71
+
72
+ case 'AssignmentPattern':
73
+ case 'ArrayPattern':
74
+ case 'ObjectPattern':
75
+ assertParent(VALID_FUNCTION_PARAMETER_PARENTS);
76
+ return 'params';
77
+
78
+ case 'FunctionTypeParam':
79
+ assertParent('FunctionTypeAnnotation');
80
+ return 'params';
81
+
82
+ case 'JSXAttribute':
83
+ assertParent('JSXOpeningElement');
84
+ return 'attributes';
85
+
86
+ case 'ImportDeclaration':
87
+ assertParent('Program');
88
+ return 'body';
89
+
90
+ case 'ObjectTypeCallProperty':
91
+ assertParent('ObjectTypeAnnotation');
92
+ return 'callProperties';
93
+
94
+ case 'ObjectTypeIndexer':
95
+ assertParent('ObjectTypeAnnotation');
96
+ return 'indexers';
97
+
98
+ case 'ObjectTypeInternalSlot':
99
+ assertParent('ObjectTypeAnnotation');
100
+ return 'internalSlots';
101
+
102
+ case 'ObjectTypeProperty':
103
+ case 'ObjectTypeSpreadProperty':
104
+ assertParent('ObjectTypeAnnotation');
105
+ return 'properties';
106
+
107
+ case 'Property':
108
+ assertParent(VALID_PROPERTY_PARENTS);
109
+ return 'properties';
110
+ // Identifier can be the child of a number of usecases
111
+
112
+ case 'Identifier':
113
+ switch (node.parent.type) {
114
+ case 'ArrowFunctionExpression':
115
+ case 'FunctionDeclaration':
116
+ case 'FunctionExpression':
117
+ return 'params';
118
+
119
+ case 'ArrayExpression':
120
+ case 'ArrayPattern':
121
+ return 'elements';
122
+
123
+ default:
124
+ throw new _Errors.InvalidRemovalError(getErrorMessage(['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'ArrayExpression', 'ArrayPattern']));
125
+ }
126
+
127
+ // RestElement can be the child of a number of usecases
128
+
129
+ case 'RestElement':
130
+ switch (node.parent.type) {
131
+ case 'ArrowFunctionExpression':
132
+ case 'FunctionDeclaration':
133
+ case 'FunctionExpression':
134
+ case 'ComponentDeclaration':
135
+ return 'params';
136
+
137
+ case 'ArrayPattern':
138
+ return 'elements';
139
+
140
+ case 'ObjectPattern':
141
+ return 'properties';
142
+ // $FlowFixMe[incompatible-type]
143
+
144
+ case 'OptionalCallExpression':
145
+ case 'CallExpression':
146
+ case 'NewExpression':
147
+ return 'arguments';
148
+
149
+ default:
150
+ throw new _Errors.InvalidRemovalError(getErrorMessage(['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'ComponentDeclaration', 'ArrayPattern', 'ObjectPattern', 'CallExpression', 'OptionalCallExpression', 'NewExpression']));
151
+ }
152
+
153
+ // SpreadElement can be the child of a number of usecases
154
+
155
+ case 'SpreadElement':
156
+ switch (node.parent.type) {
157
+ case 'ArrayExpression':
158
+ return 'elements';
159
+
160
+ case 'ObjectExpression':
161
+ return 'properties';
162
+ // $FlowFixMe[incompatible-type]
163
+
164
+ case 'OptionalCallExpression':
165
+ case 'CallExpression':
166
+ case 'NewExpression':
167
+ return 'arguments';
168
+
169
+ default:
170
+ throw new _Errors.InvalidRemovalError(getErrorMessage(['ArrayExpression', 'ObjectExpression', 'CallExpression', 'OptionalCallExpression', 'NewExpression']));
171
+ }
172
+
173
+ default:
174
+ throw new _Errors.InvalidRemovalError(`Cannot perform a remove mutation on node of type ${node.type}`);
175
+ }
176
+ })();
177
+
178
+ const targetIndex = (() => {
179
+ // $FlowExpectedError[prop-missing]
180
+ const arr = node.parent[key];
181
+ const idx = arr.indexOf(node);
182
+
183
+ if (idx === -1) {
184
+ throw new _Errors.InvalidRemovalError(`Could not find target in array of \`${node.parent.type}.${key}\`.`);
185
+ }
186
+
187
+ return idx;
188
+ })();
189
+
190
+ return {
191
+ type: 'array',
192
+ parent: node.parent,
193
+ key,
194
+ targetIndex
195
+ };
196
+ }
197
+
198
+ function performRemoveNodeMutation(mutationContext, mutation) {
199
+ const removalParent = getRemovalParent(mutation.node);
200
+ mutationContext.markDeletion(mutation.node);
201
+ mutationContext.markMutation(removalParent.parent, removalParent.key);
202
+ const parent = removalParent.parent;
203
+ parent[removalParent.key] = _hermesParser.astArrayMutationHelpers.removeFromArray(parent[removalParent.key], removalParent.targetIndex);
204
+ return removalParent.parent;
205
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createRemoveStatementMutation = createRemoveStatementMutation;
7
+ exports.performRemoveStatementMutation = performRemoveStatementMutation;
8
+
9
+ var _hermesParser = require("hermes-parser");
10
+
11
+ var _getStatementParent = require("./utils/getStatementParent");
12
+
13
+ var t = _interopRequireWildcard(require("../../generated/node-types"));
14
+
15
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
16
+
17
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
18
+
19
+ /**
20
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
21
+ *
22
+ * This source code is licensed under the MIT license found in the
23
+ * LICENSE file in the root directory of this source tree.
24
+ *
25
+ *
26
+ * @format
27
+ */
28
+ function createRemoveStatementMutation(node) {
29
+ return {
30
+ type: 'removeStatement',
31
+ node
32
+ };
33
+ }
34
+
35
+ function performRemoveStatementMutation(mutationContext, mutation) {
36
+ const removalParent = (0, _getStatementParent.getStatementParent)(mutation.node);
37
+ mutationContext.markDeletion(mutation.node);
38
+ mutationContext.markMutation(removalParent.parent, removalParent.key);
39
+
40
+ if (removalParent.type === 'array') {
41
+ const parent = removalParent.parent;
42
+ parent[removalParent.key] = _hermesParser.astArrayMutationHelpers.removeFromArray(parent[removalParent.key], removalParent.targetIndex);
43
+ } else {
44
+ // The parent has a 1:1 relationship on this key, so we can't just
45
+ // remove the node. Instead we replace it with an empty block statement.
46
+ // We COULD throw an error here and make the codemodder write a stricter
47
+ // codemod - but we decided to add this bit of magic to make it easier
48
+ // to write codemods.
49
+ // Worst case it creates some dead code that can be easily detected
50
+ // and cleaned up later.
51
+ const blockStatement = t.BlockStatement({
52
+ body: [],
53
+ parent: removalParent.parent
54
+ });
55
+ removalParent.parent[removalParent.key] = blockStatement;
56
+ }
57
+
58
+ return removalParent.parent;
59
+ }
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createReplaceNodeMutation = createReplaceNodeMutation;
7
+ exports.performReplaceNodeMutation = performReplaceNodeMutation;
8
+
9
+ var _hermesParser = require("hermes-parser");
10
+
11
+ var _comments = require("../comments/comments");
12
+
13
+ var _Errors = require("../Errors");
14
+
15
+ var _detachedNode = require("../../detachedNode");
16
+
17
+ /**
18
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
19
+ *
20
+ * This source code is licensed under the MIT license found in the
21
+ * LICENSE file in the root directory of this source tree.
22
+ *
23
+ *
24
+ * @format
25
+ */
26
+ function createReplaceNodeMutation(target, nodeToReplaceWith, options) {
27
+ var _options$keepComments;
28
+
29
+ return {
30
+ type: 'replaceNode',
31
+ target,
32
+ nodeToReplaceWith,
33
+ keepComments: (_options$keepComments = options == null ? void 0 : options.keepComments) != null ? _options$keepComments : false
34
+ };
35
+ }
36
+
37
+ function performReplaceNodeMutation(mutationContext, mutation) {
38
+ const replacementParent = getParentKey(mutation.target);
39
+ mutationContext.markDeletion(mutation.target);
40
+ mutationContext.markMutation(replacementParent.parent, replacementParent.key); // NOTE: currently this mutation assumes you're doing the right thing.
41
+ // it does no runtime checks and provides no guarantees about the
42
+ // correctness of the resulting code.
43
+ // TODO: maybe add some runtime checks based on codegenned predicates?
44
+
45
+ if (replacementParent.type === 'array') {
46
+ const parent = replacementParent.parent;
47
+ parent[replacementParent.key] = _hermesParser.astArrayMutationHelpers.replaceInArray(parent[replacementParent.key], replacementParent.targetIndex, [mutation.nodeToReplaceWith]);
48
+ } else {
49
+ replacementParent.parent[replacementParent.key] = mutation.nodeToReplaceWith;
50
+ }
51
+
52
+ if (mutation.keepComments) {
53
+ (0, _comments.moveCommentsToNewNode)(mutation.target, mutation.nodeToReplaceWith);
54
+ }
55
+
56
+ return replacementParent.parent;
57
+ }
58
+
59
+ function getParentKey(target) {
60
+ const parent = target.parent;
61
+
62
+ for (const key of (0, _hermesParser.getVisitorKeys)(parent)) {
63
+ const child = parent[key];
64
+
65
+ if ((0, _hermesParser.isNode)(child)) {
66
+ if (child === target) {
67
+ return {
68
+ type: 'single',
69
+ parent,
70
+ key
71
+ };
72
+ }
73
+ } else if (Array.isArray(child)) {
74
+ for (let i = 0; i < child.length; i += 1) {
75
+ const current = child[i];
76
+ const originalNode = (0, _detachedNode.getOriginalNode)(current);
77
+
78
+ if (current === target || originalNode === target) {
79
+ return {
80
+ type: 'array',
81
+ parent,
82
+ key,
83
+ targetIndex: i
84
+ };
85
+ }
86
+ }
87
+ }
88
+ } // this shouldn't happen ever
89
+
90
+
91
+ throw new _Errors.InvalidReplacementError(`Expected to find the ${target.type} as a direct child of the ${parent.type}.`);
92
+ }