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,79 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createReplaceStatementWithManyMutation = createReplaceStatementWithManyMutation;
7
+ exports.performReplaceStatementWithManyMutation = performReplaceStatementWithManyMutation;
8
+
9
+ var _hermesParser = require("hermes-parser");
10
+
11
+ var _getStatementParent = require("./utils/getStatementParent");
12
+
13
+ var _isValidModuleDeclarationParent = require("./utils/isValidModuleDeclarationParent");
14
+
15
+ var _comments = require("../comments/comments");
16
+
17
+ var _Errors = require("../Errors");
18
+
19
+ var t = _interopRequireWildcard(require("../../generated/node-types"));
20
+
21
+ 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); }
22
+
23
+ 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; }
24
+
25
+ /**
26
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
27
+ *
28
+ * This source code is licensed under the MIT license found in the
29
+ * LICENSE file in the root directory of this source tree.
30
+ *
31
+ *
32
+ * @format
33
+ */
34
+ function createReplaceStatementWithManyMutation(target, nodesToReplaceWith, options) {
35
+ var _options$keepComments;
36
+
37
+ if (nodesToReplaceWith.length === 0) {
38
+ return null;
39
+ }
40
+
41
+ return {
42
+ type: 'replaceStatementWithMany',
43
+ target,
44
+ nodesToReplaceWith,
45
+ keepComments: (_options$keepComments = options == null ? void 0 : options.keepComments) != null ? _options$keepComments : false
46
+ };
47
+ }
48
+
49
+ function performReplaceStatementWithManyMutation(mutationContext, mutation) {
50
+ const replacementParent = (0, _getStatementParent.getStatementParent)(mutation.target); // enforce that if we are replacing with module declarations - they are being inserted in a valid location
51
+
52
+ if (!(0, _isValidModuleDeclarationParent.isValidModuleDeclarationParent)(replacementParent.parent, mutation.nodesToReplaceWith)) {
53
+ throw new _Errors.InvalidReplacementError(`import/export cannot be replaced into a ${replacementParent.parent.type}.`);
54
+ }
55
+
56
+ mutationContext.markDeletion(mutation.target);
57
+ mutationContext.markMutation(replacementParent.parent, replacementParent.key);
58
+
59
+ if (mutation.keepComments) {
60
+ // attach comments to the very first replacement node
61
+ (0, _comments.moveCommentsToNewNode)(mutation.target, mutation.nodesToReplaceWith[0]);
62
+ }
63
+
64
+ if (replacementParent.type === 'array') {
65
+ const parent = replacementParent.parent;
66
+ parent[replacementParent.key] = _hermesParser.astArrayMutationHelpers.replaceInArray(parent[replacementParent.key], replacementParent.targetIndex, mutation.nodesToReplaceWith);
67
+ return replacementParent.parent;
68
+ }
69
+
70
+ const statementsToReplaceWith = // $FlowExpectedError[incompatible-cast] -- this is enforced by isValidModuleDeclarationParent above
71
+ mutation.nodesToReplaceWith; // we need to wrap the nodes in a BlockStatement as before there was only 1 node
72
+
73
+ const blockStatement = t.BlockStatement({
74
+ body: statementsToReplaceWith,
75
+ parent: replacementParent.parent
76
+ });
77
+ replacementParent.parent[replacementParent.key] = blockStatement;
78
+ return replacementParent.parent;
79
+ }
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getStatementParent = getStatementParent;
7
+
8
+ var _Errors = require("../../Errors");
9
+
10
+ /**
11
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
12
+ *
13
+ * This source code is licensed under the MIT license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ *
16
+ *
17
+ * @format
18
+ */
19
+ function getStatementParent(target) {
20
+ function assertValidStatementLocation(parentWithType, ...invalidKeys) {
21
+ for (const key of invalidKeys) {
22
+ // $FlowExpectedError[prop-missing]
23
+ const value = parentWithType[key];
24
+
25
+ if (value === target || Array.isArray(value) && value.includes(target)) {
26
+ throw new _Errors.InvalidStatementError(`Attempted to insert a statement into \`${parentWithType.type}.${key}\`.`);
27
+ }
28
+ }
29
+ }
30
+
31
+ function getAssertedIndex(key, arr) {
32
+ const idx = arr.indexOf(target);
33
+
34
+ if (idx === -1) {
35
+ throw new _Errors.InvalidStatementError(`Could not find target in array of \`${parent.type}.${key}\`.`);
36
+ }
37
+
38
+ return idx;
39
+ }
40
+
41
+ const parent = target.parent;
42
+
43
+ const result = (() => {
44
+ switch (parent.type) {
45
+ case 'IfStatement':
46
+ {
47
+ assertValidStatementLocation(parent, 'test');
48
+ const key = parent.consequent === target ? 'consequent' : 'alternate';
49
+ return {
50
+ type: 'single',
51
+ parent,
52
+ key
53
+ };
54
+ }
55
+
56
+ case 'LabeledStatement':
57
+ {
58
+ assertValidStatementLocation(parent, 'label');
59
+ return {
60
+ type: 'single',
61
+ parent,
62
+ key: 'body'
63
+ };
64
+ }
65
+
66
+ case 'WithStatement':
67
+ {
68
+ assertValidStatementLocation(parent, 'object');
69
+ return {
70
+ type: 'single',
71
+ parent,
72
+ key: 'body'
73
+ };
74
+ }
75
+
76
+ case 'DoWhileStatement':
77
+ case 'WhileStatement':
78
+ {
79
+ assertValidStatementLocation(parent, 'test');
80
+ return {
81
+ type: 'single',
82
+ parent,
83
+ key: 'body'
84
+ };
85
+ }
86
+
87
+ case 'ForStatement':
88
+ {
89
+ assertValidStatementLocation(parent, 'init', 'test', 'update');
90
+ return {
91
+ type: 'single',
92
+ parent,
93
+ key: 'body'
94
+ };
95
+ }
96
+
97
+ case 'ForInStatement':
98
+ case 'ForOfStatement':
99
+ {
100
+ assertValidStatementLocation(parent, // $FlowExpectedError[prop-missing] - flow does not track properties from parent interface
101
+ 'left', // $FlowExpectedError[prop-missing] - flow does not track properties from parent interface
102
+ 'right');
103
+ return {
104
+ type: 'single',
105
+ parent,
106
+ key: 'body'
107
+ };
108
+ }
109
+
110
+ case 'SwitchCase':
111
+ {
112
+ assertValidStatementLocation(parent, 'test');
113
+ return {
114
+ type: 'array',
115
+ parent,
116
+ key: 'consequent',
117
+ targetIndex: getAssertedIndex('consequent', parent.consequent)
118
+ };
119
+ }
120
+
121
+ case 'BlockStatement':
122
+ case 'Program':
123
+ {
124
+ return {
125
+ type: 'array',
126
+ parent,
127
+ key: 'body',
128
+ targetIndex: getAssertedIndex('body', parent.body)
129
+ };
130
+ }
131
+ }
132
+
133
+ throw new _Errors.InvalidStatementError(`Expected to find a valid statement parent, but found a parent of type "${parent.type}".`);
134
+ })();
135
+
136
+ if ( // array insertions are already validated by the getAssertedIndex function
137
+ result.targetIndex == null && // $FlowExpectedError[prop-missing]
138
+ result.parent[result.key] !== target) {
139
+ throw new _Errors.InvalidStatementError(`Expected to find the target "${target.type}" on the "${result.parent.type}.${result.key}", but found a different node. ` + 'This likely means that you attempted to mutate around the target after it was deleted/replaced.');
140
+ }
141
+
142
+ return result;
143
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isValidModuleDeclarationParent = isValidModuleDeclarationParent;
7
+
8
+ /**
9
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
10
+ *
11
+ * This source code is licensed under the MIT license found in the
12
+ * LICENSE file in the root directory of this source tree.
13
+ *
14
+ *
15
+ * @noformat
16
+ */
17
+ function isModuleDeclaration(node)
18
+ /*: node is (
19
+ | ImportDeclaration
20
+ | ExportNamedDeclaration
21
+ | ExportDefaultDeclaration
22
+ | ExportAllDeclaration
23
+ ) */
24
+ {
25
+ return node.type === 'ImportDeclaration' || node.type === 'ExportNamedDeclaration' || node.type === 'ExportDefaultDeclaration' || node.type === 'ExportAllDeclaration';
26
+ }
27
+
28
+ function isValidModuleDeclarationParent(target, nodesToInsertOrReplace) {
29
+ if (target.type === 'Program' || target.type === 'BlockStatement' && target.parent.type === 'DeclareModule') {
30
+ return true;
31
+ }
32
+
33
+ for (const node of nodesToInsertOrReplace) {
34
+ if (!isModuleDeclaration( // $FlowExpectedError[incompatible-cast]
35
+ node)) {
36
+ continue;
37
+ }
38
+
39
+ return false;
40
+ }
41
+
42
+ return true;
43
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @format
9
+ */
10
+ 'use strict';
11
+
12
+ Object.defineProperty(exports, "__esModule", {
13
+ value: true
14
+ });
15
+ exports.parse = parse;
16
+
17
+ var _comments = require("./comments/comments");
18
+
19
+ var _hermesEslint = require("hermes-eslint");
20
+
21
+ async function parse(code) {
22
+ const {
23
+ ast,
24
+ scopeManager
25
+ } = (0, _hermesEslint.parseForESLint)(code, {
26
+ sourceType: 'module',
27
+ enableExperimentalComponentSyntax: true
28
+ }); // Don't include the docblock comment in the comment list as we don't want to attach it
29
+ // as it should be maintained at the top of the file as nodes are moved around.
30
+
31
+ let comments = ast.comments;
32
+
33
+ if (ast.docblock != null && ast.docblock.comment === comments[0]) {
34
+ const [first, ...nonDocblockComments] = comments; // Since we will not be attaching this comment automatically we need to add the
35
+ // properties prettier expects for printing.
36
+ // $FlowExpectedError[prop-missing]
37
+
38
+ first.placement = 'endOfLine'; // $FlowExpectedError[prop-missing]
39
+
40
+ first.leading = true; // $FlowExpectedError[prop-missing]
41
+
42
+ first.trailing = false; // $FlowExpectedError[prop-missing]
43
+
44
+ first.printed = false;
45
+ comments = nonDocblockComments;
46
+ } // attach comments before mutation. this will ensure that as nodes are
47
+ // cloned / moved around - comments remain in the correct place with respect to the node
48
+
49
+
50
+ (0, _comments.attachComments)(comments, ast, code);
51
+ return {
52
+ ast,
53
+ scopeManager,
54
+ code
55
+ };
56
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @format
9
+ */
10
+ 'use strict';
11
+
12
+ Object.defineProperty(exports, "__esModule", {
13
+ value: true
14
+ });
15
+ exports.print = print;
16
+
17
+ var _hermesParser = require("hermes-parser");
18
+
19
+ var prettier = _interopRequireWildcard(require("prettier"));
20
+
21
+ var _comments = require("./comments/comments");
22
+
23
+ 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); }
24
+
25
+ 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; }
26
+
27
+ let cache = 1;
28
+ const cacheBase = Math.random();
29
+
30
+ async function print(ast, originalCode, prettierOptions = {}, visitorKeys) {
31
+ // $FlowExpectedError[incompatible-type] This is now safe to access.
32
+ const program = ast; // If the AST body is empty, we can skip the cost of prettier by returning a static string of the contents.
33
+
34
+ if (program.body.length === 0) {
35
+ var _program$docblock;
36
+
37
+ // If the program had a docblock comment, we need to create the string manually.
38
+ const docblockComment = (_program$docblock = program.docblock) == null ? void 0 : _program$docblock.comment;
39
+
40
+ if (docblockComment != null) {
41
+ return '/*' + docblockComment.value + '*/\n';
42
+ }
43
+
44
+ return '';
45
+ } // Cleanup the comments from the AST and generate the "orginal" code needed for prettier.
46
+
47
+
48
+ const codeForPrinting = (0, _comments.mutateESTreeASTCommentsForPrettier)(program, originalCode); // Fix up the AST to match what prettier expects.
49
+
50
+ (0, _hermesParser.mutateESTreeASTForPrettier)(program, visitorKeys);
51
+
52
+ switch (getPrettierMajorVersion()) {
53
+ case '3':
54
+ {
55
+ // Lazy require this module as it only exists in prettier v3.
56
+ const prettierFlowPlugin = require('prettier/plugins/flow');
57
+
58
+ return prettier.format(codeForPrinting, // $FlowExpectedError[incompatible-exact] - we don't want to create a dependency on the prettier types
59
+ { ...prettierOptions,
60
+ parser: 'flow',
61
+ requirePragma: false,
62
+ plugins: [{
63
+ parsers: {
64
+ flow: { ...prettierFlowPlugin.parsers.flow,
65
+
66
+ parse() {
67
+ return program;
68
+ }
69
+
70
+ }
71
+ }
72
+ }]
73
+ });
74
+ }
75
+
76
+ case '2':
77
+ {
78
+ var _hermesPlugin$parsers;
79
+
80
+ const hermesPlugin = require('prettier-plugin-hermes-parser');
81
+
82
+ const hermesParser = (_hermesPlugin$parsers = hermesPlugin.parsers) == null ? void 0 : _hermesPlugin$parsers.hermes;
83
+
84
+ if (hermesParser == null) {
85
+ throw new Error('Hermes parser plugin not found');
86
+ }
87
+
88
+ return prettier.format(codeForPrinting, // $FlowExpectedError[incompatible-exact] - we don't want to create a dependency on the prettier types
89
+ { ...prettierOptions,
90
+ parser: 'hermes',
91
+ requirePragma: false,
92
+ plugins: [// $FlowExpectedError[incompatible-call] Cache value is not expected but needed in this case.
93
+ {
94
+ parsers: {
95
+ hermes: { ...hermesParser,
96
+ // Prettier caches the plugin, by making this key always unique we ensure the new `parse`
97
+ // function with the correct AST is always called.
98
+ cache: `${cacheBase}-${cache++}`,
99
+
100
+ // Provide the passed AST to prettier
101
+ parse() {
102
+ return program;
103
+ }
104
+
105
+ }
106
+ },
107
+ printers: hermesPlugin.printers
108
+ }]
109
+ });
110
+ }
111
+
112
+ case 'UNSUPPORTED':
113
+ default:
114
+ {
115
+ throw new Error(`Unknown or unsupported prettier version of "${prettier.version}". Only major versions 3 or 2 of prettier are supported.`);
116
+ }
117
+ }
118
+ }
119
+
120
+ function getPrettierMajorVersion() {
121
+ const {
122
+ version
123
+ } = prettier;
124
+
125
+ if (version.startsWith('3.')) {
126
+ return '3';
127
+ }
128
+
129
+ if (version.startsWith('2.')) {
130
+ return '2';
131
+ }
132
+
133
+ return 'UNSUPPORTED';
134
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @format
9
+ */
10
+ 'use strict';
11
+
12
+ Object.defineProperty(exports, "__esModule", {
13
+ value: true
14
+ });
15
+ exports.transform = transform;
16
+
17
+ var _transformAST = require("./transformAST");
18
+
19
+ var _parse = require("./parse");
20
+
21
+ var _print = require("./print");
22
+
23
+ async function transform(originalCode, visitors, prettierOptions = {}) {
24
+ const parseResult = await (0, _parse.parse)(originalCode);
25
+ const {
26
+ ast,
27
+ astWasMutated,
28
+ mutatedCode
29
+ } = (0, _transformAST.transformAST)(parseResult, visitors);
30
+
31
+ if (!astWasMutated) {
32
+ return originalCode;
33
+ }
34
+
35
+ return (0, _print.print)(ast, mutatedCode, prettierOptions);
36
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @format
9
+ */
10
+ 'use strict';
11
+
12
+ Object.defineProperty(exports, "__esModule", {
13
+ value: true
14
+ });
15
+ exports.transformAST = transformAST;
16
+
17
+ var _detachedNode = require("../detachedNode");
18
+
19
+ var _traverse = require("../traverse/traverse");
20
+
21
+ var _MutationContext = require("./MutationContext");
22
+
23
+ var _TransformContext = require("./TransformContext");
24
+
25
+ var _AddComments = require("./mutations/AddComments");
26
+
27
+ var _CloneCommentsTo = require("./mutations/CloneCommentsTo");
28
+
29
+ var _InsertStatement = require("./mutations/InsertStatement");
30
+
31
+ var _RemoveComment = require("./mutations/RemoveComment");
32
+
33
+ var _RemoveNode = require("./mutations/RemoveNode");
34
+
35
+ var _RemoveStatement = require("./mutations/RemoveStatement");
36
+
37
+ var _ReplaceNode = require("./mutations/ReplaceNode");
38
+
39
+ var _ReplaceStatementWithMany = require("./mutations/ReplaceStatementWithMany");
40
+
41
+ var _ModifyNodeInPlace = require("./mutations/ModifyNodeInPlace");
42
+
43
+ function transformAST({
44
+ ast,
45
+ scopeManager,
46
+ code
47
+ }, visitors) {
48
+ // traverse the AST and collect the mutations
49
+ const transformContext = (0, _TransformContext.getTransformContext)();
50
+ (0, _traverse.traverseWithContext)(code, ast, scopeManager, () => transformContext, visitors); // apply the mutations to the AST
51
+
52
+ const mutationContext = new _MutationContext.MutationContext(code);
53
+ const removeCommentMutations = [];
54
+
55
+ for (const mutation of transformContext.mutations) {
56
+ const mutationRoot = (() => {
57
+ switch (mutation.type) {
58
+ case 'modifyNodeInPlace':
59
+ {
60
+ return (0, _ModifyNodeInPlace.performModifyNodeInPlaceMutation)(mutationContext, mutation);
61
+ }
62
+
63
+ case 'insertStatement':
64
+ {
65
+ return (0, _InsertStatement.performInsertStatementMutation)(mutationContext, mutation);
66
+ }
67
+
68
+ case 'replaceNode':
69
+ {
70
+ return (0, _ReplaceNode.performReplaceNodeMutation)(mutationContext, mutation);
71
+ }
72
+
73
+ case 'replaceStatementWithMany':
74
+ {
75
+ return (0, _ReplaceStatementWithMany.performReplaceStatementWithManyMutation)(mutationContext, mutation);
76
+ }
77
+
78
+ case 'removeNode':
79
+ {
80
+ return (0, _RemoveNode.performRemoveNodeMutation)(mutationContext, mutation);
81
+ }
82
+
83
+ case 'removeStatement':
84
+ {
85
+ return (0, _RemoveStatement.performRemoveStatementMutation)(mutationContext, mutation);
86
+ }
87
+
88
+ case 'removeComment':
89
+ {
90
+ // these are handled later
91
+ removeCommentMutations.push(mutation);
92
+ return null;
93
+ }
94
+
95
+ case 'addComments':
96
+ {
97
+ return (0, _AddComments.performAddCommentsMutation)(mutationContext, mutation);
98
+ }
99
+
100
+ case 'cloneCommentsTo':
101
+ {
102
+ return (0, _CloneCommentsTo.performCloneCommentsToMutation)(mutationContext, mutation);
103
+ }
104
+ }
105
+ })(); // ensure the subtree's parent pointers are correct
106
+ // this is required for two reasons:
107
+ // 1) The userland transform is just JS - so there's nothing stopping them
108
+ // from doing anything dodgy. The flow types have some enforcement, but
109
+ // ofc that can just be ignored with a suppression.
110
+ // 2) Shallow clones are a necessary evil in the transform because they
111
+ // allow codemods to do simple changes to just one node without the
112
+ // weight that comes with deeply cloning the entire AST.
113
+ // However we can't update the parent pointers of the cloned node's
114
+ // children until the mutation step or else we would be mutating
115
+ // real AST nodes and potentially break the traverse step.
116
+ //
117
+ // Being strict here just helps us ensure we keep everything in sync
118
+
119
+
120
+ if (mutationRoot) {
121
+ (0, _detachedNode.updateAllParentPointers)(mutationRoot);
122
+ }
123
+ } // remove the comments
124
+ // this is done at the end because it requires a complete traversal of the AST
125
+ // so that we can find relevant node's attachment array
126
+
127
+
128
+ (0, _RemoveComment.performRemoveCommentMutations)(ast, removeCommentMutations);
129
+ return {
130
+ ast,
131
+ astWasMutated: transformContext.astWasMutated,
132
+ mutatedCode: mutationContext.code
133
+ };
134
+ }