flow-parser 0.318.0 → 0.319.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 (102) hide show
  1. package/oxidized/FlowParser.js +249 -0
  2. package/oxidized/FlowParser.js.flow +457 -0
  3. package/oxidized/FlowParserDeserializer.js +209 -0
  4. package/oxidized/FlowParserDeserializer.js.flow +323 -0
  5. package/oxidized/FlowParserNodeDeserializers.js +1767 -0
  6. package/oxidized/FlowParserNodeDeserializers.js.flow +18 -0
  7. package/oxidized/FlowParserWASM.js +1 -0
  8. package/oxidized/FlowParserWASM.js.flow +119 -0
  9. package/oxidized/HermesAST.js.flow +57 -0
  10. package/oxidized/HermesParserDecodeUTF8String.js +45 -0
  11. package/oxidized/HermesParserDecodeUTF8String.js.flow +65 -0
  12. package/oxidized/ParserOptions.js +8 -0
  13. package/oxidized/ParserOptions.js.flow +55 -0
  14. package/oxidized/babel/TransformESTreeToBabel.js +1055 -0
  15. package/oxidized/babel/TransformESTreeToBabel.js.flow +1349 -0
  16. package/oxidized/estree/StripFlowTypes.js +158 -0
  17. package/oxidized/estree/StripFlowTypes.js.flow +158 -0
  18. package/oxidized/estree/StripFlowTypesForBabel.js +176 -0
  19. package/oxidized/estree/StripFlowTypesForBabel.js.flow +216 -0
  20. package/oxidized/estree/TransformComponentSyntax.js +751 -0
  21. package/oxidized/estree/TransformComponentSyntax.js.flow +864 -0
  22. package/oxidized/estree/TransformEnumSyntax.js +92 -0
  23. package/oxidized/estree/TransformEnumSyntax.js.flow +125 -0
  24. package/oxidized/estree/TransformMatchSyntax.js +990 -0
  25. package/oxidized/estree/TransformMatchSyntax.js.flow +991 -0
  26. package/oxidized/estree/TransformRecordSyntax.js +283 -0
  27. package/oxidized/estree/TransformRecordSyntax.js.flow +310 -0
  28. package/oxidized/generated/ESTreeVisitorKeys.js +234 -0
  29. package/oxidized/generated/ESTreeVisitorKeys.js.flow +22 -0
  30. package/oxidized/getModuleDocblock.js +87 -0
  31. package/oxidized/getModuleDocblock.js.flow +119 -0
  32. package/oxidized/index.js +220 -0
  33. package/oxidized/index.js.flow +183 -0
  34. package/oxidized/oxidized-src/FlowParser.js +249 -0
  35. package/oxidized/oxidized-src/FlowParserDeserializer.js +209 -0
  36. package/oxidized/oxidized-src/FlowParserNodeDeserializers.js +1767 -0
  37. package/oxidized/oxidized-src/HermesParserDecodeUTF8String.js +45 -0
  38. package/oxidized/oxidized-src/ParserOptions.js +8 -0
  39. package/oxidized/oxidized-src/babel/TransformESTreeToBabel.js +1055 -0
  40. package/oxidized/oxidized-src/estree/StripFlowTypes.js +158 -0
  41. package/oxidized/oxidized-src/estree/StripFlowTypesForBabel.js +176 -0
  42. package/oxidized/oxidized-src/estree/TransformComponentSyntax.js +751 -0
  43. package/oxidized/oxidized-src/estree/TransformEnumSyntax.js +92 -0
  44. package/oxidized/oxidized-src/estree/TransformMatchSyntax.js +990 -0
  45. package/oxidized/oxidized-src/estree/TransformRecordSyntax.js +283 -0
  46. package/oxidized/oxidized-src/generated/ESTreeVisitorKeys.js +234 -0
  47. package/oxidized/oxidized-src/getModuleDocblock.js +87 -0
  48. package/oxidized/oxidized-src/index.js +220 -0
  49. package/oxidized/oxidized-src/transform/SimpleTransform.js +95 -0
  50. package/oxidized/oxidized-src/transform/astArrayMutationHelpers.js +52 -0
  51. package/oxidized/oxidized-src/transform/astNodeMutationHelpers.js +142 -0
  52. package/oxidized/oxidized-src/transform/print/comments/comments.js +245 -0
  53. package/oxidized/oxidized-src/transform/print/comments/prettier/common/util.js +235 -0
  54. package/oxidized/oxidized-src/transform/print/comments/prettier/language-js/comments.js +663 -0
  55. package/oxidized/oxidized-src/transform/print/comments/prettier/language-js/loc.js +30 -0
  56. package/oxidized/oxidized-src/transform/print/comments/prettier/language-js/printer-estree.js +23 -0
  57. package/oxidized/oxidized-src/transform/print/comments/prettier/language-js/utils.js +89 -0
  58. package/oxidized/oxidized-src/transform/print/comments/prettier/main/comments.js +374 -0
  59. package/oxidized/oxidized-src/transform/print/comments/prettier/utils/get-last.js +5 -0
  60. package/oxidized/oxidized-src/transform/print/detachedNodeTypes.js +1 -0
  61. package/oxidized/oxidized-src/transform/print/print.js +68 -0
  62. package/oxidized/oxidized-src/traverse/SimpleTraverser.js +90 -0
  63. package/oxidized/oxidized-src/traverse/getVisitorKeys.js +29 -0
  64. package/oxidized/oxidized-src/utils/Builders.js +181 -0
  65. package/oxidized/oxidized-src/utils/GenID.js +37 -0
  66. package/oxidized/oxidized-src/utils/createSyntaxError.js +15 -0
  67. package/oxidized/oxidized-src/utils/isReservedWord.js +53 -0
  68. package/oxidized/oxidized-src/utils/mutateESTreeASTForPrettier.js +85 -0
  69. package/oxidized/transform/SimpleTransform.js +95 -0
  70. package/oxidized/transform/SimpleTransform.js.flow +168 -0
  71. package/oxidized/transform/astArrayMutationHelpers.js +52 -0
  72. package/oxidized/transform/astArrayMutationHelpers.js.flow +71 -0
  73. package/oxidized/transform/astNodeMutationHelpers.js +142 -0
  74. package/oxidized/transform/astNodeMutationHelpers.js.flow +252 -0
  75. package/oxidized/transform/print/comments/comments.js +245 -0
  76. package/oxidized/transform/print/comments/comments.js.flow +330 -0
  77. package/oxidized/transform/print/comments/prettier/common/util.js +235 -0
  78. package/oxidized/transform/print/comments/prettier/language-js/comments.js +663 -0
  79. package/oxidized/transform/print/comments/prettier/language-js/loc.js +30 -0
  80. package/oxidized/transform/print/comments/prettier/language-js/printer-estree.js +23 -0
  81. package/oxidized/transform/print/comments/prettier/language-js/utils.js +89 -0
  82. package/oxidized/transform/print/comments/prettier/main/comments.js +374 -0
  83. package/oxidized/transform/print/comments/prettier/utils/get-last.js +5 -0
  84. package/oxidized/transform/print/detachedNodeTypes.js +1 -0
  85. package/oxidized/transform/print/detachedNodeTypes.js.flow +24 -0
  86. package/oxidized/transform/print/print.js +68 -0
  87. package/oxidized/transform/print/print.js.flow +87 -0
  88. package/oxidized/traverse/SimpleTraverser.js +90 -0
  89. package/oxidized/traverse/SimpleTraverser.js.flow +133 -0
  90. package/oxidized/traverse/getVisitorKeys.js +29 -0
  91. package/oxidized/traverse/getVisitorKeys.js.flow +36 -0
  92. package/oxidized/utils/Builders.js +181 -0
  93. package/oxidized/utils/Builders.js.flow +218 -0
  94. package/oxidized/utils/GenID.js +37 -0
  95. package/oxidized/utils/GenID.js.flow +39 -0
  96. package/oxidized/utils/createSyntaxError.js +15 -0
  97. package/oxidized/utils/createSyntaxError.js.flow +24 -0
  98. package/oxidized/utils/isReservedWord.js +53 -0
  99. package/oxidized/utils/isReservedWord.js.flow +57 -0
  100. package/oxidized/utils/mutateESTreeASTForPrettier.js +85 -0
  101. package/oxidized/utils/mutateESTreeASTForPrettier.js.flow +130 -0
  102. package/package.json +6 -4
