hermes-transform 0.5.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 (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +8 -0
  3. package/dist/detachedNode.js +128 -0
  4. package/dist/detachedNode.js.flow +113 -0
  5. package/dist/generated/TransformCloneSignatures.js.flow +19 -0
  6. package/dist/generated/TransformReplaceSignatures.js.flow +943 -0
  7. package/dist/generated/node-types.js +2071 -0
  8. package/dist/generated/node-types.js.flow +3149 -0
  9. package/dist/generated/special-case-node-types.js +178 -0
  10. package/dist/generated/special-case-node-types.js.flow +248 -0
  11. package/dist/getVisitorKeys.js +35 -0
  12. package/dist/getVisitorKeys.js.flow +31 -0
  13. package/dist/index.js +41 -0
  14. package/dist/index.js.flow +15 -0
  15. package/dist/transform/Errors.js +151 -0
  16. package/dist/transform/Errors.js.flow +17 -0
  17. package/dist/transform/MutationContext.js +94 -0
  18. package/dist/transform/MutationContext.js.flow +80 -0
  19. package/dist/transform/TransformContext.js +136 -0
  20. package/dist/transform/TransformContext.js.flow +378 -0
  21. package/dist/transform/comments/comments.js +140 -0
  22. package/dist/transform/comments/comments.js.flow +145 -0
  23. package/dist/transform/comments/prettier/README.md +6 -0
  24. package/dist/transform/comments/prettier/common/util.js +365 -0
  25. package/dist/transform/comments/prettier/common/util.js.flow +349 -0
  26. package/dist/transform/comments/prettier/language-js/comments.js +777 -0
  27. package/dist/transform/comments/prettier/language-js/comments.js.flow +950 -0
  28. package/dist/transform/comments/prettier/language-js/loc.js +41 -0
  29. package/dist/transform/comments/prettier/language-js/loc.js.flow +41 -0
  30. package/dist/transform/comments/prettier/language-js/printer-estree.js +31 -0
  31. package/dist/transform/comments/prettier/language-js/printer-estree.js.flow +37 -0
  32. package/dist/transform/comments/prettier/language-js/utils.js +131 -0
  33. package/dist/transform/comments/prettier/language-js/utils.js.flow +135 -0
  34. package/dist/transform/comments/prettier/main/comments.js +513 -0
  35. package/dist/transform/comments/prettier/main/comments.js.flow +436 -0
  36. package/dist/transform/comments/prettier/utils/get-last.js +15 -0
  37. package/dist/transform/comments/prettier/utils/get-last.js.flow +14 -0
  38. package/dist/transform/getTransformedAST.js +159 -0
  39. package/dist/transform/getTransformedAST.js.flow +128 -0
  40. package/dist/transform/mutations/AddLeadingComments.js +47 -0
  41. package/dist/transform/mutations/AddLeadingComments.js.flow +49 -0
  42. package/dist/transform/mutations/AddTrailingComments.js +47 -0
  43. package/dist/transform/mutations/AddTrailingComments.js.flow +49 -0
  44. package/dist/transform/mutations/CloneCommentsTo.js +46 -0
  45. package/dist/transform/mutations/CloneCommentsTo.js.flow +51 -0
  46. package/dist/transform/mutations/InsertStatement.js +92 -0
  47. package/dist/transform/mutations/InsertStatement.js.flow +113 -0
  48. package/dist/transform/mutations/RemoveComment.js +96 -0
  49. package/dist/transform/mutations/RemoveComment.js.flow +80 -0
  50. package/dist/transform/mutations/RemoveStatement.js +61 -0
  51. package/dist/transform/mutations/RemoveStatement.js.flow +68 -0
  52. package/dist/transform/mutations/ReplaceNode.js +96 -0
  53. package/dist/transform/mutations/ReplaceNode.js.flow +113 -0
  54. package/dist/transform/mutations/ReplaceStatementWithMany.js +81 -0
  55. package/dist/transform/mutations/ReplaceStatementWithMany.js.flow +102 -0
  56. package/dist/transform/mutations/utils/arrayUtils.js +41 -0
  57. package/dist/transform/mutations/utils/arrayUtils.js.flow +35 -0
  58. package/dist/transform/mutations/utils/getStatementParent.js +147 -0
  59. package/dist/transform/mutations/utils/getStatementParent.js.flow +143 -0
  60. package/dist/transform/mutations/utils/isValidModuleDeclarationParent.js +53 -0
  61. package/dist/transform/mutations/utils/isValidModuleDeclarationParent.js.flow +50 -0
  62. package/dist/transform/transform.js +69 -0
  63. package/dist/transform/transform.js.flow +60 -0
  64. package/dist/traverse/NodeEventGenerator.js +427 -0
  65. package/dist/traverse/NodeEventGenerator.js.flow +406 -0
  66. package/dist/traverse/SafeEmitter.js +70 -0
  67. package/dist/traverse/SafeEmitter.js.flow +46 -0
  68. package/dist/traverse/SimpleTraverser.js +149 -0
  69. package/dist/traverse/SimpleTraverser.js.flow +109 -0
  70. package/dist/traverse/esquery.js +37 -0
  71. package/dist/traverse/esquery.js.flow +173 -0
  72. package/dist/traverse/traverse.js +139 -0
  73. package/dist/traverse/traverse.js.flow +149 -0
  74. package/package.json +22 -0
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its 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
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ import type {ESNode, Program} from 'hermes-estree';
14
+ import type {Visitor} from '../traverse/traverse';
15
+ import type {TransformContext} from './TransformContext';
16
+ import type {RemoveCommentMutation} from './mutations/RemoveComment';
17
+
18
+ import {parseForESLint} from 'hermes-eslint';
19
+ import {updateAllParentPointers} from '../detachedNode';
20
+ import {traverseWithContext} from '../traverse/traverse';
21
+ import {MutationContext} from './MutationContext';
22
+ import {getTransformContext} from './TransformContext';
23
+ import {attachComments} from './comments/comments';
24
+ import {performAddLeadingCommentsMutation} from './mutations/AddLeadingComments';
25
+ import {performAddTrailingCommentsMutation} from './mutations/AddTrailingComments';
26
+ import {performCloneCommentsToMutation} from './mutations/CloneCommentsTo';
27
+ import {performInsertStatementMutation} from './mutations/InsertStatement';
28
+ import {performRemoveCommentMutations} from './mutations/RemoveComment';
29
+ import {performRemoveStatementMutation} from './mutations/RemoveStatement';
30
+ import {performReplaceNodeMutation} from './mutations/ReplaceNode';
31
+ import {performReplaceStatementWithManyMutation} from './mutations/ReplaceStatementWithMany';
32
+
33
+ export function getTransformedAST(
34
+ code: string,
35
+ visitors: Visitor<TransformContext>,
36
+ ): {
37
+ ast: Program,
38
+ astWasMutated: boolean,
39
+ mutatedCode: string,
40
+ } {
41
+ const {ast, scopeManager} = parseForESLint(code, {
42
+ sourceType: 'module',
43
+ });
44
+
45
+ // attach comments before mutation. this will ensure that as nodes are
46
+ // cloned / moved around - comments remain in the correct place with respect to the node
47
+ attachComments(ast.comments, ast, code);
48
+
49
+ // traverse the AST and colllect the mutations
50
+ const transformContext = getTransformContext();
51
+ traverseWithContext(ast, scopeManager, () => transformContext, visitors);
52
+
53
+ // apply the mutations to the AST
54
+ const mutationContext = new MutationContext(code);
55
+
56
+ const removeCommentMutations: Array<RemoveCommentMutation> = [];
57
+
58
+ for (const mutation of transformContext.mutations) {
59
+ const mutationRoot = ((): ESNode | null => {
60
+ switch (mutation.type) {
61
+ case 'insertStatement': {
62
+ return performInsertStatementMutation(mutationContext, mutation);
63
+ }
64
+
65
+ case 'replaceNode': {
66
+ return performReplaceNodeMutation(mutationContext, mutation);
67
+ }
68
+
69
+ case 'replaceStatementWithMany': {
70
+ return performReplaceStatementWithManyMutation(
71
+ mutationContext,
72
+ mutation,
73
+ );
74
+ }
75
+
76
+ case 'removeStatement': {
77
+ return performRemoveStatementMutation(mutationContext, mutation);
78
+ }
79
+
80
+ case 'removeComment': {
81
+ // these are handled later
82
+ removeCommentMutations.push(mutation);
83
+ return null;
84
+ }
85
+
86
+ case 'addLeadingComments': {
87
+ return performAddLeadingCommentsMutation(mutationContext, mutation);
88
+ }
89
+
90
+ case 'addTrailingComments': {
91
+ return performAddTrailingCommentsMutation(mutationContext, mutation);
92
+ }
93
+
94
+ case 'cloneCommentsTo': {
95
+ return performCloneCommentsToMutation(mutationContext, mutation);
96
+ }
97
+ }
98
+ })();
99
+
100
+ // ensure the subtree's parent pointers are correct
101
+ // this is required for two reasons:
102
+ // 1) The userland transform is just JS - so there's nothing stopping them
103
+ // from doing anything dodgy. The flow types have some enforcement, but
104
+ // ofc that can just be ignored with a suppression.
105
+ // 2) Shallow clones are a necessary evil in the transform because they
106
+ // allow codemods to do simple changes to just one node without the
107
+ // weight that comes with deeply cloning the entire AST.
108
+ // However we can't update the parent pointers of the cloned node's
109
+ // children until the mutation step or else we would be mutating
110
+ // real AST nodes and potentially break the traverse step.
111
+ //
112
+ // Being strict here just helps us ensure we keep everything in sync
113
+ if (mutationRoot) {
114
+ updateAllParentPointers(mutationRoot);
115
+ }
116
+ }
117
+
118
+ // remove the comments
119
+ // this is done at the end because it requires a complete traversal of the AST
120
+ // so that we can find relevant node's attachment array
121
+ performRemoveCommentMutations(ast, removeCommentMutations);
122
+
123
+ return {
124
+ ast,
125
+ astWasMutated: transformContext.astWasMutated,
126
+ mutatedCode: mutationContext.code,
127
+ };
128
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createAddLeadingCommentsMutation = createAddLeadingCommentsMutation;
7
+ exports.performAddLeadingCommentsMutation = performAddLeadingCommentsMutation;
8
+
9
+ var _comments = require("../comments/comments");
10
+
11
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
12
+
13
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
14
+
15
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
16
+
17
+ function createAddLeadingCommentsMutation(node, comments) {
18
+ if (comments.length === 0) {
19
+ return null;
20
+ }
21
+
22
+ return {
23
+ type: 'addLeadingComments',
24
+ comments: comments,
25
+ node: node
26
+ };
27
+ }
28
+
29
+ function performAddLeadingCommentsMutation(mutationContext, mutation) {
30
+ var _iterator = _createForOfIteratorHelper(mutation.comments),
31
+ _step;
32
+
33
+ try {
34
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
35
+ var originalComment = _step.value;
36
+ var comment = (0, _comments.cloneComment)(originalComment);
37
+ mutationContext.appendCommentToSource(comment);
38
+ (0, _comments.addLeadingComment)(mutation.node, comment);
39
+ }
40
+ } catch (err) {
41
+ _iterator.e(err);
42
+ } finally {
43
+ _iterator.f();
44
+ }
45
+
46
+ return null;
47
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its 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
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ import type {Comment, ESNode} from 'hermes-estree';
12
+ import type {DetachedNode} from '../../detachedNode';
13
+ import type {MutationContext} from '../MutationContext';
14
+
15
+ import {addLeadingComment, cloneComment} from '../comments/comments';
16
+
17
+ export type AddLeadingCommentsMutation = $ReadOnly<{
18
+ type: 'addLeadingComments',
19
+ comments: $ReadOnlyArray<Comment>,
20
+ node: ESNode | DetachedNode<ESNode>,
21
+ }>;
22
+
23
+ export function createAddLeadingCommentsMutation(
24
+ node: AddLeadingCommentsMutation['node'],
25
+ comments: AddLeadingCommentsMutation['comments'],
26
+ ): ?AddLeadingCommentsMutation {
27
+ if (comments.length === 0) {
28
+ return null;
29
+ }
30
+
31
+ return {
32
+ type: 'addLeadingComments',
33
+ comments,
34
+ node,
35
+ };
36
+ }
37
+
38
+ export function performAddLeadingCommentsMutation(
39
+ mutationContext: MutationContext,
40
+ mutation: AddLeadingCommentsMutation,
41
+ ): null {
42
+ for (const originalComment of mutation.comments) {
43
+ const comment = cloneComment(originalComment);
44
+ mutationContext.appendCommentToSource(comment);
45
+ addLeadingComment(mutation.node, comment);
46
+ }
47
+
48
+ return null;
49
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createAddTrailingCommentsMutation = createAddTrailingCommentsMutation;
7
+ exports.performAddTrailingCommentsMutation = performAddTrailingCommentsMutation;
8
+
9
+ var _comments = require("../comments/comments");
10
+
11
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
12
+
13
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
14
+
15
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
16
+
17
+ function createAddTrailingCommentsMutation(node, comments) {
18
+ if (comments.length === 0) {
19
+ return null;
20
+ }
21
+
22
+ return {
23
+ type: 'addTrailingComments',
24
+ comments: comments,
25
+ node: node
26
+ };
27
+ }
28
+
29
+ function performAddTrailingCommentsMutation(mutationContext, mutation) {
30
+ var _iterator = _createForOfIteratorHelper(mutation.comments),
31
+ _step;
32
+
33
+ try {
34
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
35
+ var originalComment = _step.value;
36
+ var comment = (0, _comments.cloneComment)(originalComment);
37
+ mutationContext.appendCommentToSource(comment);
38
+ (0, _comments.addTrailingComment)(mutation.node, comment);
39
+ }
40
+ } catch (err) {
41
+ _iterator.e(err);
42
+ } finally {
43
+ _iterator.f();
44
+ }
45
+
46
+ return null;
47
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its 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
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ import type {Comment, ESNode} from 'hermes-estree';
12
+ import type {DetachedNode} from '../../detachedNode';
13
+ import type {MutationContext} from '../MutationContext';
14
+
15
+ import {addTrailingComment, cloneComment} from '../comments/comments';
16
+
17
+ export type AddTrailingCommentsMutation = $ReadOnly<{
18
+ type: 'addTrailingComments',
19
+ comments: $ReadOnlyArray<Comment>,
20
+ node: ESNode | DetachedNode<ESNode>,
21
+ }>;
22
+
23
+ export function createAddTrailingCommentsMutation(
24
+ node: AddTrailingCommentsMutation['node'],
25
+ comments: AddTrailingCommentsMutation['comments'],
26
+ ): ?AddTrailingCommentsMutation {
27
+ if (comments.length === 0) {
28
+ return null;
29
+ }
30
+
31
+ return {
32
+ type: 'addTrailingComments',
33
+ comments,
34
+ node,
35
+ };
36
+ }
37
+
38
+ export function performAddTrailingCommentsMutation(
39
+ mutationContext: MutationContext,
40
+ mutation: AddTrailingCommentsMutation,
41
+ ): null {
42
+ for (const originalComment of mutation.comments) {
43
+ const comment = cloneComment(originalComment);
44
+ mutationContext.appendCommentToSource(comment);
45
+ addTrailingComment(mutation.node, comment);
46
+ }
47
+
48
+ return null;
49
+ }
@@ -0,0 +1,46 @@
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
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
12
+
13
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
14
+
15
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
16
+
17
+ function createCloneCommentsToMutation(target, destination) {
18
+ return {
19
+ type: 'cloneCommentsTo',
20
+ target: target,
21
+ destination: destination
22
+ };
23
+ }
24
+
25
+ function performCloneCommentsToMutation(mutationContext, mutation) {
26
+ var newComments = [];
27
+
28
+ var _iterator = _createForOfIteratorHelper((0, _comments.getCommentsForNode)(mutation.target)),
29
+ _step;
30
+
31
+ try {
32
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
33
+ var originalComment = _step.value;
34
+ var comment = (0, _comments.cloneCommentWithMarkers)(originalComment);
35
+ mutationContext.appendCommentToSource(comment);
36
+ newComments.push(comment);
37
+ }
38
+ } catch (err) {
39
+ _iterator.e(err);
40
+ } finally {
41
+ _iterator.f();
42
+ }
43
+
44
+ (0, _comments.addCommentsToNode)(mutation.destination, newComments);
45
+ return null;
46
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its 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
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ import type {ESNode} from 'hermes-estree';
12
+ import type {DetachedNode} from '../../detachedNode';
13
+ import type {MutationContext} from '../MutationContext';
14
+
15
+ import {
16
+ addCommentsToNode,
17
+ cloneCommentWithMarkers,
18
+ getCommentsForNode,
19
+ } from '../comments/comments';
20
+
21
+ export type CloneCommentsToMutation = $ReadOnly<{
22
+ type: 'cloneCommentsTo',
23
+ target: ESNode | DetachedNode<ESNode>,
24
+ destination: ESNode | DetachedNode<ESNode>,
25
+ }>;
26
+
27
+ export function createCloneCommentsToMutation(
28
+ target: CloneCommentsToMutation['target'],
29
+ destination: CloneCommentsToMutation['destination'],
30
+ ): CloneCommentsToMutation {
31
+ return {
32
+ type: 'cloneCommentsTo',
33
+ target,
34
+ destination,
35
+ };
36
+ }
37
+
38
+ export function performCloneCommentsToMutation(
39
+ mutationContext: MutationContext,
40
+ mutation: CloneCommentsToMutation,
41
+ ): null {
42
+ const newComments = [];
43
+ for (const originalComment of getCommentsForNode(mutation.target)) {
44
+ const comment = cloneCommentWithMarkers(originalComment);
45
+ mutationContext.appendCommentToSource(comment);
46
+ newComments.push(comment);
47
+ }
48
+ addCommentsToNode(mutation.destination, newComments);
49
+
50
+ return null;
51
+ }
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+
3
+ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.createInsertStatementMutation = createInsertStatementMutation;
9
+ exports.performInsertStatementMutation = performInsertStatementMutation;
10
+
11
+ var _arrayUtils = require("./utils/arrayUtils");
12
+
13
+ var _getStatementParent = require("./utils/getStatementParent");
14
+
15
+ var _isValidModuleDeclarationParent = require("./utils/isValidModuleDeclarationParent");
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 _getRequireWildcardCache(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
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
26
+
27
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
28
+
29
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
30
+
31
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
32
+
33
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
34
+
35
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
36
+
37
+ function createInsertStatementMutation(side, target, nodesToInsert) {
38
+ if (nodesToInsert.length === 0) {
39
+ return null;
40
+ }
41
+
42
+ return {
43
+ type: 'insertStatement',
44
+ side: side,
45
+ target: target,
46
+ nodesToInsert: nodesToInsert
47
+ };
48
+ }
49
+
50
+ function performInsertStatementMutation(mutationContext, mutation) {
51
+ var insertionParent = (0, _getStatementParent.getStatementParent)(mutation.target); // enforce that if we are inserting module declarations - they are being inserted in a valid location
52
+
53
+ if (!(0, _isValidModuleDeclarationParent.isValidModuleDeclarationParent)(insertionParent.parent, mutation.nodesToInsert)) {
54
+ throw new _Errors.InvalidInsertionError("import/export cannot be inserted into a ".concat(insertionParent.parent.type, "."));
55
+ }
56
+
57
+ mutationContext.markMutation(insertionParent.parent, insertionParent.key);
58
+
59
+ if (insertionParent.type === 'array') {
60
+ var _parent = insertionParent.parent;
61
+
62
+ switch (mutation.side) {
63
+ case 'before':
64
+ {
65
+ _parent[insertionParent.key] = (0, _arrayUtils.insertInArray)(_parent[insertionParent.key], insertionParent.targetIndex - 1, mutation.nodesToInsert);
66
+ break;
67
+ }
68
+
69
+ case 'after':
70
+ {
71
+ _parent[insertionParent.key] = (0, _arrayUtils.insertInArray)(_parent[insertionParent.key], insertionParent.targetIndex + 1, mutation.nodesToInsert);
72
+ break;
73
+ }
74
+ }
75
+
76
+ return insertionParent.parent;
77
+ }
78
+
79
+ var statementsToInsert = // $FlowExpectedError[incompatible-cast] -- this is enforced by isValidModuleDeclarationParent above
80
+ mutation.nodesToInsert;
81
+ var parent = insertionParent.parent,
82
+ key = insertionParent.key; // $FlowExpectedError[prop-missing]
83
+
84
+ var statementToWrap = parent[key]; // we need to wrap this key in a BlockStatement so we can insert the new statement
85
+
86
+ var blockStatement = t.BlockStatement({
87
+ body: mutation.side === 'before' ? [].concat(_toConsumableArray(statementsToInsert), [statementToWrap]) : [statementToWrap].concat(_toConsumableArray(statementsToInsert)),
88
+ parent: insertionParent.parent
89
+ });
90
+ insertionParent.parent[insertionParent.key] = blockStatement;
91
+ return insertionParent.parent;
92
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its 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
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ import type {ESNode, ModuleDeclaration, Statement} from 'hermes-estree';
12
+ import type {MutationContext} from '../MutationContext';
13
+ import type {DetachedNode} from '../../detachedNode';
14
+
15
+ import {insertInArray} from './utils/arrayUtils';
16
+ import {getStatementParent} from './utils/getStatementParent';
17
+ import {isValidModuleDeclarationParent} from './utils/isValidModuleDeclarationParent';
18
+ import {InvalidInsertionError} from '../Errors';
19
+ import * as t from '../../generated/node-types';
20
+
21
+ export type InsertStatementMutation = $ReadOnly<{
22
+ type: 'insertStatement',
23
+ side: 'before' | 'after',
24
+ target: ModuleDeclaration | Statement,
25
+ nodesToInsert: $ReadOnlyArray<DetachedNode<Statement | ModuleDeclaration>>,
26
+ }>;
27
+
28
+ export function createInsertStatementMutation(
29
+ side: InsertStatementMutation['side'],
30
+ target: InsertStatementMutation['target'],
31
+ nodesToInsert: InsertStatementMutation['nodesToInsert'],
32
+ ): ?InsertStatementMutation {
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
+ export function performInsertStatementMutation(
46
+ mutationContext: MutationContext,
47
+ mutation: InsertStatementMutation,
48
+ ): ESNode {
49
+ const insertionParent = getStatementParent(mutation.target);
50
+
51
+ // enforce that if we are inserting module declarations - they are being inserted in a valid location
52
+ if (
53
+ !isValidModuleDeclarationParent(
54
+ insertionParent.parent,
55
+ mutation.nodesToInsert,
56
+ )
57
+ ) {
58
+ throw new InvalidInsertionError(
59
+ `import/export cannot be inserted into a ${insertionParent.parent.type}.`,
60
+ );
61
+ }
62
+
63
+ mutationContext.markMutation(insertionParent.parent, insertionParent.key);
64
+
65
+ if (insertionParent.type === 'array') {
66
+ const parent: interface {
67
+ [string]: $ReadOnlyArray<DetachedNode<Statement | ModuleDeclaration>>,
68
+ } = insertionParent.parent;
69
+ switch (mutation.side) {
70
+ case 'before': {
71
+ parent[insertionParent.key] = insertInArray(
72
+ parent[insertionParent.key],
73
+ insertionParent.targetIndex - 1,
74
+ mutation.nodesToInsert,
75
+ );
76
+ break;
77
+ }
78
+
79
+ case 'after': {
80
+ parent[insertionParent.key] = insertInArray(
81
+ parent[insertionParent.key],
82
+ insertionParent.targetIndex + 1,
83
+ mutation.nodesToInsert,
84
+ );
85
+ break;
86
+ }
87
+ }
88
+
89
+ return insertionParent.parent;
90
+ }
91
+
92
+ const statementsToInsert =
93
+ // $FlowExpectedError[incompatible-cast] -- this is enforced by isValidModuleDeclarationParent above
94
+ (mutation.nodesToInsert: $ReadOnlyArray<DetachedNode<Statement>>);
95
+
96
+ const {parent, key} = insertionParent;
97
+
98
+ // $FlowExpectedError[prop-missing]
99
+ const statementToWrap = parent[key];
100
+ // we need to wrap this key in a BlockStatement so we can insert the new statement
101
+ const blockStatement = t.BlockStatement({
102
+ body:
103
+ mutation.side === 'before'
104
+ ? [...statementsToInsert, statementToWrap]
105
+ : [statementToWrap, ...statementsToInsert],
106
+ parent: insertionParent.parent,
107
+ });
108
+
109
+ (insertionParent.parent: interface {[string]: mixed})[insertionParent.key] =
110
+ blockStatement;
111
+
112
+ return insertionParent.parent;
113
+ }