hermes-transform 0.9.0 → 0.10.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/dist/detachedNode.js +9 -27
- package/dist/detachedNode.js.flow +18 -31
- package/dist/generated/TransformCloneSignatures.js.flow +18 -0
- package/dist/generated/TransformModifySignatures.js.flow +14 -0
- package/dist/generated/TransformReplaceSignatures.js.flow +15 -1
- package/dist/generated/node-types.js +253 -59
- package/dist/generated/node-types.js.flow +257 -102
- package/dist/generated/special-case-node-types/Comment.js +36 -0
- package/dist/generated/special-case-node-types/Comment.js.flow +36 -0
- package/dist/generated/special-case-node-types/DeclareExportDeclaration.js +55 -0
- package/dist/generated/special-case-node-types/DeclareExportDeclaration.js.flow +97 -0
- package/dist/generated/special-case-node-types/ExportNamedDeclaration.js +42 -0
- package/dist/generated/special-case-node-types/ExportNamedDeclaration.js.flow +75 -0
- package/dist/generated/special-case-node-types/Literal.js +97 -0
- package/dist/generated/special-case-node-types/Literal.js.flow +139 -0
- package/dist/generated/special-case-node-types/ObjectTypeProperty.js +73 -0
- package/dist/generated/special-case-node-types/ObjectTypeProperty.js.flow +107 -0
- package/dist/generated/special-case-node-types/Property.js +136 -0
- package/dist/generated/special-case-node-types/Property.js.flow +237 -0
- package/dist/generated/special-case-node-types/misc.js +119 -0
- package/dist/generated/special-case-node-types/misc.js.flow +205 -0
- package/dist/generated/special-case-node-types.js +42 -174
- package/dist/generated/special-case-node-types.js.flow +7 -274
- package/dist/index.js +19 -3
- package/dist/index.js.flow +6 -2
- package/dist/transform/TransformContext.js +1 -1
- package/dist/transform/TransformContext.js.flow +2 -2
- package/dist/transform/comments/comments.js +11 -0
- package/dist/transform/comments/comments.js.flow +16 -1
- package/dist/transform/comments/prettier/main/comments.js +1 -1
- package/dist/transform/comments/prettier/main/comments.js.flow +2 -1
- package/dist/transform/mutations/InsertStatement.js +3 -3
- package/dist/transform/mutations/InsertStatement.js.flow +3 -3
- package/dist/transform/mutations/RemoveComment.js +3 -3
- package/dist/transform/mutations/RemoveComment.js.flow +3 -5
- package/dist/transform/mutations/RemoveNode.js +2 -2
- package/dist/transform/mutations/RemoveNode.js.flow +2 -2
- package/dist/transform/mutations/RemoveStatement.js +2 -2
- package/dist/transform/mutations/RemoveStatement.js.flow +2 -2
- package/dist/transform/mutations/ReplaceNode.js +4 -6
- package/dist/transform/mutations/ReplaceNode.js.flow +2 -3
- package/dist/transform/mutations/ReplaceStatementWithMany.js +2 -2
- package/dist/transform/mutations/ReplaceStatementWithMany.js.flow +2 -2
- package/dist/transform/mutations/utils/getStatementParent.js +3 -2
- package/dist/transform/mutations/utils/getStatementParent.js.flow +5 -2
- package/dist/transform/parse.js +55 -0
- package/dist/transform/parse.js.flow +55 -0
- package/dist/transform/print.js +160 -0
- package/dist/transform/print.js.flow +176 -0
- package/dist/transform/transform.js +6 -67
- package/dist/transform/transform.js.flow +6 -69
- package/dist/transform/{getTransformedAST.js → transformAST.js} +7 -31
- package/dist/transform/{getTransformedAST.js.flow → transformAST.js.flow} +7 -32
- package/dist/traverse/traverse.js +36 -35
- package/dist/traverse/traverse.js.flow +45 -26
- package/package.json +5 -4
- package/dist/getVisitorKeys.js +0 -33
- package/dist/getVisitorKeys.js.flow +0 -31
- package/dist/transform/mutations/utils/arrayUtils.js +0 -43
- package/dist/transform/mutations/utils/arrayUtils.js.flow +0 -50
- package/dist/traverse/SimpleTraverser.js +0 -118
- package/dist/traverse/SimpleTraverser.js.flow +0 -112
|
@@ -10,13 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
'use strict';
|
|
12
12
|
|
|
13
|
-
import type {ESNode} from 'hermes-estree';
|
|
14
13
|
import type {Visitor} from '../traverse/traverse';
|
|
15
14
|
import type {TransformContextAdditions} from './TransformContext';
|
|
16
15
|
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
16
|
+
import {transformAST} from './transformAST';
|
|
17
|
+
import {parse} from './parse';
|
|
18
|
+
import {print} from './print';
|
|
20
19
|
|
|
21
20
|
export type TransformVisitor = Visitor<TransformContextAdditions>;
|
|
22
21
|
|
|
@@ -25,74 +24,12 @@ export function transform(
|
|
|
25
24
|
visitors: TransformVisitor,
|
|
26
25
|
prettierOptions: {...} = {},
|
|
27
26
|
): string {
|
|
28
|
-
const
|
|
29
|
-
originalCode,
|
|
30
|
-
visitors,
|
|
31
|
-
);
|
|
27
|
+
const parseResult = parse(originalCode);
|
|
32
28
|
|
|
29
|
+
const {ast, astWasMutated, mutatedCode} = transformAST(parseResult, visitors);
|
|
33
30
|
if (!astWasMutated) {
|
|
34
31
|
return originalCode;
|
|
35
32
|
}
|
|
36
33
|
|
|
37
|
-
|
|
38
|
-
enter(node) {
|
|
39
|
-
// prettier fully expects the parent pointers are NOT set and
|
|
40
|
-
// certain cases can crash due to prettier infinite-looping
|
|
41
|
-
// whilst naively traversing the parent property
|
|
42
|
-
// https://github.com/prettier/prettier/issues/11793
|
|
43
|
-
// $FlowExpectedError[cannot-write]
|
|
44
|
-
delete node.parent;
|
|
45
|
-
|
|
46
|
-
// prettier currently relies on the AST being in the old-school, deprecated AST format for optional chaining
|
|
47
|
-
// so we have to apply their transform to our AST so it can actually format it.
|
|
48
|
-
if (node.type === 'ChainExpression') {
|
|
49
|
-
const newNode = transformChainExpression(node.expression);
|
|
50
|
-
// $FlowExpectedError[cannot-write]
|
|
51
|
-
delete node.expression;
|
|
52
|
-
// $FlowExpectedError[prop-missing]
|
|
53
|
-
// $FlowExpectedError[cannot-write]
|
|
54
|
-
Object.assign(node, newNode);
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
leave() {},
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// we need to delete the comments prop or else prettier will do
|
|
61
|
-
// its own attachment pass after the mutation and duplicate the
|
|
62
|
-
// comments on each node, borking the output
|
|
63
|
-
// $FlowExpectedError[cannot-write]
|
|
64
|
-
delete ast.comments;
|
|
65
|
-
|
|
66
|
-
return prettier.format(
|
|
67
|
-
mutatedCode,
|
|
68
|
-
// $FlowExpectedError[incompatible-exact] - we don't want to create a dependency on the prettier types
|
|
69
|
-
{
|
|
70
|
-
...prettierOptions,
|
|
71
|
-
parser() {
|
|
72
|
-
return ast;
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// https://github.com/prettier/prettier/blob/d962466a828f8ef51435e3e8840178d90b7ec6cd/src/language-js/parse/postprocess/index.js#L161-L182
|
|
79
|
-
function transformChainExpression(node: ESNode) {
|
|
80
|
-
switch (node.type) {
|
|
81
|
-
case 'CallExpression':
|
|
82
|
-
// $FlowExpectedError[cannot-write]
|
|
83
|
-
node.type = 'OptionalCallExpression';
|
|
84
|
-
// $FlowExpectedError[cannot-write]
|
|
85
|
-
node.callee = transformChainExpression(node.callee);
|
|
86
|
-
break;
|
|
87
|
-
|
|
88
|
-
case 'MemberExpression':
|
|
89
|
-
// $FlowExpectedError[cannot-write]
|
|
90
|
-
node.type = 'OptionalMemberExpression';
|
|
91
|
-
// $FlowExpectedError[cannot-write]
|
|
92
|
-
node.object = transformChainExpression(node.object);
|
|
93
|
-
break;
|
|
94
|
-
// No default
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return node;
|
|
34
|
+
return print(ast, mutatedCode, prettierOptions);
|
|
98
35
|
}
|
|
@@ -12,9 +12,7 @@
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", {
|
|
13
13
|
value: true
|
|
14
14
|
});
|
|
15
|
-
exports.
|
|
16
|
-
|
|
17
|
-
var _hermesEslint = require("hermes-eslint");
|
|
15
|
+
exports.transformAST = transformAST;
|
|
18
16
|
|
|
19
17
|
var _detachedNode = require("../detachedNode");
|
|
20
18
|
|
|
@@ -24,8 +22,6 @@ var _MutationContext = require("./MutationContext");
|
|
|
24
22
|
|
|
25
23
|
var _TransformContext = require("./TransformContext");
|
|
26
24
|
|
|
27
|
-
var _comments = require("./comments/comments");
|
|
28
|
-
|
|
29
25
|
var _AddComments = require("./mutations/AddComments");
|
|
30
26
|
|
|
31
27
|
var _CloneCommentsTo = require("./mutations/CloneCommentsTo");
|
|
@@ -42,17 +38,12 @@ var _ReplaceNode = require("./mutations/ReplaceNode");
|
|
|
42
38
|
|
|
43
39
|
var _ReplaceStatementWithMany = require("./mutations/ReplaceStatementWithMany");
|
|
44
40
|
|
|
45
|
-
function
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}); // attach comments before mutation. this will ensure that as nodes are
|
|
52
|
-
// cloned / moved around - comments remain in the correct place with respect to the node
|
|
53
|
-
|
|
54
|
-
(0, _comments.attachComments)(ast.comments, ast, code); // traverse the AST and colllect the mutations
|
|
55
|
-
|
|
41
|
+
function transformAST({
|
|
42
|
+
ast,
|
|
43
|
+
scopeManager,
|
|
44
|
+
code
|
|
45
|
+
}, visitors) {
|
|
46
|
+
// traverse the AST and colllect the mutations
|
|
56
47
|
const transformContext = (0, _TransformContext.getTransformContext)();
|
|
57
48
|
(0, _traverse.traverseWithContext)(code, ast, scopeManager, () => transformContext, visitors); // apply the mutations to the AST
|
|
58
49
|
|
|
@@ -122,21 +113,6 @@ function getTransformedAST(code, visitors) {
|
|
|
122
113
|
if (mutationRoot) {
|
|
123
114
|
(0, _detachedNode.updateAllParentPointers)(mutationRoot);
|
|
124
115
|
}
|
|
125
|
-
} // if the very first node in the program is replaced, it will take the docblock with it
|
|
126
|
-
// this is bad as it means we'll lose `@format`, ``, licence, etc.
|
|
127
|
-
// so this hack just makes sure that we keep the docblock
|
|
128
|
-
// note that we do this **BEFORE** the comment mutations in case someone intentionally
|
|
129
|
-
// wants to remove the docblock comment for some weird reason
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (ast.docblock != null && ast.body.length > 0) {
|
|
133
|
-
const firstNode = ast.body[0];
|
|
134
|
-
const docblockComment = ast.docblock.comment;
|
|
135
|
-
const leadingComments = (0, _comments.getLeadingCommentsForNode)(firstNode);
|
|
136
|
-
|
|
137
|
-
if (!leadingComments.includes(docblockComment)) {
|
|
138
|
-
(0, _comments.addCommentsToNode)(firstNode, [docblockComment], 'leading');
|
|
139
|
-
}
|
|
140
116
|
} // remove the comments
|
|
141
117
|
// this is done at the end because it requires a complete traversal of the AST
|
|
142
118
|
// so that we can find relevant node's attachment array
|
|
@@ -13,17 +13,12 @@
|
|
|
13
13
|
import type {ESNode, Program} from 'hermes-estree';
|
|
14
14
|
import type {TransformVisitor} from './transform';
|
|
15
15
|
import type {RemoveCommentMutation} from './mutations/RemoveComment';
|
|
16
|
+
import type {ParseResult} from './parse';
|
|
16
17
|
|
|
17
|
-
import {parseForESLint} from 'hermes-eslint';
|
|
18
18
|
import {updateAllParentPointers} from '../detachedNode';
|
|
19
19
|
import {traverseWithContext} from '../traverse/traverse';
|
|
20
20
|
import {MutationContext} from './MutationContext';
|
|
21
21
|
import {getTransformContext} from './TransformContext';
|
|
22
|
-
import {
|
|
23
|
-
addCommentsToNode,
|
|
24
|
-
attachComments,
|
|
25
|
-
getLeadingCommentsForNode,
|
|
26
|
-
} from './comments/comments';
|
|
27
22
|
import {performAddCommentsMutation} from './mutations/AddComments';
|
|
28
23
|
import {performCloneCommentsToMutation} from './mutations/CloneCommentsTo';
|
|
29
24
|
import {performInsertStatementMutation} from './mutations/InsertStatement';
|
|
@@ -33,22 +28,16 @@ import {performRemoveStatementMutation} from './mutations/RemoveStatement';
|
|
|
33
28
|
import {performReplaceNodeMutation} from './mutations/ReplaceNode';
|
|
34
29
|
import {performReplaceStatementWithManyMutation} from './mutations/ReplaceStatementWithMany';
|
|
35
30
|
|
|
36
|
-
export
|
|
37
|
-
code: string,
|
|
38
|
-
visitors: TransformVisitor,
|
|
39
|
-
): {
|
|
31
|
+
export type TransformASTResult = {
|
|
40
32
|
ast: Program,
|
|
41
33
|
astWasMutated: boolean,
|
|
42
34
|
mutatedCode: string,
|
|
43
|
-
}
|
|
44
|
-
const {ast, scopeManager} = parseForESLint(code, {
|
|
45
|
-
sourceType: 'module',
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// attach comments before mutation. this will ensure that as nodes are
|
|
49
|
-
// cloned / moved around - comments remain in the correct place with respect to the node
|
|
50
|
-
attachComments(ast.comments, ast, code);
|
|
35
|
+
};
|
|
51
36
|
|
|
37
|
+
export function transformAST(
|
|
38
|
+
{ast, scopeManager, code}: ParseResult,
|
|
39
|
+
visitors: TransformVisitor,
|
|
40
|
+
): TransformASTResult {
|
|
52
41
|
// traverse the AST and colllect the mutations
|
|
53
42
|
const transformContext = getTransformContext();
|
|
54
43
|
traverseWithContext(
|
|
@@ -124,20 +113,6 @@ export function getTransformedAST(
|
|
|
124
113
|
}
|
|
125
114
|
}
|
|
126
115
|
|
|
127
|
-
// if the very first node in the program is replaced, it will take the docblock with it
|
|
128
|
-
// this is bad as it means we'll lose `@format`, `@flow`, licence, etc.
|
|
129
|
-
// so this hack just makes sure that we keep the docblock
|
|
130
|
-
// note that we do this **BEFORE** the comment mutations in case someone intentionally
|
|
131
|
-
// wants to remove the docblock comment for some weird reason
|
|
132
|
-
if (ast.docblock != null && ast.body.length > 0) {
|
|
133
|
-
const firstNode = ast.body[0];
|
|
134
|
-
const docblockComment = ast.docblock.comment;
|
|
135
|
-
const leadingComments = getLeadingCommentsForNode(firstNode);
|
|
136
|
-
if (!leadingComments.includes(docblockComment)) {
|
|
137
|
-
addCommentsToNode(firstNode, [docblockComment], 'leading');
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
116
|
// remove the comments
|
|
142
117
|
// this is done at the end because it requires a complete traversal of the AST
|
|
143
118
|
// so that we can find relevant node's attachment array
|
|
@@ -12,7 +12,7 @@ var _NodeEventGenerator = require("./NodeEventGenerator");
|
|
|
12
12
|
|
|
13
13
|
var _SafeEmitter = require("./SafeEmitter");
|
|
14
14
|
|
|
15
|
-
var
|
|
15
|
+
var _hermesParser = require("hermes-parser");
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -32,27 +32,9 @@ var _SimpleTraverser = require("./SimpleTraverser");
|
|
|
32
32
|
*/
|
|
33
33
|
function traverseWithContext(code, ast, scopeManager, additionalContext, visitor) {
|
|
34
34
|
const emitter = new _SafeEmitter.SafeEmitter();
|
|
35
|
-
|
|
36
|
-
let
|
|
37
|
-
|
|
38
|
-
_SimpleTraverser.SimpleTraverser.traverse(ast, {
|
|
39
|
-
enter(node, parent) {
|
|
40
|
-
// $FlowExpectedError[cannot-write] - hermes doesn't set this
|
|
41
|
-
node.parent = parent;
|
|
42
|
-
nodeQueue.push({
|
|
43
|
-
isEntering: true,
|
|
44
|
-
node
|
|
45
|
-
});
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
leave(node) {
|
|
49
|
-
nodeQueue.push({
|
|
50
|
-
isEntering: false,
|
|
51
|
-
node
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
});
|
|
35
|
+
let currentNode = ast;
|
|
36
|
+
let shouldSkipTraversal = false;
|
|
37
|
+
let shouldStopTraversal = false;
|
|
56
38
|
|
|
57
39
|
const getScope = (givenNode = currentNode) => {
|
|
58
40
|
// On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope.
|
|
@@ -112,7 +94,13 @@ function traverseWithContext(code, ast, scopeManager, additionalContext, visitor
|
|
|
112
94
|
|
|
113
95
|
return null;
|
|
114
96
|
},
|
|
115
|
-
getScope
|
|
97
|
+
getScope,
|
|
98
|
+
stopTraversal: () => {
|
|
99
|
+
shouldStopTraversal = true;
|
|
100
|
+
},
|
|
101
|
+
skipTraversal: () => {
|
|
102
|
+
shouldSkipTraversal = true;
|
|
103
|
+
}
|
|
116
104
|
});
|
|
117
105
|
const traversalContext = Object.freeze({ ...traversalContextBase,
|
|
118
106
|
...additionalContext(traversalContextBase)
|
|
@@ -130,19 +118,32 @@ function traverseWithContext(code, ast, scopeManager, additionalContext, visitor
|
|
|
130
118
|
}
|
|
131
119
|
});
|
|
132
120
|
const eventGenerator = new _NodeEventGenerator.NodeEventGenerator(emitter);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
121
|
+
|
|
122
|
+
function checkTraversalFlags() {
|
|
123
|
+
if (shouldStopTraversal) {
|
|
124
|
+
// No need to reset the flag since we won't enter any more nodes.
|
|
125
|
+
throw _hermesParser.SimpleTraverser.Break;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (shouldSkipTraversal) {
|
|
129
|
+
shouldSkipTraversal = false;
|
|
130
|
+
throw _hermesParser.SimpleTraverser.Skip;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
_hermesParser.SimpleTraverser.traverse(ast, {
|
|
135
|
+
enter(node) {
|
|
136
|
+
currentNode = node;
|
|
137
|
+
eventGenerator.enterNode(node);
|
|
138
|
+
checkTraversalFlags();
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
leave(node) {
|
|
142
|
+
currentNode = node;
|
|
143
|
+
eventGenerator.leaveNode(node);
|
|
144
|
+
checkTraversalFlags();
|
|
145
145
|
}
|
|
146
|
+
|
|
146
147
|
});
|
|
147
148
|
}
|
|
148
149
|
|
|
@@ -15,7 +15,7 @@ import type {EmitterListener} from './SafeEmitter';
|
|
|
15
15
|
import {codeFrameColumns} from '@babel/code-frame';
|
|
16
16
|
import {NodeEventGenerator} from './NodeEventGenerator';
|
|
17
17
|
import {SafeEmitter} from './SafeEmitter';
|
|
18
|
-
import {SimpleTraverser} from '
|
|
18
|
+
import {SimpleTraverser} from 'hermes-parser';
|
|
19
19
|
|
|
20
20
|
export type TraversalContextBase = $ReadOnly<{
|
|
21
21
|
/**
|
|
@@ -55,6 +55,17 @@ export type TraversalContextBase = $ReadOnly<{
|
|
|
55
55
|
* (where 56:44 represents L56, Col44)
|
|
56
56
|
*/
|
|
57
57
|
buildSimpleCodeFrame: (node: ESNode, message: string) => string,
|
|
58
|
+
/**
|
|
59
|
+
* Can be called at any point during the traversal to immediately stop traversal
|
|
60
|
+
* entirely.
|
|
61
|
+
*/
|
|
62
|
+
stopTraversal: () => void,
|
|
63
|
+
/**
|
|
64
|
+
* Can be called within the traversal "enter" function to prevent the traverser
|
|
65
|
+
* from traversing the node any further, essentially culling the remainder of the
|
|
66
|
+
* AST branch from traversal.
|
|
67
|
+
*/
|
|
68
|
+
skipTraversal: () => void,
|
|
58
69
|
}>;
|
|
59
70
|
export type TraversalContext<T> = $ReadOnly<{
|
|
60
71
|
...TraversalContextBase,
|
|
@@ -77,21 +88,10 @@ export function traverseWithContext<T = TraversalContextBase>(
|
|
|
77
88
|
visitor: Visitor<T>,
|
|
78
89
|
): void {
|
|
79
90
|
const emitter = new SafeEmitter();
|
|
80
|
-
const nodeQueue: Array<{isEntering: boolean, node: ESNode}> = [];
|
|
81
91
|
|
|
82
92
|
let currentNode: ESNode = ast;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
SimpleTraverser.traverse(ast, {
|
|
86
|
-
enter(node, parent) {
|
|
87
|
-
// $FlowExpectedError[cannot-write] - hermes doesn't set this
|
|
88
|
-
node.parent = parent;
|
|
89
|
-
nodeQueue.push({isEntering: true, node});
|
|
90
|
-
},
|
|
91
|
-
leave(node) {
|
|
92
|
-
nodeQueue.push({isEntering: false, node});
|
|
93
|
-
},
|
|
94
|
-
});
|
|
93
|
+
let shouldSkipTraversal = false;
|
|
94
|
+
let shouldStopTraversal = false;
|
|
95
95
|
|
|
96
96
|
const getScope = (givenNode: ESNode = currentNode) => {
|
|
97
97
|
// On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope.
|
|
@@ -155,6 +155,14 @@ export function traverseWithContext<T = TraversalContextBase>(
|
|
|
155
155
|
},
|
|
156
156
|
|
|
157
157
|
getScope,
|
|
158
|
+
|
|
159
|
+
stopTraversal: () => {
|
|
160
|
+
shouldStopTraversal = true;
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
skipTraversal: () => {
|
|
164
|
+
shouldSkipTraversal = true;
|
|
165
|
+
},
|
|
158
166
|
});
|
|
159
167
|
|
|
160
168
|
const traversalContext: TraversalContext<T> = Object.freeze({
|
|
@@ -176,19 +184,30 @@ export function traverseWithContext<T = TraversalContextBase>(
|
|
|
176
184
|
});
|
|
177
185
|
|
|
178
186
|
const eventGenerator = new NodeEventGenerator(emitter);
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
err.currentNode = currentNode;
|
|
190
|
-
throw err;
|
|
187
|
+
|
|
188
|
+
function checkTraversalFlags(): void {
|
|
189
|
+
if (shouldStopTraversal) {
|
|
190
|
+
// No need to reset the flag since we won't enter any more nodes.
|
|
191
|
+
throw SimpleTraverser.Break;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (shouldSkipTraversal) {
|
|
195
|
+
shouldSkipTraversal = false;
|
|
196
|
+
throw SimpleTraverser.Skip;
|
|
191
197
|
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
SimpleTraverser.traverse(ast, {
|
|
201
|
+
enter(node) {
|
|
202
|
+
currentNode = node;
|
|
203
|
+
eventGenerator.enterNode(node);
|
|
204
|
+
checkTraversalFlags();
|
|
205
|
+
},
|
|
206
|
+
leave(node) {
|
|
207
|
+
currentNode = node;
|
|
208
|
+
eventGenerator.leaveNode(node);
|
|
209
|
+
checkTraversalFlags();
|
|
210
|
+
},
|
|
192
211
|
});
|
|
193
212
|
}
|
|
194
213
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hermes-transform",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Tools built on top of Hermes-ESTree to enable codebase transformation",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,11 +12,12 @@
|
|
|
12
12
|
"@babel/code-frame": "^7.16.0",
|
|
13
13
|
"esquery": "^1.4.0",
|
|
14
14
|
"flow-enums-runtime": "^0.0.6",
|
|
15
|
-
"hermes-eslint": "0.
|
|
16
|
-
"hermes-estree": "0.
|
|
15
|
+
"hermes-eslint": "0.10.0",
|
|
16
|
+
"hermes-estree": "0.10.0",
|
|
17
|
+
"hermes-parser": "0.10.0"
|
|
17
18
|
},
|
|
18
19
|
"peerDependencies": {
|
|
19
|
-
"prettier": "^2.
|
|
20
|
+
"prettier": "^2.7.1"
|
|
20
21
|
},
|
|
21
22
|
"files": [
|
|
22
23
|
"dist",
|
package/dist/getVisitorKeys.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
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.getVisitorKeys = getVisitorKeys;
|
|
16
|
-
exports.isNode = isNode;
|
|
17
|
-
|
|
18
|
-
var _hermesEslint = require("hermes-eslint");
|
|
19
|
-
|
|
20
|
-
function isNode(thing) {
|
|
21
|
-
return typeof thing === 'object' && thing != null && typeof thing.type === 'string';
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function getVisitorKeys(node) {
|
|
25
|
-
const keys = _hermesEslint.VisitorKeys[node.type];
|
|
26
|
-
|
|
27
|
-
if (keys == null) {
|
|
28
|
-
throw new Error(`No visitor keys found for node type "${node.type}".`);
|
|
29
|
-
} // $FlowExpectedError[prop-missing]
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return keys;
|
|
33
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
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
|
-
* @flow strict-local
|
|
8
|
-
* @format
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
import type {ESNode} from 'hermes-estree';
|
|
14
|
-
|
|
15
|
-
import {VisitorKeys} from 'hermes-eslint';
|
|
16
|
-
|
|
17
|
-
export function isNode(thing: mixed): boolean %checks {
|
|
18
|
-
return (
|
|
19
|
-
typeof thing === 'object' && thing != null && typeof thing.type === 'string'
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function getVisitorKeys<T: ESNode>(node: T): $ReadOnlyArray<$Keys<T>> {
|
|
24
|
-
const keys = VisitorKeys[node.type];
|
|
25
|
-
if (keys == null) {
|
|
26
|
-
throw new Error(`No visitor keys found for node type "${node.type}".`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// $FlowExpectedError[prop-missing]
|
|
30
|
-
return keys;
|
|
31
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
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
|
-
/**
|
|
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 assertArrayBounds(array, index) {
|
|
20
|
-
if (index < 0 || index >= array.length) {
|
|
21
|
-
throw new Error(`Invalid Mutation: Tried to mutate an elements array with an out of bounds index. Index: ${index}, Array Size: ${array.length}`);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function insertInArray(array, index, elements) {
|
|
26
|
-
if (index === array.length) {
|
|
27
|
-
// Support the insert at end of array case.
|
|
28
|
-
return array.concat(elements);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
assertArrayBounds(array, index);
|
|
32
|
-
return array.slice(0, index).concat(elements).concat(array.slice(index));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function removeFromArray(array, index) {
|
|
36
|
-
assertArrayBounds(array, index);
|
|
37
|
-
return [...array.slice(0, index), ...array.slice(index + 1)];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function replaceInArray(array, index, elements) {
|
|
41
|
-
assertArrayBounds(array, index);
|
|
42
|
-
return array.slice(0, index).concat(elements).concat(array.slice(index + 1));
|
|
43
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
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
|
-
* @flow strict-local
|
|
8
|
-
* @format
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
function assertArrayBounds<T>(array: $ReadOnlyArray<T>, index: number): void {
|
|
12
|
-
if (index < 0 || index >= array.length) {
|
|
13
|
-
throw new Error(
|
|
14
|
-
`Invalid Mutation: Tried to mutate an elements array with an out of bounds index. Index: ${index}, Array Size: ${array.length}`,
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function insertInArray<T>(
|
|
20
|
-
array: $ReadOnlyArray<T>,
|
|
21
|
-
index: number,
|
|
22
|
-
elements: $ReadOnlyArray<T>,
|
|
23
|
-
): Array<T> {
|
|
24
|
-
if (index === array.length) {
|
|
25
|
-
// Support the insert at end of array case.
|
|
26
|
-
return array.concat(elements);
|
|
27
|
-
}
|
|
28
|
-
assertArrayBounds(array, index);
|
|
29
|
-
return array.slice(0, index).concat(elements).concat(array.slice(index));
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function removeFromArray<T>(
|
|
33
|
-
array: $ReadOnlyArray<T>,
|
|
34
|
-
index: number,
|
|
35
|
-
): Array<T> {
|
|
36
|
-
assertArrayBounds(array, index);
|
|
37
|
-
return [...array.slice(0, index), ...array.slice(index + 1)];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function replaceInArray<T>(
|
|
41
|
-
array: $ReadOnlyArray<T>,
|
|
42
|
-
index: number,
|
|
43
|
-
elements: $ReadOnlyArray<T>,
|
|
44
|
-
): Array<T> {
|
|
45
|
-
assertArrayBounds(array, index);
|
|
46
|
-
return array
|
|
47
|
-
.slice(0, index)
|
|
48
|
-
.concat(elements)
|
|
49
|
-
.concat(array.slice(index + 1));
|
|
50
|
-
}
|