@@ -0,0 +1,330 @@
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, Program} from 'flow-estree';
12
+ import type {DetachedNode, MaybeDetachedNode} from '../detachedNodeTypes';
13
+
14
+ // $FlowExpectedError[untyped-import]
15
+ import {attach as untypedAttach} from './prettier/main/comments';
16
+ // $FlowExpectedError[untyped-import]
17
+ import {locEnd, locStart} from './prettier/language-js/loc';
18
+ // $FlowExpectedError[untyped-import]
19
+ import printer from './prettier/language-js/printer-estree';
20
+ import {
21
+ // $FlowExpectedError[untyped-import]
22
+ addLeadingComment as untypedAddLeadingComment,
23
+ // $FlowExpectedError[untyped-import]
24
+ addTrailingComment as untypedAddTrailingComment,
25
+ // $FlowFixMe[untyped-import]
26
+ } from './prettier/common/util';
27
+ import {isBlockComment} from 'flow-estree';
28
+ import {EOL} from 'os';
29
+
30
+ export type Options = Readonly<{}>;
31
+
32
+ export enum CommentPlacement {
33
+ LEADING_OWN_LINE,
34
+ LEADING_INLINE,
35
+ TRAILING_OWN_LINE,
36
+ TRAILING_INLINE,
37
+ }
38
+
39
+ export function attachComments(
40
+ comments: ReadonlyArray<Comment>,
41
+ ast: Program,
42
+ text: string,
43
+ ): void {
44
+ untypedAttach(comments, ast, text, {
45
+ locStart,
46
+ locEnd,
47
+ printer,
48
+ });
49
+ }
50
+
51
+ export function mutateESTreeASTCommentsForPrettier(
52
+ program: Program,
53
+ text: string,
54
+ ): string {
55
+ let code = text;
56
+
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
+ delete program.comments;
62
+
63
+ // The docblock comment is never attached to any AST nodes, since its technically
64
+ // attached to the program. However this is specific to our AST and in order for
65
+ // prettier to correctly print it we need to attach it to the first node in the
66
+ // program body.
67
+ if (program.docblock != null && program.docblock.comment != null) {
68
+ const docblockComment = program.docblock.comment;
69
+
70
+ const isDocblockCommentNew = !isAttachedComment(docblockComment);
71
+ if (isDocblockCommentNew) {
72
+ // $FlowExpectedError[prop-missing]
73
+ docblockComment.printed = false;
74
+ // $FlowExpectedError[prop-missing]
75
+ docblockComment.leading = true;
76
+ // $FlowExpectedError[prop-missing]
77
+ docblockComment.trailing = false;
78
+ }
79
+
80
+ // If we have a first node in the program body, attach the comment to that
81
+ // otherwise set it on the program.
82
+ if (program.body.length > 0) {
83
+ const firstStatement = program.body[0];
84
+ const leadingComments = getLeadingCommentsForNode(firstStatement);
85
+ if (!leadingComments.includes(docblockComment)) {
86
+ setCommentsOnNode(firstStatement, [
87
+ docblockComment,
88
+ ...getCommentsForNode(firstStatement),
89
+ ]);
90
+
91
+ if (isDocblockCommentNew) {
92
+ // Add markers to the code block to ensure docblock comment is printed on its
93
+ // own line.
94
+ code = makeCommentOwnLine(code, docblockComment);
95
+ }
96
+ }
97
+ } else {
98
+ setCommentsOnNode(program, [docblockComment]);
99
+ }
100
+ }
101
+
102
+ // Should not be needed anymore
103
+ // $FlowExpectedError[cannot-write]
104
+ delete program.docblock;
105
+
106
+ return code;
107
+ }
108
+
109
+ export function moveCommentsToNewNode(
110
+ oldNode: ESNode,
111
+ newNode: DetachedNode<ESNode>,
112
+ ): void {
113
+ setCommentsOnNode(newNode, getCommentsForNode(oldNode));
114
+ setCommentsOnNode(oldNode, []);
115
+ }
116
+
117
+ export function cloneCommentsToNewNode(
118
+ oldNode: MaybeDetachedNode<ESNode>,
119
+ newNode: MaybeDetachedNode<ESNode>,
120
+ ): void {
121
+ setCommentsOnNode(
122
+ newNode,
123
+ getCommentsForNode(oldNode).map(comment =>
124
+ cloneCommentWithMarkers(comment),
125
+ ),
126
+ );
127
+ }
128
+
129
+ export function cloneJSDocCommentsToNewNode(
130
+ oldNode: ESNode,
131
+ newNode: MaybeDetachedNode<ESNode>,
132
+ ): void {
133
+ const comments = getCommentsForNode(oldNode).filter(comment => {
134
+ return (
135
+ isBlockComment(comment) &&
136
+ // JSDoc comments always start with an extra asterisk
137
+ comment.value.startsWith('*')
138
+ );
139
+ });
140
+ setCommentsOnNode(newNode, [
141
+ ...getCommentsForNode(newNode),
142
+ ...comments.map(cloneCommentWithMarkers),
143
+ ]);
144
+ }
145
+
146
+ export function setCommentsOnNode(
147
+ node: ESNode | DetachedNode<ESNode>,
148
+ comments: ReadonlyArray<Comment>,
149
+ ): void {
150
+ // $FlowExpectedError[prop-missing] - this property is secretly added by prettier.
151
+ // $FlowExpectedError[incompatible-use] - this property is secretly added by prettier.
152
+ // $FlowExpectedError[cannot-write] - this property is secretly added by prettier.
153
+ node.comments = comments;
154
+ }
155
+
156
+ export function getCommentsForNode(
157
+ node: ESNode | DetachedNode<ESNode>,
158
+ ): ReadonlyArray<Comment> {
159
+ // $FlowExpectedError[prop-missing] - this property is secretly added by prettier.
160
+ // $FlowExpectedError[incompatible-use] - this property is secretly added by prettier.
161
+ return node.comments ?? [];
162
+ }
163
+
164
+ export function isAttachedComment(comment: Comment): boolean {
165
+ // Prettier adds this property to comments that have been attached.
166
+ // $FlowExpectedError[prop-missing] - this property is secretly added by prettier.
167
+ return comment.printed === false;
168
+ }
169
+
170
+ export function isLeadingComment(comment: Comment): boolean {
171
+ // $FlowExpectedError[prop-missing] - this property is secretly added by prettier.
172
+ return comment.leading === true;
173
+ }
174
+ export function isTrailingComment(comment: Comment): boolean {
175
+ // $FlowExpectedError[prop-missing] - this property is secretly added by prettier.
176
+ return comment.trailing === true;
177
+ }
178
+
179
+ export function getLeadingCommentsForNode(
180
+ node: ESNode | DetachedNode<ESNode>,
181
+ ): ReadonlyArray<Comment> {
182
+ return getCommentsForNode(node).filter(isLeadingComment);
183
+ }
184
+
185
+ export function getTrailingCommentsForNode(
186
+ node: ESNode | DetachedNode<ESNode>,
187
+ ): ReadonlyArray<Comment> {
188
+ return getCommentsForNode(node).filter(isTrailingComment);
189
+ }
190
+
191
+ export function addComment(
192
+ node: ESNode | DetachedNode<ESNode>,
193
+ comment: Comment,
194
+ placement: CommentPlacement,
195
+ ): void {
196
+ switch (placement) {
197
+ case CommentPlacement.LEADING_OWN_LINE:
198
+ case CommentPlacement.LEADING_INLINE: {
199
+ untypedAddLeadingComment(node, comment);
200
+ break;
201
+ }
202
+ case CommentPlacement.TRAILING_OWN_LINE:
203
+ case CommentPlacement.TRAILING_INLINE: {
204
+ untypedAddTrailingComment(node, comment);
205
+ break;
206
+ }
207
+ }
208
+ }
209
+
210
+ export function cloneComment<T extends Comment>(comment: T): T {
211
+ // $FlowExpectedError[incompatible-type]
212
+ return {
213
+ type: comment.type,
214
+ value: comment.value,
215
+ loc: comment.loc,
216
+ range: comment.range,
217
+ };
218
+ }
219
+
220
+ export function cloneCommentWithMarkers<T extends Comment>(comment: T): T {
221
+ // $FlowExpectedError[incompatible-type]
222
+ return {
223
+ type: comment.type,
224
+ value: comment.value,
225
+ loc: comment.loc,
226
+ range: comment.range,
227
+ leading: isLeadingComment(comment),
228
+ trailing: isTrailingComment(comment),
229
+ };
230
+ }
231
+
232
+ function getFirstNewlineIndex(code: string): number {
233
+ return code.search(/\r\n|\n|\r/);
234
+ }
235
+
236
+ function getFirstNonWhitespaceIndex(code: string): number {
237
+ return code.search(/\S/);
238
+ }
239
+
240
+ export function makeCommentOwnLine(code: string, comment: Comment): string {
241
+ let newCode = code;
242
+ // Since we always want a line break we need to ensure a newline is found when
243
+ // searching out from either side of the comment range.
244
+ let firstNewline = getFirstNewlineIndex(code);
245
+ if (firstNewline === -1) {
246
+ // No newline in file, lets add one.
247
+ newCode += EOL;
248
+ firstNewline = newCode.length;
249
+ }
250
+
251
+ // Prettier only uses these ranges for detecting whitespace, so this nonsensical
252
+ // range is safe.
253
+ // $FlowExpectedError[cannot-write]
254
+ comment.range = [firstNewline + 1, firstNewline];
255
+
256
+ return newCode;
257
+ }
258
+
259
+ export function appendCommentToSource(
260
+ code: string,
261
+ comment: Comment,
262
+ placement: CommentPlacement,
263
+ ): string {
264
+ let newCode = code;
265
+ switch (comment.type) {
266
+ case 'Block': {
267
+ // Prettier decides if a newline is necessary between the comment and its node by looking
268
+ // to see if a newline seperates them in the source text. We can trick prettier into
269
+ // formatting how we want for new comments by placing the range such that a newline
270
+ // will (OWN_LINE) or will not (INLINE) be found when searching from the specified range
271
+ // position.
272
+ switch (placement) {
273
+ case CommentPlacement.LEADING_OWN_LINE:
274
+ case CommentPlacement.TRAILING_OWN_LINE: {
275
+ newCode = makeCommentOwnLine(code, comment);
276
+ break;
277
+ }
278
+ case CommentPlacement.LEADING_INLINE:
279
+ case CommentPlacement.TRAILING_INLINE: {
280
+ // Since we don't want a line break we need to ensure a non whitespace char is
281
+ // always found before a newline when searching out from either side of the
282
+ // comment range.
283
+ let firstNonWhitespace = getFirstNonWhitespaceIndex(code);
284
+ if (firstNonWhitespace === -1) {
285
+ // No non whitespace chars in file, lets add an identifiable statement for prettier to find.
286
+ newCode += '$FORCE_INLINE_ON_EMPTY_FILE_TOKEN$;';
287
+ firstNonWhitespace = newCode.length;
288
+ break;
289
+ }
290
+
291
+ // $FlowExpectedError[cannot-write]
292
+ comment.range = [firstNonWhitespace + 1, firstNonWhitespace];
293
+ break;
294
+ }
295
+ }
296
+ break;
297
+ }
298
+ case 'Line': {
299
+ // For `Line` comments prettier slices comments directly from the source code when printing
300
+ // https://github.com/prettier/prettier/blob/5f0ee39fa03532c85bd1c35291450fe7ac3667b3/src/language-js/print/comment.js#L15-L20
301
+ // this means that we need to have any appended comments directly in the
302
+ // source code or else prettier will slice nothing and bork up the transform
303
+ const commentText = `//${comment.value}`;
304
+
305
+ const lastChar = newCode[newCode.length - 1];
306
+ if (lastChar !== '\n' && lastChar !== '\r') {
307
+ newCode += EOL;
308
+ }
309
+
310
+ // Line comments cannot be inline before a node so we only place trailing Line comments inline.
311
+ if (placement === CommentPlacement.TRAILING_INLINE) {
312
+ // Prettier determines an "end of line" comment by walking backwards from
313
+ // the comment start range through the source code to see if it finds a non
314
+ // newline token. In order to trick prettier for new comments we need to
315
+ // insert fake source code for it to find.
316
+ newCode += '$FORCE_END_OF_LINE_COMMENT_TOKEN$;';
317
+ }
318
+ const start = newCode.length;
319
+ newCode += commentText;
320
+ const end = newCode.length;
321
+
322
+ // $FlowExpectedError[cannot-write]
323
+ comment.range = [start, end];
324
+
325
+ break;
326
+ }
327
+ }
328
+
329
+ return newCode;
330
+ }
@@ -0,0 +1,235 @@
1
+ 'use strict';
2
+
3
+ const stringWidth = require('string-width');
4
+
5
+ const getLast = require('../utils/get-last.js');
6
+
7
+ const notAsciiRegex = /[^\x20-\x7F]/;
8
+
9
+ function skip(chars) {
10
+ return (text, index, opts) => {
11
+ const backwards = opts && opts.backwards;
12
+
13
+ if (index === false) {
14
+ return false;
15
+ }
16
+
17
+ const {
18
+ length
19
+ } = text;
20
+ let cursor = index;
21
+
22
+ while (cursor >= 0 && cursor < length) {
23
+ const c = text.charAt(cursor);
24
+
25
+ if (chars instanceof RegExp) {
26
+ if (!chars.test(c)) {
27
+ return cursor;
28
+ }
29
+ } else if (!chars.includes(c)) {
30
+ return cursor;
31
+ }
32
+
33
+ backwards ? cursor-- : cursor++;
34
+ }
35
+
36
+ if (cursor === -1 || cursor === length) {
37
+ return cursor;
38
+ }
39
+
40
+ return false;
41
+ };
42
+ }
43
+
44
+ const skipWhitespace = skip(/\s/);
45
+ const skipSpaces = skip(' \t');
46
+ const skipToLineEnd = skip(',; \t');
47
+ const skipEverythingButNewLine = skip(/[^\n\r]/);
48
+
49
+ function skipInlineComment(text, index) {
50
+ if (index === false) {
51
+ return false;
52
+ }
53
+
54
+ if (text.charAt(index) === '/' && text.charAt(index + 1) === '*') {
55
+ for (let i = index + 2; i < text.length; ++i) {
56
+ if (text.charAt(i) === '*' && text.charAt(i + 1) === '/') {
57
+ return i + 2;
58
+ }
59
+ }
60
+ }
61
+
62
+ return index;
63
+ }
64
+
65
+ function skipTrailingComment(text, index) {
66
+ if (index === false) {
67
+ return false;
68
+ }
69
+
70
+ if (text.charAt(index) === '/' && text.charAt(index + 1) === '/') {
71
+ return skipEverythingButNewLine(text, index);
72
+ }
73
+
74
+ return index;
75
+ }
76
+
77
+ function skipNewline(text, index, opts) {
78
+ const backwards = opts && opts.backwards;
79
+
80
+ if (index === false) {
81
+ return false;
82
+ }
83
+
84
+ const atIndex = text.charAt(index);
85
+
86
+ if (backwards) {
87
+ if (text.charAt(index - 1) === '\r' && atIndex === '\n') {
88
+ return index - 2;
89
+ }
90
+
91
+ if (atIndex === '\n' || atIndex === '\r' || atIndex === '\u2028' || atIndex === '\u2029') {
92
+ return index - 1;
93
+ }
94
+ } else {
95
+ if (atIndex === '\r' && text.charAt(index + 1) === '\n') {
96
+ return index + 2;
97
+ }
98
+
99
+ if (atIndex === '\n' || atIndex === '\r' || atIndex === '\u2028' || atIndex === '\u2029') {
100
+ return index + 1;
101
+ }
102
+ }
103
+
104
+ return index;
105
+ }
106
+
107
+ function hasNewline(text, index, opts = {}) {
108
+ const idx = skipSpaces(text, opts.backwards ? index - 1 : index, opts);
109
+ const idx2 = skipNewline(text, idx, opts);
110
+ return idx !== idx2;
111
+ }
112
+
113
+ function hasNewlineInRange(text, start, end) {
114
+ for (let i = start; i < end; ++i) {
115
+ if (text.charAt(i) === '\n') {
116
+ return true;
117
+ }
118
+ }
119
+
120
+ return false;
121
+ }
122
+
123
+ function isNextLineEmptyAfterIndex(text, index) {
124
+ let oldIdx = null;
125
+ let idx = index;
126
+
127
+ while (idx !== oldIdx) {
128
+ oldIdx = idx;
129
+ idx = skipToLineEnd(text, idx);
130
+ idx = skipInlineComment(text, idx);
131
+ idx = skipSpaces(text, idx);
132
+ }
133
+
134
+ idx = skipTrailingComment(text, idx);
135
+ idx = skipNewline(text, idx);
136
+ return idx !== false && hasNewline(text, idx);
137
+ }
138
+
139
+ function getNextNonSpaceNonCommentCharacterIndexWithStartIndex(text, idx) {
140
+ let oldIdx = null;
141
+ let nextIdx = idx;
142
+
143
+ while (nextIdx !== oldIdx) {
144
+ oldIdx = nextIdx;
145
+ nextIdx = skipSpaces(text, nextIdx);
146
+ nextIdx = skipInlineComment(text, nextIdx);
147
+ nextIdx = skipTrailingComment(text, nextIdx);
148
+ nextIdx = skipNewline(text, nextIdx);
149
+ }
150
+
151
+ return nextIdx;
152
+ }
153
+
154
+ function getNextNonSpaceNonCommentCharacterIndex(text, node, locEnd) {
155
+ return getNextNonSpaceNonCommentCharacterIndexWithStartIndex(text, locEnd(node));
156
+ }
157
+
158
+ function getNextNonSpaceNonCommentCharacter(text, node, locEnd) {
159
+ return text.charAt(getNextNonSpaceNonCommentCharacterIndex(text, node, locEnd));
160
+ }
161
+
162
+ function getStringWidth(text) {
163
+ if (!text) {
164
+ return 0;
165
+ }
166
+
167
+ if (!notAsciiRegex.test(text)) {
168
+ return text.length;
169
+ }
170
+
171
+ return stringWidth(text);
172
+ }
173
+
174
+ function addCommentHelper(node, comment) {
175
+ const comments = node.comments || (node.comments = []);
176
+ comments.push(comment);
177
+ comment.printed = false;
178
+ comment.nodeDescription = describeNodeForDebugging(node);
179
+ }
180
+
181
+ function addLeadingComment(node, comment) {
182
+ comment.leading = true;
183
+ comment.trailing = false;
184
+ addCommentHelper(node, comment);
185
+ }
186
+
187
+ function addDanglingComment(node, comment, marker) {
188
+ comment.leading = false;
189
+ comment.trailing = false;
190
+
191
+ if (marker) {
192
+ comment.marker = marker;
193
+ }
194
+
195
+ addCommentHelper(node, comment);
196
+ }
197
+
198
+ function addTrailingComment(node, comment) {
199
+ comment.leading = false;
200
+ comment.trailing = true;
201
+ addCommentHelper(node, comment);
202
+ }
203
+
204
+ function isNonEmptyArray(object) {
205
+ return Array.isArray(object) && object.length > 0;
206
+ }
207
+
208
+ function describeNodeForDebugging(node) {
209
+ const nodeType = node.type || node.kind || '(unknown type)';
210
+ let nodeName = String(node.name || node.id && (typeof node.id === 'object' ? node.id.name : node.id) || node.key && (typeof node.key === 'object' ? node.key.name : node.key) || node.value && (typeof node.value === 'object' ? '' : String(node.value)) || node.operator || '');
211
+
212
+ if (nodeName.length > 20) {
213
+ nodeName = nodeName.slice(0, 19) + '…';
214
+ }
215
+
216
+ return nodeType + (nodeName ? ' ' + nodeName : '');
217
+ }
218
+
219
+ module.exports = {
220
+ getStringWidth,
221
+ getLast,
222
+ getNextNonSpaceNonCommentCharacterIndexWithStartIndex,
223
+ getNextNonSpaceNonCommentCharacterIndex,
224
+ getNextNonSpaceNonCommentCharacter,
225
+ skipWhitespace,
226
+ skipSpaces,
227
+ skipNewline,
228
+ isNextLineEmptyAfterIndex,
229
+ hasNewline,
230
+ hasNewlineInRange,
231
+ addLeadingComment,
232
+ addDanglingComment,
233
+ addTrailingComment,
234
+ isNonEmptyArray
235
+ };