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.
- package/LICENSE +21 -0
- package/README.md +8 -0
- package/dist/detachedNode.js +128 -0
- package/dist/detachedNode.js.flow +113 -0
- package/dist/generated/TransformCloneSignatures.js.flow +19 -0
- package/dist/generated/TransformReplaceSignatures.js.flow +943 -0
- package/dist/generated/node-types.js +2071 -0
- package/dist/generated/node-types.js.flow +3149 -0
- package/dist/generated/special-case-node-types.js +178 -0
- package/dist/generated/special-case-node-types.js.flow +248 -0
- package/dist/getVisitorKeys.js +35 -0
- package/dist/getVisitorKeys.js.flow +31 -0
- package/dist/index.js +41 -0
- package/dist/index.js.flow +15 -0
- package/dist/transform/Errors.js +151 -0
- package/dist/transform/Errors.js.flow +17 -0
- package/dist/transform/MutationContext.js +94 -0
- package/dist/transform/MutationContext.js.flow +80 -0
- package/dist/transform/TransformContext.js +136 -0
- package/dist/transform/TransformContext.js.flow +378 -0
- package/dist/transform/comments/comments.js +140 -0
- package/dist/transform/comments/comments.js.flow +145 -0
- package/dist/transform/comments/prettier/README.md +6 -0
- package/dist/transform/comments/prettier/common/util.js +365 -0
- package/dist/transform/comments/prettier/common/util.js.flow +349 -0
- package/dist/transform/comments/prettier/language-js/comments.js +777 -0
- package/dist/transform/comments/prettier/language-js/comments.js.flow +950 -0
- package/dist/transform/comments/prettier/language-js/loc.js +41 -0
- package/dist/transform/comments/prettier/language-js/loc.js.flow +41 -0
- package/dist/transform/comments/prettier/language-js/printer-estree.js +31 -0
- package/dist/transform/comments/prettier/language-js/printer-estree.js.flow +37 -0
- package/dist/transform/comments/prettier/language-js/utils.js +131 -0
- package/dist/transform/comments/prettier/language-js/utils.js.flow +135 -0
- package/dist/transform/comments/prettier/main/comments.js +513 -0
- package/dist/transform/comments/prettier/main/comments.js.flow +436 -0
- package/dist/transform/comments/prettier/utils/get-last.js +15 -0
- package/dist/transform/comments/prettier/utils/get-last.js.flow +14 -0
- package/dist/transform/getTransformedAST.js +159 -0
- package/dist/transform/getTransformedAST.js.flow +128 -0
- package/dist/transform/mutations/AddLeadingComments.js +47 -0
- package/dist/transform/mutations/AddLeadingComments.js.flow +49 -0
- package/dist/transform/mutations/AddTrailingComments.js +47 -0
- package/dist/transform/mutations/AddTrailingComments.js.flow +49 -0
- package/dist/transform/mutations/CloneCommentsTo.js +46 -0
- package/dist/transform/mutations/CloneCommentsTo.js.flow +51 -0
- package/dist/transform/mutations/InsertStatement.js +92 -0
- package/dist/transform/mutations/InsertStatement.js.flow +113 -0
- package/dist/transform/mutations/RemoveComment.js +96 -0
- package/dist/transform/mutations/RemoveComment.js.flow +80 -0
- package/dist/transform/mutations/RemoveStatement.js +61 -0
- package/dist/transform/mutations/RemoveStatement.js.flow +68 -0
- package/dist/transform/mutations/ReplaceNode.js +96 -0
- package/dist/transform/mutations/ReplaceNode.js.flow +113 -0
- package/dist/transform/mutations/ReplaceStatementWithMany.js +81 -0
- package/dist/transform/mutations/ReplaceStatementWithMany.js.flow +102 -0
- package/dist/transform/mutations/utils/arrayUtils.js +41 -0
- package/dist/transform/mutations/utils/arrayUtils.js.flow +35 -0
- package/dist/transform/mutations/utils/getStatementParent.js +147 -0
- package/dist/transform/mutations/utils/getStatementParent.js.flow +143 -0
- package/dist/transform/mutations/utils/isValidModuleDeclarationParent.js +53 -0
- package/dist/transform/mutations/utils/isValidModuleDeclarationParent.js.flow +50 -0
- package/dist/transform/transform.js +69 -0
- package/dist/transform/transform.js.flow +60 -0
- package/dist/traverse/NodeEventGenerator.js +427 -0
- package/dist/traverse/NodeEventGenerator.js.flow +406 -0
- package/dist/traverse/SafeEmitter.js +70 -0
- package/dist/traverse/SafeEmitter.js.flow +46 -0
- package/dist/traverse/SimpleTraverser.js +149 -0
- package/dist/traverse/SimpleTraverser.js.flow +109 -0
- package/dist/traverse/esquery.js +37 -0
- package/dist/traverse/esquery.js.flow +173 -0
- package/dist/traverse/traverse.js +139 -0
- package/dist/traverse/traverse.js.flow +149 -0
- package/package.json +22 -0
|
@@ -0,0 +1,102 @@
|
|
|
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 {replaceInArray} from './utils/arrayUtils';
|
|
16
|
+
import {getStatementParent} from './utils/getStatementParent';
|
|
17
|
+
import {isValidModuleDeclarationParent} from './utils/isValidModuleDeclarationParent';
|
|
18
|
+
import {moveCommentsToNewNode} from '../comments/comments';
|
|
19
|
+
import {InvalidReplacementError} from '../Errors';
|
|
20
|
+
import * as t from '../../generated/node-types';
|
|
21
|
+
|
|
22
|
+
export type ReplaceStatementWithManyMutation = $ReadOnly<{
|
|
23
|
+
type: 'replaceStatementWithMany',
|
|
24
|
+
target: ModuleDeclaration | Statement,
|
|
25
|
+
nodesToReplaceWith: $ReadOnlyArray<
|
|
26
|
+
DetachedNode<ModuleDeclaration | Statement>,
|
|
27
|
+
>,
|
|
28
|
+
keepComments: boolean,
|
|
29
|
+
}>;
|
|
30
|
+
|
|
31
|
+
export function createReplaceStatementWithManyMutation(
|
|
32
|
+
target: ReplaceStatementWithManyMutation['target'],
|
|
33
|
+
nodesToReplaceWith: ReplaceStatementWithManyMutation['nodesToReplaceWith'],
|
|
34
|
+
options?: $ReadOnly<{keepComments?: boolean}>,
|
|
35
|
+
): ?ReplaceStatementWithManyMutation {
|
|
36
|
+
if (nodesToReplaceWith.length === 0) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
type: 'replaceStatementWithMany',
|
|
42
|
+
target,
|
|
43
|
+
nodesToReplaceWith,
|
|
44
|
+
keepComments: options?.keepComments ?? false,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function performReplaceStatementWithManyMutation(
|
|
49
|
+
mutationContext: MutationContext,
|
|
50
|
+
mutation: ReplaceStatementWithManyMutation,
|
|
51
|
+
): ESNode {
|
|
52
|
+
const replacementParent = getStatementParent(mutation.target);
|
|
53
|
+
|
|
54
|
+
// enforce that if we are replacing with module declarations - they are being inserted in a valid location
|
|
55
|
+
if (
|
|
56
|
+
!isValidModuleDeclarationParent(
|
|
57
|
+
replacementParent.parent,
|
|
58
|
+
mutation.nodesToReplaceWith,
|
|
59
|
+
)
|
|
60
|
+
) {
|
|
61
|
+
throw new InvalidReplacementError(
|
|
62
|
+
`import/export cannot be replaced into a ${replacementParent.parent.type}.`,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
mutationContext.markDeletion(mutation.target);
|
|
67
|
+
mutationContext.markMutation(replacementParent.parent, replacementParent.key);
|
|
68
|
+
|
|
69
|
+
if (mutation.keepComments) {
|
|
70
|
+
// attach comments to the very first replacement node
|
|
71
|
+
moveCommentsToNewNode(mutation.target, mutation.nodesToReplaceWith[0]);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (replacementParent.type === 'array') {
|
|
75
|
+
const parent: interface {
|
|
76
|
+
[string]: $ReadOnlyArray<DetachedNode<Statement | ModuleDeclaration>>,
|
|
77
|
+
} = replacementParent.parent;
|
|
78
|
+
parent[replacementParent.key] = replaceInArray(
|
|
79
|
+
parent[replacementParent.key],
|
|
80
|
+
replacementParent.targetIndex,
|
|
81
|
+
mutation.nodesToReplaceWith,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
return replacementParent.parent;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const statementsToReplaceWith =
|
|
88
|
+
// $FlowExpectedError[incompatible-cast] -- this is enforced by isValidModuleDeclarationParent above
|
|
89
|
+
(mutation.nodesToReplaceWith: $ReadOnlyArray<DetachedNode<Statement>>);
|
|
90
|
+
|
|
91
|
+
// we need to wrap the nodes in a BlockStatement as before there was only 1 node
|
|
92
|
+
const blockStatement = t.BlockStatement({
|
|
93
|
+
body: statementsToReplaceWith,
|
|
94
|
+
parent: replacementParent.parent,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
(replacementParent.parent: interface {[string]: mixed})[
|
|
98
|
+
replacementParent.key
|
|
99
|
+
] = blockStatement;
|
|
100
|
+
|
|
101
|
+
return replacementParent.parent;
|
|
102
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.insertInArray = insertInArray;
|
|
7
|
+
exports.removeFromArray = removeFromArray;
|
|
8
|
+
exports.replaceInArray = replaceInArray;
|
|
9
|
+
|
|
10
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
11
|
+
|
|
12
|
+
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."); }
|
|
13
|
+
|
|
14
|
+
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); }
|
|
15
|
+
|
|
16
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
17
|
+
|
|
18
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
19
|
+
|
|
20
|
+
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; }
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
24
|
+
*
|
|
25
|
+
* This source code is licensed under the MIT license found in the
|
|
26
|
+
* LICENSE file in the root directory of this source tree.
|
|
27
|
+
*
|
|
28
|
+
*
|
|
29
|
+
* @format
|
|
30
|
+
*/
|
|
31
|
+
function insertInArray(array, index, elements) {
|
|
32
|
+
return array.slice(0, index).concat(elements).concat(array.slice(index));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function removeFromArray(array, index) {
|
|
36
|
+
return [].concat(_toConsumableArray(array.slice(0, index)), _toConsumableArray(array.slice(index + 1)));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function replaceInArray(array, index, elements) {
|
|
40
|
+
return array.slice(0, index).concat(elements).concat(array.slice(index + 1));
|
|
41
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
export function insertInArray<T>(
|
|
12
|
+
array: $ReadOnlyArray<T>,
|
|
13
|
+
index: number,
|
|
14
|
+
elements: $ReadOnlyArray<T>,
|
|
15
|
+
): Array<T> {
|
|
16
|
+
return array.slice(0, index).concat(elements).concat(array.slice(index));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function removeFromArray<T>(
|
|
20
|
+
array: $ReadOnlyArray<T>,
|
|
21
|
+
index: number,
|
|
22
|
+
): Array<T> {
|
|
23
|
+
return [...array.slice(0, index), ...array.slice(index + 1)];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function replaceInArray<T>(
|
|
27
|
+
array: $ReadOnlyArray<T>,
|
|
28
|
+
index: number,
|
|
29
|
+
elements: $ReadOnlyArray<T>,
|
|
30
|
+
): Array<T> {
|
|
31
|
+
return array
|
|
32
|
+
.slice(0, index)
|
|
33
|
+
.concat(elements)
|
|
34
|
+
.concat(array.slice(index + 1));
|
|
35
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
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) Facebook, Inc. and its 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) {
|
|
21
|
+
for (var _len = arguments.length, invalidKeys = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
22
|
+
invalidKeys[_key - 1] = arguments[_key];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
for (var _i = 0, _invalidKeys = invalidKeys; _i < _invalidKeys.length; _i++) {
|
|
26
|
+
var key = _invalidKeys[_i];
|
|
27
|
+
// $FlowExpectedError[prop-missing]
|
|
28
|
+
var value = parentWithType[key];
|
|
29
|
+
|
|
30
|
+
if (value === target || Array.isArray(value) && value.includes(target)) {
|
|
31
|
+
throw new _Errors.InvalidStatementError("Attempted to insert a statement into `".concat(parentWithType.type, ".").concat(key, "`."));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function getAssertedIndex(key, arr) {
|
|
37
|
+
var idx = arr.indexOf(target);
|
|
38
|
+
|
|
39
|
+
if (idx == null) {
|
|
40
|
+
throw new _Errors.InvalidStatementError("Could not find target in array of `".concat(parent.type, ".").concat(key, "`."));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return idx;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
var parent = target.parent;
|
|
47
|
+
|
|
48
|
+
var result = function () {
|
|
49
|
+
switch (parent.type) {
|
|
50
|
+
case 'IfStatement':
|
|
51
|
+
{
|
|
52
|
+
assertValidStatementLocation(parent, 'test');
|
|
53
|
+
var key = parent.consequent === target ? 'consequent' : 'alternate';
|
|
54
|
+
return {
|
|
55
|
+
type: 'single',
|
|
56
|
+
parent: parent,
|
|
57
|
+
key: key
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
case 'LabeledStatement':
|
|
62
|
+
{
|
|
63
|
+
assertValidStatementLocation(parent, 'label');
|
|
64
|
+
return {
|
|
65
|
+
type: 'single',
|
|
66
|
+
parent: parent,
|
|
67
|
+
key: 'body'
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
case 'WithStatement':
|
|
72
|
+
{
|
|
73
|
+
assertValidStatementLocation(parent, 'object');
|
|
74
|
+
return {
|
|
75
|
+
type: 'single',
|
|
76
|
+
parent: parent,
|
|
77
|
+
key: 'body'
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
case 'DoWhileStatement':
|
|
82
|
+
case 'WhileStatement':
|
|
83
|
+
{
|
|
84
|
+
assertValidStatementLocation(parent, 'test');
|
|
85
|
+
return {
|
|
86
|
+
type: 'single',
|
|
87
|
+
parent: parent,
|
|
88
|
+
key: 'body'
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
case 'ForStatement':
|
|
93
|
+
{
|
|
94
|
+
assertValidStatementLocation(parent, 'init', 'test', 'update');
|
|
95
|
+
return {
|
|
96
|
+
type: 'single',
|
|
97
|
+
parent: parent,
|
|
98
|
+
key: 'body'
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
case 'ForInStatement':
|
|
103
|
+
case 'ForOfStatement':
|
|
104
|
+
{
|
|
105
|
+
assertValidStatementLocation( // $FlowExpectedError[prop-missing] - flow does not track properties from parent interface
|
|
106
|
+
parent, 'left', 'right');
|
|
107
|
+
return {
|
|
108
|
+
type: 'single',
|
|
109
|
+
parent: parent,
|
|
110
|
+
key: 'body'
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
case 'SwitchCase':
|
|
115
|
+
{
|
|
116
|
+
assertValidStatementLocation(parent, 'test');
|
|
117
|
+
return {
|
|
118
|
+
type: 'array',
|
|
119
|
+
parent: parent,
|
|
120
|
+
key: 'consequent',
|
|
121
|
+
targetIndex: getAssertedIndex('consequent', parent.consequent)
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
case 'BlockStatement':
|
|
126
|
+
case 'Program':
|
|
127
|
+
{
|
|
128
|
+
return {
|
|
129
|
+
type: 'array',
|
|
130
|
+
parent: parent,
|
|
131
|
+
key: 'body',
|
|
132
|
+
targetIndex: getAssertedIndex('body', parent.body)
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
throw new _Errors.InvalidStatementError("Expected to find a valid statement parent, but found a parent of type \"".concat(parent.type, "\"."));
|
|
138
|
+
}();
|
|
139
|
+
|
|
140
|
+
if ( // array insertions are already validated by the getAssertedIndex function
|
|
141
|
+
result.targetIndex == null && // $FlowExpectedError[prop-missing]
|
|
142
|
+
result.parent[result.key] !== target) {
|
|
143
|
+
throw new _Errors.InvalidStatementError("Expected to find the target \"".concat(target.type, "\" on the \"").concat(result.parent.type, ".").concat(result.key, "\", but found a different node. ") + 'This likely means that you attempted to mutate around the target after it was deleted/replaced.');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
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 {
|
|
12
|
+
ModuleDeclaration,
|
|
13
|
+
Statement,
|
|
14
|
+
StatementParentArray,
|
|
15
|
+
StatementParentSingle,
|
|
16
|
+
} from 'hermes-estree';
|
|
17
|
+
|
|
18
|
+
import {InvalidStatementError} from '../../Errors';
|
|
19
|
+
|
|
20
|
+
export function getStatementParent(
|
|
21
|
+
target: ModuleDeclaration | Statement,
|
|
22
|
+
): $ReadOnly<
|
|
23
|
+
| {
|
|
24
|
+
type: 'single',
|
|
25
|
+
parent: StatementParentSingle,
|
|
26
|
+
key: string,
|
|
27
|
+
}
|
|
28
|
+
| {
|
|
29
|
+
type: 'array',
|
|
30
|
+
parent: StatementParentArray,
|
|
31
|
+
key: string,
|
|
32
|
+
targetIndex: number,
|
|
33
|
+
},
|
|
34
|
+
> {
|
|
35
|
+
function assertValidStatementLocation<T: $ReadOnly<interface {type: string}>>(
|
|
36
|
+
parentWithType: T,
|
|
37
|
+
...invalidKeys: $ReadOnlyArray<$Keys<T>>
|
|
38
|
+
): void {
|
|
39
|
+
for (const key of invalidKeys) {
|
|
40
|
+
// $FlowExpectedError[prop-missing]
|
|
41
|
+
const value = parentWithType[key];
|
|
42
|
+
|
|
43
|
+
if (
|
|
44
|
+
value === target ||
|
|
45
|
+
(Array.isArray(value) && value.includes(target))
|
|
46
|
+
) {
|
|
47
|
+
throw new InvalidStatementError(
|
|
48
|
+
`Attempted to insert a statement into \`${parentWithType.type}.${key}\`.`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function getAssertedIndex(key: string, arr: $ReadOnlyArray<mixed>): number {
|
|
54
|
+
const idx = arr.indexOf(target);
|
|
55
|
+
if (idx == null) {
|
|
56
|
+
throw new InvalidStatementError(
|
|
57
|
+
`Could not find target in array of \`${parent.type}.${key}\`.`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return idx;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const parent = target.parent;
|
|
64
|
+
const result = (() => {
|
|
65
|
+
switch (parent.type) {
|
|
66
|
+
case 'IfStatement': {
|
|
67
|
+
assertValidStatementLocation(parent, 'test');
|
|
68
|
+
const key = parent.consequent === target ? 'consequent' : 'alternate';
|
|
69
|
+
return {type: 'single', parent, key};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
case 'LabeledStatement': {
|
|
73
|
+
assertValidStatementLocation(parent, 'label');
|
|
74
|
+
return {type: 'single', parent, key: 'body'};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
case 'WithStatement': {
|
|
78
|
+
assertValidStatementLocation(parent, 'object');
|
|
79
|
+
return {type: 'single', parent, key: 'body'};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
case 'DoWhileStatement':
|
|
83
|
+
case 'WhileStatement': {
|
|
84
|
+
assertValidStatementLocation(parent, 'test');
|
|
85
|
+
return {type: 'single', parent, key: 'body'};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
case 'ForStatement': {
|
|
89
|
+
assertValidStatementLocation(parent, 'init', 'test', 'update');
|
|
90
|
+
return {type: 'single', parent, key: 'body'};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
case 'ForInStatement':
|
|
94
|
+
case 'ForOfStatement': {
|
|
95
|
+
assertValidStatementLocation(
|
|
96
|
+
// $FlowExpectedError[prop-missing] - flow does not track properties from parent interface
|
|
97
|
+
parent,
|
|
98
|
+
'left',
|
|
99
|
+
'right',
|
|
100
|
+
);
|
|
101
|
+
return {type: 'single', parent, key: 'body'};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
case 'SwitchCase': {
|
|
105
|
+
assertValidStatementLocation(parent, 'test');
|
|
106
|
+
return {
|
|
107
|
+
type: 'array',
|
|
108
|
+
parent,
|
|
109
|
+
key: 'consequent',
|
|
110
|
+
targetIndex: getAssertedIndex('consequent', parent.consequent),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
case 'BlockStatement':
|
|
115
|
+
case 'Program': {
|
|
116
|
+
return {
|
|
117
|
+
type: 'array',
|
|
118
|
+
parent,
|
|
119
|
+
key: 'body',
|
|
120
|
+
targetIndex: getAssertedIndex('body', parent.body),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
throw new InvalidStatementError(
|
|
126
|
+
`Expected to find a valid statement parent, but found a parent of type "${parent.type}".`,
|
|
127
|
+
);
|
|
128
|
+
})();
|
|
129
|
+
|
|
130
|
+
if (
|
|
131
|
+
// array insertions are already validated by the getAssertedIndex function
|
|
132
|
+
result.targetIndex == null &&
|
|
133
|
+
// $FlowExpectedError[prop-missing]
|
|
134
|
+
result.parent[result.key] !== target
|
|
135
|
+
) {
|
|
136
|
+
throw new InvalidStatementError(
|
|
137
|
+
`Expected to find the target "${target.type}" on the "${result.parent.type}.${result.key}", but found a different node. ` +
|
|
138
|
+
'This likely means that you attempted to mutate around the target after it was deleted/replaced.',
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.isValidModuleDeclarationParent = isValidModuleDeclarationParent;
|
|
7
|
+
|
|
8
|
+
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; } } }; }
|
|
9
|
+
|
|
10
|
+
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); }
|
|
11
|
+
|
|
12
|
+
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; }
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
16
|
+
*
|
|
17
|
+
* This source code is licensed under the MIT license found in the
|
|
18
|
+
* LICENSE file in the root directory of this source tree.
|
|
19
|
+
*
|
|
20
|
+
*
|
|
21
|
+
* @format
|
|
22
|
+
*/
|
|
23
|
+
function isModuleDeclaration(node) {
|
|
24
|
+
return node.type === 'ImportDeclaration' || node.type === 'ExportNamedDeclaration' || node.type === 'ExportDefaultDeclaration' || node.type === 'ExportAllDeclaration';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isValidModuleDeclarationParent(target, nodesToInsertOrReplace) {
|
|
28
|
+
if (target.type === 'Program' || target.type === 'BlockStatement' && target.parent.type === 'DeclareModule') {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
var _iterator = _createForOfIteratorHelper(nodesToInsertOrReplace),
|
|
33
|
+
_step;
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
37
|
+
var node = _step.value;
|
|
38
|
+
|
|
39
|
+
if (!isModuleDeclaration( // $FlowExpectedError[incompatible-cast]
|
|
40
|
+
node)) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
} catch (err) {
|
|
47
|
+
_iterator.e(err);
|
|
48
|
+
} finally {
|
|
49
|
+
_iterator.f();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
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 {DetachedNode} from '../../../detachedNode';
|
|
13
|
+
|
|
14
|
+
function isModuleDeclaration(node: ESNode): boolean %checks {
|
|
15
|
+
return (
|
|
16
|
+
node.type === 'ImportDeclaration' ||
|
|
17
|
+
node.type === 'ExportNamedDeclaration' ||
|
|
18
|
+
node.type === 'ExportDefaultDeclaration' ||
|
|
19
|
+
node.type === 'ExportAllDeclaration'
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function isValidModuleDeclarationParent(
|
|
24
|
+
target: ESNode,
|
|
25
|
+
nodesToInsertOrReplace: $ReadOnlyArray<
|
|
26
|
+
DetachedNode<ModuleDeclaration | Statement>,
|
|
27
|
+
>,
|
|
28
|
+
): boolean {
|
|
29
|
+
if (
|
|
30
|
+
target.type === 'Program' ||
|
|
31
|
+
(target.type === 'BlockStatement' && target.parent.type === 'DeclareModule')
|
|
32
|
+
) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
for (const node of nodesToInsertOrReplace) {
|
|
37
|
+
if (
|
|
38
|
+
!isModuleDeclaration(
|
|
39
|
+
// $FlowExpectedError[incompatible-cast]
|
|
40
|
+
(node: ESNode),
|
|
41
|
+
)
|
|
42
|
+
) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
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
|
+
*
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
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); }
|
|
13
|
+
|
|
14
|
+
Object.defineProperty(exports, "__esModule", {
|
|
15
|
+
value: true
|
|
16
|
+
});
|
|
17
|
+
exports.transform = transform;
|
|
18
|
+
|
|
19
|
+
var prettier = _interopRequireWildcard(require("prettier"));
|
|
20
|
+
|
|
21
|
+
var _getTransformedAST2 = require("./getTransformedAST");
|
|
22
|
+
|
|
23
|
+
var _SimpleTraverser = require("../traverse/SimpleTraverser");
|
|
24
|
+
|
|
25
|
+
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); }
|
|
26
|
+
|
|
27
|
+
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; }
|
|
28
|
+
|
|
29
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
|
|
30
|
+
|
|
31
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
32
|
+
|
|
33
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
34
|
+
|
|
35
|
+
function transform(originalCode, visitors) {
|
|
36
|
+
var prettierOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
37
|
+
|
|
38
|
+
var _getTransformedAST = (0, _getTransformedAST2.getTransformedAST)(originalCode, visitors),
|
|
39
|
+
ast = _getTransformedAST.ast,
|
|
40
|
+
astWasMutated = _getTransformedAST.astWasMutated,
|
|
41
|
+
mutatedCode = _getTransformedAST.mutatedCode;
|
|
42
|
+
|
|
43
|
+
if (!astWasMutated) {
|
|
44
|
+
return originalCode;
|
|
45
|
+
} // prettier fully expects the parent pointers are NOT set and
|
|
46
|
+
// certain cases can crash due to prettier infinite-looping
|
|
47
|
+
// whilst naively traversing the parent property
|
|
48
|
+
// https://github.com/prettier/prettier/issues/11793
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
_SimpleTraverser.SimpleTraverser.traverse(ast, {
|
|
52
|
+
enter: function enter(node) {
|
|
53
|
+
// $FlowExpectedError[cannot-write]
|
|
54
|
+
delete node.parent;
|
|
55
|
+
},
|
|
56
|
+
leave: function leave() {}
|
|
57
|
+
}); // we need to delete the comments prop or else prettier will do
|
|
58
|
+
// its own attachment pass after the mutation and duplicate the
|
|
59
|
+
// comments on each node, borking the output
|
|
60
|
+
// $FlowExpectedError[cannot-write]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
delete ast.comments;
|
|
64
|
+
return prettier.format(mutatedCode, _objectSpread(_objectSpread({}, prettierOptions), {}, {
|
|
65
|
+
parser: function parser() {
|
|
66
|
+
return ast;
|
|
67
|
+
}
|
|
68
|
+
}));
|
|
69
|
+
}
|