hermes-transform 0.6.0 → 0.9.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/ESLINT_LICENCE +19 -0
- package/PRETTIER_LICENCE +7 -0
- package/dist/detachedNode.js +96 -20
- package/dist/detachedNode.js.flow +105 -17
- package/dist/generated/TransformCloneSignatures.js.flow +33 -66
- package/dist/generated/TransformModifySignatures.js.flow +1113 -0
- package/dist/generated/TransformReplaceSignatures.js.flow +19 -40
- package/dist/generated/node-types.js +638 -905
- package/dist/generated/node-types.js.flow +998 -1256
- package/dist/generated/special-case-node-types.js +71 -77
- package/dist/generated/special-case-node-types.js.flow +104 -88
- package/dist/index.js.flow +2 -1
- package/dist/transform/MutationContext.js +2 -2
- package/dist/transform/MutationContext.js.flow +3 -2
- package/dist/transform/TransformContext.js +56 -43
- package/dist/transform/TransformContext.js.flow +154 -95
- package/dist/transform/comments/comments.js +133 -28
- package/dist/transform/comments/comments.js.flow +125 -28
- package/dist/transform/getTransformedAST.js +20 -12
- package/dist/transform/getTransformedAST.js.flow +32 -14
- package/dist/transform/mutations/{AddLeadingComments.js → AddComments.js} +11 -8
- package/dist/transform/mutations/AddComments.js.flow +50 -0
- package/dist/transform/mutations/CloneCommentsTo.js +1 -2
- package/dist/transform/mutations/CloneCommentsTo.js.flow +1 -2
- package/dist/transform/mutations/InsertStatement.js +3 -1
- package/dist/transform/mutations/InsertStatement.js.flow +7 -1
- package/dist/transform/mutations/RemoveNode.js +10 -3
- package/dist/transform/mutations/RemoveNode.js.flow +14 -3
- package/dist/transform/mutations/ReplaceNode.js +7 -2
- package/dist/transform/mutations/ReplaceNode.js.flow +5 -2
- package/dist/transform/mutations/ReplaceStatementWithMany.js.flow +5 -2
- package/dist/transform/mutations/utils/arrayUtils.js +14 -0
- package/dist/transform/mutations/utils/arrayUtils.js.flow +15 -0
- package/dist/transform/transform.js +38 -6
- package/dist/transform/transform.js.flow +40 -6
- package/dist/traverse/NodeEventGenerator.js.flow +1 -1
- package/dist/traverse/traverse.js +27 -3
- package/dist/traverse/traverse.js.flow +63 -10
- package/package.json +9 -4
- package/dist/transform/mutations/AddLeadingComments.js.flow +0 -49
- package/dist/transform/mutations/AddTrailingComments.js +0 -40
- package/dist/transform/mutations/AddTrailingComments.js.flow +0 -49
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.CommentPlacement = void 0;
|
|
7
|
+
exports.addComment = addComment;
|
|
6
8
|
exports.addCommentsToNode = addCommentsToNode;
|
|
7
|
-
exports.addLeadingComment = addLeadingComment;
|
|
8
|
-
exports.addTrailingComment = addTrailingComment;
|
|
9
9
|
exports.appendCommentToSource = appendCommentToSource;
|
|
10
10
|
exports.attachComments = attachComments;
|
|
11
11
|
exports.cloneComment = cloneComment;
|
|
12
12
|
exports.cloneCommentWithMarkers = cloneCommentWithMarkers;
|
|
13
13
|
exports.getCommentsForNode = getCommentsForNode;
|
|
14
|
+
exports.getLeadingCommentsForNode = getLeadingCommentsForNode;
|
|
15
|
+
exports.getTrailingCommentsForNode = getTrailingCommentsForNode;
|
|
14
16
|
exports.isLeadingComment = isLeadingComment;
|
|
15
17
|
exports.isTrailingComment = isTrailingComment;
|
|
16
18
|
exports.moveCommentsToNewNode = moveCommentsToNewNode;
|
|
@@ -24,6 +26,8 @@ var _printerEstree = _interopRequireDefault(require("./prettier/language-js/prin
|
|
|
24
26
|
|
|
25
27
|
var _util = require("./prettier/common/util");
|
|
26
28
|
|
|
29
|
+
var _os = require("os");
|
|
30
|
+
|
|
27
31
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
28
32
|
|
|
29
33
|
/**
|
|
@@ -38,6 +42,10 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
38
42
|
// $FlowExpectedError[untyped-import]
|
|
39
43
|
// $FlowExpectedError[untyped-import]
|
|
40
44
|
// $FlowExpectedError[untyped-import]
|
|
45
|
+
const CommentPlacement = require("flow-enums-runtime").Mirrored(["LEADING_OWN_LINE", "LEADING_INLINE", "TRAILING_OWN_LINE", "TRAILING_INLINE"]);
|
|
46
|
+
|
|
47
|
+
exports.CommentPlacement = CommentPlacement;
|
|
48
|
+
|
|
41
49
|
function attachComments(comments, ast, text) {
|
|
42
50
|
(0, _comments.attach)(comments, ast, text, {
|
|
43
51
|
locStart: _loc.locStart,
|
|
@@ -56,13 +64,21 @@ function setCommentsOnNode(node, comments) {
|
|
|
56
64
|
node.comments = comments;
|
|
57
65
|
}
|
|
58
66
|
|
|
59
|
-
function addCommentsToNode(node, comments) {
|
|
67
|
+
function addCommentsToNode(node, comments, side = 'trailing') {
|
|
60
68
|
var _node$comments;
|
|
61
69
|
|
|
62
|
-
// $FlowExpectedError - this property is secretly added by prettier.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
node.comments
|
|
70
|
+
// $FlowExpectedError[prop-missing] - this property is secretly added by prettier.
|
|
71
|
+
// $FlowExpectedError[cannot-write]
|
|
72
|
+
// $FlowExpectedError[incompatible-use]
|
|
73
|
+
node.comments = (_node$comments = node.comments) != null ? _node$comments : [];
|
|
74
|
+
|
|
75
|
+
if (side === 'leading') {
|
|
76
|
+
// $FlowExpectedError[incompatible-cast]
|
|
77
|
+
node.comments.unshift(...comments);
|
|
78
|
+
} else {
|
|
79
|
+
// $FlowExpectedError[incompatible-cast]
|
|
80
|
+
node.comments.push(...comments);
|
|
81
|
+
}
|
|
66
82
|
}
|
|
67
83
|
|
|
68
84
|
function getCommentsForNode(node) {
|
|
@@ -82,12 +98,30 @@ function isTrailingComment(comment) {
|
|
|
82
98
|
return comment.trailing === true;
|
|
83
99
|
}
|
|
84
100
|
|
|
85
|
-
function
|
|
86
|
-
|
|
101
|
+
function getLeadingCommentsForNode(node) {
|
|
102
|
+
return getCommentsForNode(node).filter(isLeadingComment);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function getTrailingCommentsForNode(node) {
|
|
106
|
+
return getCommentsForNode(node).filter(isTrailingComment);
|
|
87
107
|
}
|
|
88
108
|
|
|
89
|
-
function
|
|
90
|
-
(
|
|
109
|
+
function addComment(node, comment, placement) {
|
|
110
|
+
switch (placement) {
|
|
111
|
+
case CommentPlacement.LEADING_OWN_LINE:
|
|
112
|
+
case CommentPlacement.LEADING_INLINE:
|
|
113
|
+
{
|
|
114
|
+
(0, _util.addLeadingComment)(node, comment);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
case CommentPlacement.TRAILING_OWN_LINE:
|
|
119
|
+
case CommentPlacement.TRAILING_INLINE:
|
|
120
|
+
{
|
|
121
|
+
(0, _util.addTrailingComment)(node, comment);
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
91
125
|
}
|
|
92
126
|
|
|
93
127
|
function cloneComment(comment) {
|
|
@@ -112,29 +146,100 @@ function cloneCommentWithMarkers(comment) {
|
|
|
112
146
|
};
|
|
113
147
|
}
|
|
114
148
|
|
|
115
|
-
function
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
149
|
+
function getFirstNewlineIndex(code) {
|
|
150
|
+
return code.search(/\r\n|\n|\r/);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function getFirstNonWhitespaceIndex(code) {
|
|
154
|
+
return code.search(/\S/);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function appendCommentToSource(code, comment, placement) {
|
|
158
|
+
let newCode = code;
|
|
121
159
|
|
|
122
160
|
switch (comment.type) {
|
|
123
161
|
case 'Block':
|
|
124
|
-
|
|
125
|
-
|
|
162
|
+
{
|
|
163
|
+
// Prettier decides if a newline is necessary between the comment and its node by looking
|
|
164
|
+
// to see if a newline seperates them in the source text. We can trick prettier into
|
|
165
|
+
// formatting how we want for new comments by placing the range such that a newline
|
|
166
|
+
// will (OWN_LINE) or will not (INLINE) be found when searching from the specified range
|
|
167
|
+
// position.
|
|
168
|
+
switch (placement) {
|
|
169
|
+
case CommentPlacement.LEADING_OWN_LINE:
|
|
170
|
+
case CommentPlacement.TRAILING_OWN_LINE:
|
|
171
|
+
{
|
|
172
|
+
// Since we always want a line break we need to ensure a newline is found when
|
|
173
|
+
// searching out from either side of the comment range.
|
|
174
|
+
let firstNewline = getFirstNewlineIndex(code);
|
|
175
|
+
|
|
176
|
+
if (firstNewline === -1) {
|
|
177
|
+
// No newline in file, lets add one.
|
|
178
|
+
newCode += _os.EOL;
|
|
179
|
+
firstNewline = newCode.length;
|
|
180
|
+
} // Prettier only uses these ranges for detecting whitespace, so this nonsensical
|
|
181
|
+
// range is safe.
|
|
182
|
+
// $FlowExpectedError[cannot-write]
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
comment.range = [firstNewline + 1, firstNewline];
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
case CommentPlacement.LEADING_INLINE:
|
|
190
|
+
case CommentPlacement.TRAILING_INLINE:
|
|
191
|
+
{
|
|
192
|
+
// Since we don't want a line break we need to ensure a non whitespace char is
|
|
193
|
+
// always found before a newline when searching out from either side of the
|
|
194
|
+
// comment range.
|
|
195
|
+
let firstNonWhitespace = getFirstNonWhitespaceIndex(code);
|
|
196
|
+
|
|
197
|
+
if (firstNonWhitespace === -1) {
|
|
198
|
+
// No non whitespace chars in file, lets add an identifiable statement for prettier to find.
|
|
199
|
+
newCode += '$FORCE_INLINE_ON_EMPTY_FILE_TOKEN$;';
|
|
200
|
+
firstNonWhitespace = newCode.length;
|
|
201
|
+
break;
|
|
202
|
+
} // $FlowExpectedError[cannot-write]
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
comment.range = [firstNonWhitespace + 1, firstNonWhitespace];
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
126
212
|
|
|
127
213
|
case 'Line':
|
|
128
|
-
|
|
129
|
-
|
|
214
|
+
{
|
|
215
|
+
// For `Line` comments prettier slices comments directly from the source code when printing
|
|
216
|
+
// https://github.com/prettier/prettier/blob/5f0ee39fa03532c85bd1c35291450fe7ac3667b3/src/language-js/print/comment.js#L15-L20
|
|
217
|
+
// this means that we need to have any appended comments directly in the
|
|
218
|
+
// source code or else prettier will slice nothing and bork up the transform
|
|
219
|
+
const commentText = `//${comment.value}`;
|
|
220
|
+
const lastChar = newCode[newCode.length - 1];
|
|
221
|
+
|
|
222
|
+
if (lastChar !== '\n' && lastChar !== '\r') {
|
|
223
|
+
newCode += _os.EOL;
|
|
224
|
+
} // Line comments cannot be inline before a node so we only place trailing Line comments inline.
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
if (placement === CommentPlacement.TRAILING_INLINE) {
|
|
228
|
+
// Prettier determines an "end of line" comment by walking backwards from
|
|
229
|
+
// the comment start range through the source code to see if it finds a non
|
|
230
|
+
// newline token. In order to trick prettier for new comments we need to
|
|
231
|
+
// insert fake source code for it to find.
|
|
232
|
+
newCode += '$FORCE_END_OF_LINE_COMMENT_TOKEN$;';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const start = newCode.length;
|
|
236
|
+
newCode += commentText;
|
|
237
|
+
const end = newCode.length; // $FlowExpectedError[cannot-write]
|
|
238
|
+
|
|
239
|
+
comment.range = [start, end];
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
130
242
|
}
|
|
131
243
|
|
|
132
|
-
let newCode = code;
|
|
133
|
-
newCode += '\n';
|
|
134
|
-
const start = newCode.length;
|
|
135
|
-
newCode += commentText;
|
|
136
|
-
const end = newCode.length; // $FlowExpectedError[cannot-write]
|
|
137
|
-
|
|
138
|
-
comment.range = [start, end];
|
|
139
244
|
return newCode;
|
|
140
245
|
}
|
|
@@ -23,9 +23,17 @@ import {
|
|
|
23
23
|
// $FlowExpectedError[untyped-import]
|
|
24
24
|
addTrailingComment as untypedAddTrailingComment,
|
|
25
25
|
} from './prettier/common/util';
|
|
26
|
+
import {EOL} from 'os';
|
|
26
27
|
|
|
27
28
|
export type Options = $ReadOnly<{}>;
|
|
28
29
|
|
|
30
|
+
export enum CommentPlacement {
|
|
31
|
+
LEADING_OWN_LINE,
|
|
32
|
+
LEADING_INLINE,
|
|
33
|
+
TRAILING_OWN_LINE,
|
|
34
|
+
TRAILING_INLINE,
|
|
35
|
+
}
|
|
36
|
+
|
|
29
37
|
export function attachComments(
|
|
30
38
|
comments: $ReadOnlyArray<Comment>,
|
|
31
39
|
ast: Program,
|
|
@@ -57,11 +65,19 @@ export function setCommentsOnNode(
|
|
|
57
65
|
export function addCommentsToNode(
|
|
58
66
|
node: ESNode | DetachedNode<ESNode>,
|
|
59
67
|
comments: $ReadOnlyArray<Comment>,
|
|
68
|
+
side?: 'leading' | 'trailing' = 'trailing',
|
|
60
69
|
): void {
|
|
61
|
-
// $FlowExpectedError - this property is secretly added by prettier.
|
|
70
|
+
// $FlowExpectedError[prop-missing] - this property is secretly added by prettier.
|
|
71
|
+
// $FlowExpectedError[cannot-write]
|
|
72
|
+
// $FlowExpectedError[incompatible-use]
|
|
62
73
|
node.comments = node.comments ?? [];
|
|
63
|
-
|
|
64
|
-
|
|
74
|
+
if (side === 'leading') {
|
|
75
|
+
// $FlowExpectedError[incompatible-cast]
|
|
76
|
+
(node.comments: Array<Comment>).unshift(...comments);
|
|
77
|
+
} else {
|
|
78
|
+
// $FlowExpectedError[incompatible-cast]
|
|
79
|
+
(node.comments: Array<Comment>).push(...comments);
|
|
80
|
+
}
|
|
65
81
|
}
|
|
66
82
|
|
|
67
83
|
export function getCommentsForNode(
|
|
@@ -80,18 +96,35 @@ export function isTrailingComment(comment: Comment): boolean {
|
|
|
80
96
|
return comment.trailing === true;
|
|
81
97
|
}
|
|
82
98
|
|
|
83
|
-
export function
|
|
99
|
+
export function getLeadingCommentsForNode(
|
|
84
100
|
node: ESNode | DetachedNode<ESNode>,
|
|
85
|
-
|
|
86
|
-
)
|
|
87
|
-
|
|
101
|
+
): $ReadOnlyArray<Comment> {
|
|
102
|
+
return getCommentsForNode(node).filter(isLeadingComment);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function getTrailingCommentsForNode(
|
|
106
|
+
node: ESNode | DetachedNode<ESNode>,
|
|
107
|
+
): $ReadOnlyArray<Comment> {
|
|
108
|
+
return getCommentsForNode(node).filter(isTrailingComment);
|
|
88
109
|
}
|
|
89
110
|
|
|
90
|
-
export function
|
|
111
|
+
export function addComment(
|
|
91
112
|
node: ESNode | DetachedNode<ESNode>,
|
|
92
113
|
comment: Comment,
|
|
114
|
+
placement: CommentPlacement,
|
|
93
115
|
): void {
|
|
94
|
-
|
|
116
|
+
switch (placement) {
|
|
117
|
+
case CommentPlacement.LEADING_OWN_LINE:
|
|
118
|
+
case CommentPlacement.LEADING_INLINE: {
|
|
119
|
+
untypedAddLeadingComment(node, comment);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
case CommentPlacement.TRAILING_OWN_LINE:
|
|
123
|
+
case CommentPlacement.TRAILING_INLINE: {
|
|
124
|
+
untypedAddTrailingComment(node, comment);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
95
128
|
}
|
|
96
129
|
|
|
97
130
|
export function cloneComment<T: Comment>(comment: T): T {
|
|
@@ -116,30 +149,94 @@ export function cloneCommentWithMarkers<T: Comment>(comment: T): T {
|
|
|
116
149
|
};
|
|
117
150
|
}
|
|
118
151
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
152
|
+
function getFirstNewlineIndex(code: string): number {
|
|
153
|
+
return code.search(/\r\n|\n|\r/);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function getFirstNonWhitespaceIndex(code: string): number {
|
|
157
|
+
return code.search(/\S/);
|
|
158
|
+
}
|
|
124
159
|
|
|
125
|
-
|
|
160
|
+
export function appendCommentToSource(
|
|
161
|
+
code: string,
|
|
162
|
+
comment: Comment,
|
|
163
|
+
placement: CommentPlacement,
|
|
164
|
+
): string {
|
|
165
|
+
let newCode = code;
|
|
126
166
|
switch (comment.type) {
|
|
127
|
-
case 'Block':
|
|
128
|
-
|
|
167
|
+
case 'Block': {
|
|
168
|
+
// Prettier decides if a newline is necessary between the comment and its node by looking
|
|
169
|
+
// to see if a newline seperates them in the source text. We can trick prettier into
|
|
170
|
+
// formatting how we want for new comments by placing the range such that a newline
|
|
171
|
+
// will (OWN_LINE) or will not (INLINE) be found when searching from the specified range
|
|
172
|
+
// position.
|
|
173
|
+
switch (placement) {
|
|
174
|
+
case CommentPlacement.LEADING_OWN_LINE:
|
|
175
|
+
case CommentPlacement.TRAILING_OWN_LINE: {
|
|
176
|
+
// Since we always want a line break we need to ensure a newline is found when
|
|
177
|
+
// searching out from either side of the comment range.
|
|
178
|
+
let firstNewline = getFirstNewlineIndex(code);
|
|
179
|
+
if (firstNewline === -1) {
|
|
180
|
+
// No newline in file, lets add one.
|
|
181
|
+
newCode += EOL;
|
|
182
|
+
firstNewline = newCode.length;
|
|
183
|
+
}
|
|
184
|
+
// Prettier only uses these ranges for detecting whitespace, so this nonsensical
|
|
185
|
+
// range is safe.
|
|
186
|
+
// $FlowExpectedError[cannot-write]
|
|
187
|
+
comment.range = [firstNewline + 1, firstNewline];
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
case CommentPlacement.LEADING_INLINE:
|
|
191
|
+
case CommentPlacement.TRAILING_INLINE: {
|
|
192
|
+
// Since we don't want a line break we need to ensure a non whitespace char is
|
|
193
|
+
// always found before a newline when searching out from either side of the
|
|
194
|
+
// comment range.
|
|
195
|
+
let firstNonWhitespace = getFirstNonWhitespaceIndex(code);
|
|
196
|
+
if (firstNonWhitespace === -1) {
|
|
197
|
+
// No non whitespace chars in file, lets add an identifiable statement for prettier to find.
|
|
198
|
+
newCode += '$FORCE_INLINE_ON_EMPTY_FILE_TOKEN$;';
|
|
199
|
+
firstNonWhitespace = newCode.length;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// $FlowExpectedError[cannot-write]
|
|
204
|
+
comment.range = [firstNonWhitespace + 1, firstNonWhitespace];
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
129
208
|
break;
|
|
130
|
-
|
|
131
|
-
|
|
209
|
+
}
|
|
210
|
+
case 'Line': {
|
|
211
|
+
// For `Line` comments prettier slices comments directly from the source code when printing
|
|
212
|
+
// https://github.com/prettier/prettier/blob/5f0ee39fa03532c85bd1c35291450fe7ac3667b3/src/language-js/print/comment.js#L15-L20
|
|
213
|
+
// this means that we need to have any appended comments directly in the
|
|
214
|
+
// source code or else prettier will slice nothing and bork up the transform
|
|
215
|
+
const commentText = `//${comment.value}`;
|
|
216
|
+
|
|
217
|
+
const lastChar = newCode[newCode.length - 1];
|
|
218
|
+
if (lastChar !== '\n' && lastChar !== '\r') {
|
|
219
|
+
newCode += EOL;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Line comments cannot be inline before a node so we only place trailing Line comments inline.
|
|
223
|
+
if (placement === CommentPlacement.TRAILING_INLINE) {
|
|
224
|
+
// Prettier determines an "end of line" comment by walking backwards from
|
|
225
|
+
// the comment start range through the source code to see if it finds a non
|
|
226
|
+
// newline token. In order to trick prettier for new comments we need to
|
|
227
|
+
// insert fake source code for it to find.
|
|
228
|
+
newCode += '$FORCE_END_OF_LINE_COMMENT_TOKEN$;';
|
|
229
|
+
}
|
|
230
|
+
const start = newCode.length;
|
|
231
|
+
newCode += commentText;
|
|
232
|
+
const end = newCode.length;
|
|
233
|
+
|
|
234
|
+
// $FlowExpectedError[cannot-write]
|
|
235
|
+
comment.range = [start, end];
|
|
236
|
+
|
|
132
237
|
break;
|
|
238
|
+
}
|
|
133
239
|
}
|
|
134
240
|
|
|
135
|
-
let newCode = code;
|
|
136
|
-
newCode += '\n';
|
|
137
|
-
const start = newCode.length;
|
|
138
|
-
newCode += commentText;
|
|
139
|
-
const end = newCode.length;
|
|
140
|
-
|
|
141
|
-
// $FlowExpectedError[cannot-write]
|
|
142
|
-
comment.range = [start, end];
|
|
143
|
-
|
|
144
241
|
return newCode;
|
|
145
242
|
}
|
|
@@ -26,9 +26,7 @@ var _TransformContext = require("./TransformContext");
|
|
|
26
26
|
|
|
27
27
|
var _comments = require("./comments/comments");
|
|
28
28
|
|
|
29
|
-
var
|
|
30
|
-
|
|
31
|
-
var _AddTrailingComments = require("./mutations/AddTrailingComments");
|
|
29
|
+
var _AddComments = require("./mutations/AddComments");
|
|
32
30
|
|
|
33
31
|
var _CloneCommentsTo = require("./mutations/CloneCommentsTo");
|
|
34
32
|
|
|
@@ -55,8 +53,8 @@ function getTransformedAST(code, visitors) {
|
|
|
55
53
|
|
|
56
54
|
(0, _comments.attachComments)(ast.comments, ast, code); // traverse the AST and colllect the mutations
|
|
57
55
|
|
|
58
|
-
const transformContext = (0, _TransformContext.getTransformContext)(
|
|
59
|
-
(0, _traverse.traverseWithContext)(ast, scopeManager, () => transformContext, visitors); // apply the mutations to the AST
|
|
56
|
+
const transformContext = (0, _TransformContext.getTransformContext)();
|
|
57
|
+
(0, _traverse.traverseWithContext)(code, ast, scopeManager, () => transformContext, visitors); // apply the mutations to the AST
|
|
60
58
|
|
|
61
59
|
const mutationContext = new _MutationContext.MutationContext(code);
|
|
62
60
|
const removeCommentMutations = [];
|
|
@@ -96,14 +94,9 @@ function getTransformedAST(code, visitors) {
|
|
|
96
94
|
return null;
|
|
97
95
|
}
|
|
98
96
|
|
|
99
|
-
case '
|
|
100
|
-
{
|
|
101
|
-
return (0, _AddLeadingComments.performAddLeadingCommentsMutation)(mutationContext, mutation);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
case 'addTrailingComments':
|
|
97
|
+
case 'addComments':
|
|
105
98
|
{
|
|
106
|
-
return (0,
|
|
99
|
+
return (0, _AddComments.performAddCommentsMutation)(mutationContext, mutation);
|
|
107
100
|
}
|
|
108
101
|
|
|
109
102
|
case 'cloneCommentsTo':
|
|
@@ -129,6 +122,21 @@ function getTransformedAST(code, visitors) {
|
|
|
129
122
|
if (mutationRoot) {
|
|
130
123
|
(0, _detachedNode.updateAllParentPointers)(mutationRoot);
|
|
131
124
|
}
|
|
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
|
+
}
|
|
132
140
|
} // remove the comments
|
|
133
141
|
// this is done at the end because it requires a complete traversal of the AST
|
|
134
142
|
// so that we can find relevant node's attachment array
|
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
'use strict';
|
|
12
12
|
|
|
13
13
|
import type {ESNode, Program} from 'hermes-estree';
|
|
14
|
-
import type {
|
|
15
|
-
import type {TransformContext} from './TransformContext';
|
|
14
|
+
import type {TransformVisitor} from './transform';
|
|
16
15
|
import type {RemoveCommentMutation} from './mutations/RemoveComment';
|
|
17
16
|
|
|
18
17
|
import {parseForESLint} from 'hermes-eslint';
|
|
@@ -20,9 +19,12 @@ import {updateAllParentPointers} from '../detachedNode';
|
|
|
20
19
|
import {traverseWithContext} from '../traverse/traverse';
|
|
21
20
|
import {MutationContext} from './MutationContext';
|
|
22
21
|
import {getTransformContext} from './TransformContext';
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
import {
|
|
23
|
+
addCommentsToNode,
|
|
24
|
+
attachComments,
|
|
25
|
+
getLeadingCommentsForNode,
|
|
26
|
+
} from './comments/comments';
|
|
27
|
+
import {performAddCommentsMutation} from './mutations/AddComments';
|
|
26
28
|
import {performCloneCommentsToMutation} from './mutations/CloneCommentsTo';
|
|
27
29
|
import {performInsertStatementMutation} from './mutations/InsertStatement';
|
|
28
30
|
import {performRemoveCommentMutations} from './mutations/RemoveComment';
|
|
@@ -33,7 +35,7 @@ import {performReplaceStatementWithManyMutation} from './mutations/ReplaceStatem
|
|
|
33
35
|
|
|
34
36
|
export function getTransformedAST(
|
|
35
37
|
code: string,
|
|
36
|
-
visitors:
|
|
38
|
+
visitors: TransformVisitor,
|
|
37
39
|
): {
|
|
38
40
|
ast: Program,
|
|
39
41
|
astWasMutated: boolean,
|
|
@@ -48,8 +50,14 @@ export function getTransformedAST(
|
|
|
48
50
|
attachComments(ast.comments, ast, code);
|
|
49
51
|
|
|
50
52
|
// traverse the AST and colllect the mutations
|
|
51
|
-
const transformContext = getTransformContext(
|
|
52
|
-
traverseWithContext(
|
|
53
|
+
const transformContext = getTransformContext();
|
|
54
|
+
traverseWithContext(
|
|
55
|
+
code,
|
|
56
|
+
ast,
|
|
57
|
+
scopeManager,
|
|
58
|
+
() => transformContext,
|
|
59
|
+
visitors,
|
|
60
|
+
);
|
|
53
61
|
|
|
54
62
|
// apply the mutations to the AST
|
|
55
63
|
const mutationContext = new MutationContext(code);
|
|
@@ -88,12 +96,8 @@ export function getTransformedAST(
|
|
|
88
96
|
return null;
|
|
89
97
|
}
|
|
90
98
|
|
|
91
|
-
case '
|
|
92
|
-
return
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
case 'addTrailingComments': {
|
|
96
|
-
return performAddTrailingCommentsMutation(mutationContext, mutation);
|
|
99
|
+
case 'addComments': {
|
|
100
|
+
return performAddCommentsMutation(mutationContext, mutation);
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
case 'cloneCommentsTo': {
|
|
@@ -120,6 +124,20 @@ export function getTransformedAST(
|
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
126
|
|
|
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
|
+
|
|
123
141
|
// remove the comments
|
|
124
142
|
// this is done at the end because it requires a complete traversal of the AST
|
|
125
143
|
// so that we can find relevant node's attachment array
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
7
|
-
exports.
|
|
6
|
+
exports.createAddCommentsMutation = createAddCommentsMutation;
|
|
7
|
+
exports.performAddCommentsMutation = performAddCommentsMutation;
|
|
8
8
|
|
|
9
9
|
var _comments = require("../comments/comments");
|
|
10
10
|
|
|
@@ -17,23 +17,26 @@ var _comments = require("../comments/comments");
|
|
|
17
17
|
*
|
|
18
18
|
* @format
|
|
19
19
|
*/
|
|
20
|
-
function
|
|
20
|
+
function createAddCommentsMutation(node, comments) {
|
|
21
21
|
if (comments.length === 0) {
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
return {
|
|
26
|
-
type: '
|
|
26
|
+
type: 'addComments',
|
|
27
27
|
comments,
|
|
28
28
|
node
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function
|
|
33
|
-
for (const
|
|
32
|
+
function performAddCommentsMutation(mutationContext, mutation) {
|
|
33
|
+
for (const {
|
|
34
|
+
comment: originalComment,
|
|
35
|
+
placement
|
|
36
|
+
} of mutation.comments) {
|
|
34
37
|
const comment = (0, _comments.cloneComment)(originalComment);
|
|
35
|
-
mutationContext.appendCommentToSource(comment);
|
|
36
|
-
(0, _comments.
|
|
38
|
+
mutationContext.appendCommentToSource(comment, placement);
|
|
39
|
+
(0, _comments.addComment)(mutation.node, comment, placement);
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
return null;
|
|
@@ -0,0 +1,50 @@
|
|
|
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
|
+
import type {Comment, ESNode} from 'hermes-estree';
|
|
12
|
+
import type {DetachedNode} from '../../detachedNode';
|
|
13
|
+
import type {MutationContext} from '../MutationContext';
|
|
14
|
+
import type {CommentPlacement} from '../comments/comments';
|
|
15
|
+
|
|
16
|
+
import {addComment, cloneComment} from '../comments/comments';
|
|
17
|
+
|
|
18
|
+
export type AddCommentsMutation = $ReadOnly<{
|
|
19
|
+
type: 'addComments',
|
|
20
|
+
comments: $ReadOnlyArray<{comment: Comment, placement: CommentPlacement}>,
|
|
21
|
+
node: ESNode | DetachedNode<ESNode>,
|
|
22
|
+
}>;
|
|
23
|
+
|
|
24
|
+
export function createAddCommentsMutation(
|
|
25
|
+
node: AddCommentsMutation['node'],
|
|
26
|
+
comments: AddCommentsMutation['comments'],
|
|
27
|
+
): ?AddCommentsMutation {
|
|
28
|
+
if (comments.length === 0) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
type: 'addComments',
|
|
34
|
+
comments,
|
|
35
|
+
node,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function performAddCommentsMutation(
|
|
40
|
+
mutationContext: MutationContext,
|
|
41
|
+
mutation: AddCommentsMutation,
|
|
42
|
+
): null {
|
|
43
|
+
for (const {comment: originalComment, placement} of mutation.comments) {
|
|
44
|
+
const comment = cloneComment(originalComment);
|
|
45
|
+
mutationContext.appendCommentToSource(comment, placement);
|
|
46
|
+
addComment(mutation.node, comment, placement);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
@@ -25,12 +25,11 @@ function createCloneCommentsToMutation(target, destination) {
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
function performCloneCommentsToMutation(
|
|
28
|
+
function performCloneCommentsToMutation(_mutationContext, mutation) {
|
|
29
29
|
const newComments = [];
|
|
30
30
|
|
|
31
31
|
for (const originalComment of (0, _comments.getCommentsForNode)(mutation.target)) {
|
|
32
32
|
const comment = (0, _comments.cloneCommentWithMarkers)(originalComment);
|
|
33
|
-
mutationContext.appendCommentToSource(comment);
|
|
34
33
|
newComments.push(comment);
|
|
35
34
|
}
|
|
36
35
|
|