@makano/rew 1.2.55 → 1.2.57

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1448 +0,0 @@
1
- // Generated by CoffeeScript 2.7.0
2
- (function () {
3
- // The CoffeeScript language has a good deal of optional syntax, implicit syntax,
4
- // and shorthand syntax. This can greatly complicate a grammar and bloat
5
- // the resulting parse table. Instead of making the parser handle it all, we take
6
- // a series of passes over the token stream, using this **Rewriter** to convert
7
- // shorthand into the unambiguous long form, add implicit indentation and
8
- // parentheses, and generally clean things up.
9
- var BALANCED_PAIRS,
10
- CALL_CLOSERS,
11
- CONTROL_IN_IMPLICIT,
12
- DISCARDED,
13
- EXPRESSION_CLOSE,
14
- EXPRESSION_END,
15
- EXPRESSION_START,
16
- IMPLICIT_CALL,
17
- IMPLICIT_END,
18
- IMPLICIT_FUNC,
19
- IMPLICIT_UNSPACED_CALL,
20
- INVERSES,
21
- LINEBREAKS,
22
- Rewriter,
23
- SINGLE_CLOSERS,
24
- SINGLE_LINERS,
25
- UNFINISHED,
26
- extractAllCommentTokens,
27
- generate,
28
- k,
29
- left,
30
- len,
31
- moveComments,
32
- right,
33
- throwSyntaxError,
34
- indexOf = [].indexOf,
35
- hasProp = {}.hasOwnProperty;
36
-
37
- ({ throwSyntaxError, extractAllCommentTokens } = require('./helpers'));
38
-
39
- // Move attached comments from one token to another.
40
- moveComments = function (fromToken, toToken) {
41
- var comment, k, len, ref, unshiftedComments;
42
- if (!fromToken.comments) {
43
- return;
44
- }
45
- if (toToken.comments && toToken.comments.length !== 0) {
46
- unshiftedComments = [];
47
- ref = fromToken.comments;
48
- for (k = 0, len = ref.length; k < len; k++) {
49
- comment = ref[k];
50
- if (comment.unshift) {
51
- unshiftedComments.push(comment);
52
- } else {
53
- toToken.comments.push(comment);
54
- }
55
- }
56
- toToken.comments = unshiftedComments.concat(toToken.comments);
57
- } else {
58
- toToken.comments = fromToken.comments;
59
- }
60
- return delete fromToken.comments;
61
- };
62
-
63
- // Create a generated token: one that exists due to a use of implicit syntax.
64
- // Optionally have this new token take the attached comments from another token.
65
- generate = function (tag, value, origin, commentsToken) {
66
- var token;
67
- token = [tag, value];
68
- token.generated = true;
69
- if (origin) {
70
- token.origin = origin;
71
- }
72
- if (commentsToken) {
73
- moveComments(commentsToken, token);
74
- }
75
- return token;
76
- };
77
-
78
- // The **Rewriter** class is used by the [Lexer](lexer.html), directly against
79
- // its internal array of tokens.
80
- exports.Rewriter = Rewriter = function () {
81
- class Rewriter {
82
- // Rewrite the token stream in multiple passes, one logical filter at
83
- // a time. This could certainly be changed into a single pass through the
84
- // stream, with a big ol’ efficient switch, but it’s much nicer to work with
85
- // like this. The order of these passes matters—indentation must be
86
- // corrected before implicit parentheses can be wrapped around blocks of code.
87
- rewrite(tokens1) {
88
- var ref, ref1, t;
89
- this.tokens = tokens1;
90
- // Set environment variable `DEBUG_TOKEN_STREAM` to `true` to output token
91
- // debugging info. Also set `DEBUG_REWRITTEN_TOKEN_STREAM` to `true` to
92
- // output the token stream after it has been rewritten by this file.
93
- if (typeof process !== 'undefined' && process !== null ? ((ref = process.env) != null ? ref.DEBUG_TOKEN_STREAM : void 0) : void 0) {
94
- if (process.env.DEBUG_REWRITTEN_TOKEN_STREAM) {
95
- console.log('Initial token stream:');
96
- }
97
- console.log(
98
- function () {
99
- var k, len, ref1, results;
100
- ref1 = this.tokens;
101
- results = [];
102
- for (k = 0, len = ref1.length; k < len; k++) {
103
- t = ref1[k];
104
- results.push(t[0] + '/' + t[1] + (t.comments ? '*' : ''));
105
- }
106
- return results;
107
- }
108
- .call(this)
109
- .join(' '),
110
- );
111
- }
112
- this.removeLeadingNewlines();
113
- this.closeOpenCalls();
114
- this.closeOpenIndexes();
115
- this.normalizeLines();
116
- this.tagPostfixConditionals();
117
- this.addImplicitBracesAndParens();
118
- this.rescueStowawayComments();
119
- this.addLocationDataToGeneratedTokens();
120
- this.enforceValidJSXAttributes();
121
- this.fixIndentationLocationData();
122
- this.exposeTokenDataToGrammar();
123
- if (
124
- typeof process !== 'undefined' && process !== null
125
- ? (ref1 = process.env) != null
126
- ? ref1.DEBUG_REWRITTEN_TOKEN_STREAM
127
- : void 0
128
- : void 0
129
- ) {
130
- if (process.env.DEBUG_TOKEN_STREAM) {
131
- console.log('Rewritten token stream:');
132
- }
133
- console.log(
134
- function () {
135
- var k, len, ref2, results;
136
- ref2 = this.tokens;
137
- results = [];
138
- for (k = 0, len = ref2.length; k < len; k++) {
139
- t = ref2[k];
140
- results.push(t[0] + '/' + t[1] + (t.comments ? '*' : ''));
141
- }
142
- return results;
143
- }
144
- .call(this)
145
- .join(' '),
146
- );
147
- }
148
- return this.tokens;
149
- }
150
-
151
- // Rewrite the token stream, looking one token ahead and behind.
152
- // Allow the return value of the block to tell us how many tokens to move
153
- // forwards (or backwards) in the stream, to make sure we don’t miss anything
154
- // as tokens are inserted and removed, and the stream changes length under
155
- // our feet.
156
- scanTokens(block) {
157
- var i, token, tokens;
158
- ({ tokens } = this);
159
- i = 0;
160
- while ((token = tokens[i])) {
161
- i += block.call(this, token, i, tokens);
162
- }
163
- return true;
164
- }
165
-
166
- detectEnd(i, condition, action, opts = {}) {
167
- var levels, ref, ref1, token, tokens;
168
- ({ tokens } = this);
169
- levels = 0;
170
- while ((token = tokens[i])) {
171
- if (levels === 0 && condition.call(this, token, i)) {
172
- return action.call(this, token, i);
173
- }
174
- if (((ref = token[0]), indexOf.call(EXPRESSION_START, ref) >= 0)) {
175
- levels += 1;
176
- } else if (((ref1 = token[0]), indexOf.call(EXPRESSION_END, ref1) >= 0)) {
177
- levels -= 1;
178
- }
179
- if (levels < 0) {
180
- if (opts.returnOnNegativeLevel) {
181
- return;
182
- }
183
- return action.call(this, token, i);
184
- }
185
- i += 1;
186
- }
187
- return i - 1;
188
- }
189
-
190
- // Leading newlines would introduce an ambiguity in the grammar, so we
191
- // dispatch them here.
192
- removeLeadingNewlines() {
193
- var i, k, l, leadingNewlineToken, len, len1, ref, ref1, tag;
194
- ref = this.tokens;
195
- for (i = k = 0, len = ref.length; k < len; i = ++k) {
196
- [tag] = ref[i];
197
- if (tag !== 'TERMINATOR') {
198
- // Find the index of the first non-`TERMINATOR` token.
199
- break;
200
- }
201
- }
202
- if (i === 0) {
203
- return;
204
- }
205
- ref1 = this.tokens.slice(0, i);
206
- // If there are any comments attached to the tokens we’re about to discard,
207
- // shift them forward to what will become the new first token.
208
- for (l = 0, len1 = ref1.length; l < len1; l++) {
209
- leadingNewlineToken = ref1[l];
210
- moveComments(leadingNewlineToken, this.tokens[i]);
211
- }
212
- // Discard all the leading newline tokens.
213
- return this.tokens.splice(0, i);
214
- }
215
-
216
- // The lexer has tagged the opening parenthesis of a method call. Match it with
217
- // its paired close.
218
- closeOpenCalls() {
219
- var action, condition;
220
- condition = function (token, i) {
221
- var ref;
222
- return (ref = token[0]) === ')' || ref === 'CALL_END';
223
- };
224
- action = function (token, i) {
225
- return (token[0] = 'CALL_END');
226
- };
227
- return this.scanTokens(function (token, i) {
228
- if (token[0] === 'CALL_START') {
229
- this.detectEnd(i + 1, condition, action);
230
- }
231
- return 1;
232
- });
233
- }
234
-
235
- // The lexer has tagged the opening bracket of an indexing operation call.
236
- // Match it with its paired close.
237
- closeOpenIndexes() {
238
- var action, condition, startToken;
239
- startToken = null;
240
- condition = function (token, i) {
241
- var ref;
242
- return (ref = token[0]) === ']' || ref === 'INDEX_END';
243
- };
244
- action = function (token, i) {
245
- if (this.tokens.length >= i && this.tokens[i + 1][0] === ':') {
246
- startToken[0] = '[';
247
- return (token[0] = ']');
248
- } else {
249
- return (token[0] = 'INDEX_END');
250
- }
251
- };
252
- return this.scanTokens(function (token, i) {
253
- if (token[0] === 'INDEX_START') {
254
- startToken = token;
255
- this.detectEnd(i + 1, condition, action);
256
- }
257
- return 1;
258
- });
259
- }
260
-
261
- // Match tags in token stream starting at `i` with `pattern`.
262
- // `pattern` may consist of strings (equality), an array of strings (one of)
263
- // or null (wildcard). Returns the index of the match or -1 if no match.
264
- indexOfTag(i, ...pattern) {
265
- var fuzz, j, k, ref, ref1;
266
- fuzz = 0;
267
- for (j = k = 0, ref = pattern.length; 0 <= ref ? k < ref : k > ref; j = 0 <= ref ? ++k : --k) {
268
- if (pattern[j] == null) {
269
- continue;
270
- }
271
- if (typeof pattern[j] === 'string') {
272
- pattern[j] = [pattern[j]];
273
- }
274
- if (((ref1 = this.tag(i + j + fuzz)), indexOf.call(pattern[j], ref1) < 0)) {
275
- return -1;
276
- }
277
- }
278
- return i + j + fuzz - 1;
279
- }
280
-
281
- // Returns `yes` if standing in front of something looking like
282
- // `@<x>:`, `<x>:` or `<EXPRESSION_START><x>...<EXPRESSION_END>:`.
283
- looksObjectish(j) {
284
- var end, index;
285
- if (this.indexOfTag(j, '@', null, ':') !== -1 || this.indexOfTag(j, null, ':') !== -1) {
286
- return true;
287
- }
288
- index = this.indexOfTag(j, EXPRESSION_START);
289
- if (index !== -1) {
290
- end = null;
291
- this.detectEnd(
292
- index + 1,
293
- function (token) {
294
- var ref;
295
- return (ref = token[0]), indexOf.call(EXPRESSION_END, ref) >= 0;
296
- },
297
- function (token, i) {
298
- return (end = i);
299
- },
300
- );
301
- if (this.tag(end + 1) === ':') {
302
- return true;
303
- }
304
- }
305
- return false;
306
- }
307
-
308
- // Returns `yes` if current line of tokens contain an element of tags on same
309
- // expression level. Stop searching at `LINEBREAKS` or explicit start of
310
- // containing balanced expression.
311
- findTagsBackwards(i, tags) {
312
- var backStack, ref, ref1, ref2, ref3, ref4, ref5;
313
- backStack = [];
314
- while (
315
- i >= 0 &&
316
- (backStack.length ||
317
- (((ref2 = this.tag(i)), indexOf.call(tags, ref2) < 0) &&
318
- (((ref3 = this.tag(i)), indexOf.call(EXPRESSION_START, ref3) < 0) || this.tokens[i].generated) &&
319
- ((ref4 = this.tag(i)), indexOf.call(LINEBREAKS, ref4) < 0)))
320
- ) {
321
- if (((ref = this.tag(i)), indexOf.call(EXPRESSION_END, ref) >= 0)) {
322
- backStack.push(this.tag(i));
323
- }
324
- if (((ref1 = this.tag(i)), indexOf.call(EXPRESSION_START, ref1) >= 0) && backStack.length) {
325
- backStack.pop();
326
- }
327
- i -= 1;
328
- }
329
- return (ref5 = this.tag(i)), indexOf.call(tags, ref5) >= 0;
330
- }
331
-
332
- // Look for signs of implicit calls and objects in the token stream and
333
- // add them.
334
- addImplicitBracesAndParens() {
335
- var stack, start;
336
- // Track current balancing depth (both implicit and explicit) on stack.
337
- stack = [];
338
- start = null;
339
- return this.scanTokens(function (token, i, tokens) {
340
- var endImplicitCall,
341
- endImplicitObject,
342
- forward,
343
- implicitObjectContinues,
344
- implicitObjectIndent,
345
- inControlFlow,
346
- inImplicit,
347
- inImplicitCall,
348
- inImplicitControl,
349
- inImplicitObject,
350
- isImplicit,
351
- isImplicitCall,
352
- isImplicitObject,
353
- k,
354
- newLine,
355
- nextTag,
356
- nextToken,
357
- offset,
358
- preContinuationLineIndent,
359
- preObjectToken,
360
- prevTag,
361
- prevToken,
362
- ref,
363
- ref1,
364
- ref2,
365
- ref3,
366
- ref4,
367
- ref5,
368
- s,
369
- sameLine,
370
- stackIdx,
371
- stackItem,
372
- stackNext,
373
- stackTag,
374
- stackTop,
375
- startIdx,
376
- startImplicitCall,
377
- startImplicitObject,
378
- startIndex,
379
- startTag,
380
- startsLine,
381
- tag;
382
- [tag] = token;
383
- [prevTag] = prevToken = i > 0 ? tokens[i - 1] : [];
384
- [nextTag] = nextToken = i < tokens.length - 1 ? tokens[i + 1] : [];
385
- stackTop = function () {
386
- return stack[stack.length - 1];
387
- };
388
- startIdx = i;
389
- // Helper function, used for keeping track of the number of tokens consumed
390
- // and spliced, when returning for getting a new token.
391
- forward = function (n) {
392
- return i - startIdx + n;
393
- };
394
- // Helper functions
395
- isImplicit = function (stackItem) {
396
- var ref;
397
- return stackItem != null ? ((ref = stackItem[2]) != null ? ref.ours : void 0) : void 0;
398
- };
399
- isImplicitObject = function (stackItem) {
400
- return isImplicit(stackItem) && (stackItem != null ? stackItem[0] : void 0) === '{';
401
- };
402
- isImplicitCall = function (stackItem) {
403
- return isImplicit(stackItem) && (stackItem != null ? stackItem[0] : void 0) === '(';
404
- };
405
- inImplicit = function () {
406
- return isImplicit(stackTop());
407
- };
408
- inImplicitCall = function () {
409
- return isImplicitCall(stackTop());
410
- };
411
- inImplicitObject = function () {
412
- return isImplicitObject(stackTop());
413
- };
414
- // Unclosed control statement inside implicit parens (like
415
- // class declaration or if-conditionals).
416
- inImplicitControl = function () {
417
- var ref;
418
- return inImplicit() && ((ref = stackTop()) != null ? ref[0] : void 0) === 'CONTROL';
419
- };
420
- startImplicitCall = function (idx) {
421
- stack.push([
422
- '(',
423
- idx,
424
- {
425
- ours: true,
426
- },
427
- ]);
428
- return tokens.splice(idx, 0, generate('CALL_START', '(', ['', 'implicit function call', token[2]], prevToken));
429
- };
430
- endImplicitCall = function () {
431
- stack.pop();
432
- tokens.splice(i, 0, generate('CALL_END', ')', ['', 'end of input', token[2]], prevToken));
433
- return (i += 1);
434
- };
435
- startImplicitObject = function (idx, { startsLine = true, continuationLineIndent } = {}) {
436
- var val;
437
- stack.push([
438
- '{',
439
- idx,
440
- {
441
- sameLine: true,
442
- startsLine: startsLine,
443
- ours: true,
444
- continuationLineIndent: continuationLineIndent,
445
- },
446
- ]);
447
- val = new String('{');
448
- val.generated = true;
449
- return tokens.splice(idx, 0, generate('{', val, token, prevToken));
450
- };
451
- endImplicitObject = function (j) {
452
- j = j != null ? j : i;
453
- stack.pop();
454
- tokens.splice(j, 0, generate('}', '}', token, prevToken));
455
- return (i += 1);
456
- };
457
- implicitObjectContinues = (j) => {
458
- var nextTerminatorIdx;
459
- nextTerminatorIdx = null;
460
- this.detectEnd(
461
- j,
462
- function (token) {
463
- return token[0] === 'TERMINATOR';
464
- },
465
- function (token, i) {
466
- return (nextTerminatorIdx = i);
467
- },
468
- {
469
- returnOnNegativeLevel: true,
470
- },
471
- );
472
- if (nextTerminatorIdx == null) {
473
- return false;
474
- }
475
- return this.looksObjectish(nextTerminatorIdx + 1);
476
- };
477
- // Don’t end an implicit call/object on next indent if any of these are in an argument/value.
478
- if (
479
- ((inImplicitCall() || inImplicitObject()) && indexOf.call(CONTROL_IN_IMPLICIT, tag) >= 0) ||
480
- (inImplicitObject() && prevTag === ':' && tag === 'FOR')
481
- ) {
482
- stack.push([
483
- 'CONTROL',
484
- i,
485
- {
486
- ours: true,
487
- },
488
- ]);
489
- return forward(1);
490
- }
491
- if (tag === 'INDENT' && inImplicit()) {
492
- // An `INDENT` closes an implicit call unless
493
-
494
- // 1. We have seen a `CONTROL` argument on the line.
495
- // 2. The last token before the indent is part of the list below.
496
- if (
497
- prevTag !== '=>' &&
498
- prevTag !== '->' &&
499
- prevTag !== '[' &&
500
- prevTag !== '(' &&
501
- prevTag !== ',' &&
502
- prevTag !== '{' &&
503
- prevTag !== 'ELSE' &&
504
- prevTag !== '='
505
- ) {
506
- while (inImplicitCall() || (inImplicitObject() && prevTag !== ':')) {
507
- if (inImplicitCall()) {
508
- endImplicitCall();
509
- } else {
510
- endImplicitObject();
511
- }
512
- }
513
- }
514
- if (inImplicitControl()) {
515
- stack.pop();
516
- }
517
- stack.push([tag, i]);
518
- return forward(1);
519
- }
520
- // Straightforward start of explicit expression.
521
- if (indexOf.call(EXPRESSION_START, tag) >= 0) {
522
- stack.push([tag, i]);
523
- return forward(1);
524
- }
525
- // Close all implicit expressions inside of explicitly closed expressions.
526
- if (indexOf.call(EXPRESSION_END, tag) >= 0) {
527
- while (inImplicit()) {
528
- if (inImplicitCall()) {
529
- endImplicitCall();
530
- } else if (inImplicitObject()) {
531
- endImplicitObject();
532
- } else {
533
- stack.pop();
534
- }
535
- }
536
- start = stack.pop();
537
- }
538
- inControlFlow = () => {
539
- var controlFlow, isFunc, seenFor, tagCurrentLine;
540
- seenFor = this.findTagsBackwards(i, ['FOR']) && this.findTagsBackwards(i, ['FORIN', 'FOROF', 'FORFROM']);
541
- controlFlow = seenFor || this.findTagsBackwards(i, ['WHILE', 'UNTIL', 'LOOP', 'LEADING_WHEN']);
542
- if (!controlFlow) {
543
- return false;
544
- }
545
- isFunc = false;
546
- tagCurrentLine = token[2].first_line;
547
- this.detectEnd(
548
- i,
549
- function (token, i) {
550
- var ref;
551
- return (ref = token[0]), indexOf.call(LINEBREAKS, ref) >= 0;
552
- },
553
- function (token, i) {
554
- var first_line;
555
- [prevTag, , { first_line }] = tokens[i - 1] || [];
556
- return (isFunc = tagCurrentLine === first_line && (prevTag === '->' || prevTag === '=>'));
557
- },
558
- {
559
- returnOnNegativeLevel: true,
560
- },
561
- );
562
- return isFunc;
563
- };
564
- // Recognize standard implicit calls like
565
- // f a, f() b, f? c, h[0] d etc.
566
- // Added support for spread dots on the left side: f ...a
567
- if (
568
- ((indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced) || (tag === '?' && i > 0 && !tokens[i - 1].spaced)) &&
569
- (indexOf.call(IMPLICIT_CALL, nextTag) >= 0 ||
570
- (nextTag === '...' &&
571
- ((ref = this.tag(i + 2)), indexOf.call(IMPLICIT_CALL, ref) >= 0) &&
572
- !this.findTagsBackwards(i, ['INDEX_START', '['])) ||
573
- (indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !nextToken.spaced && !nextToken.newLine)) &&
574
- !inControlFlow()
575
- ) {
576
- if (tag === '?') {
577
- tag = token[0] = 'FUNC_EXIST';
578
- }
579
- startImplicitCall(i + 1);
580
- return forward(2);
581
- }
582
- // Implicit call taking an implicit indented object as first argument.
583
-
584
- // f
585
- // a: b
586
- // c: d
587
-
588
- // Don’t accept implicit calls of this type, when on the same line
589
- // as the control structures below as that may misinterpret constructs like:
590
-
591
- // if f
592
- // a: 1
593
- // as
594
-
595
- // if f(a: 1)
596
-
597
- // which is probably always unintended.
598
- // Furthermore don’t allow this in the first line of a literal array
599
- // or explicit object, as that creates grammatical ambiguities (#5368).
600
- if (
601
- indexOf.call(IMPLICIT_FUNC, tag) >= 0 &&
602
- this.indexOfTag(i + 1, 'INDENT') > -1 &&
603
- this.looksObjectish(i + 2) &&
604
- !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL']) &&
605
- !(
606
- ((ref1 = s = (ref2 = stackTop()) != null ? ref2[0] : void 0) === '{' || ref1 === '[') &&
607
- !isImplicit(stackTop()) &&
608
- this.findTagsBackwards(i, s)
609
- )
610
- ) {
611
- startImplicitCall(i + 1);
612
- stack.push(['INDENT', i + 2]);
613
- return forward(3);
614
- }
615
- // Implicit objects start here.
616
- if (tag === ':') {
617
- // Go back to the (implicit) start of the object.
618
- s = function () {
619
- var ref3;
620
- switch (false) {
621
- case ((ref3 = this.tag(i - 1)), indexOf.call(EXPRESSION_END, ref3) < 0):
622
- [startTag, startIndex] = start;
623
- if (startTag === '[' && startIndex > 0 && this.tag(startIndex - 1) === '@' && !tokens[startIndex - 1].spaced) {
624
- return startIndex - 1;
625
- } else {
626
- return startIndex;
627
- }
628
- break;
629
- case this.tag(i - 2) !== '@':
630
- return i - 2;
631
- default:
632
- return i - 1;
633
- }
634
- }.call(this);
635
- startsLine = s <= 0 || ((ref3 = this.tag(s - 1)), indexOf.call(LINEBREAKS, ref3) >= 0) || tokens[s - 1].newLine;
636
- // Are we just continuing an already declared object?
637
- // Including the case where we indent on the line after an explicit '{'.
638
- if (stackTop()) {
639
- [stackTag, stackIdx] = stackTop();
640
- stackNext = stack[stack.length - 2];
641
- if (
642
- (stackTag === '{' ||
643
- (stackTag === 'INDENT' &&
644
- (stackNext != null ? stackNext[0] : void 0) === '{' &&
645
- !isImplicit(stackNext) &&
646
- this.findTagsBackwards(stackIdx - 1, ['{']))) &&
647
- (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{') &&
648
- ((ref4 = this.tag(s - 1)), indexOf.call(UNFINISHED, ref4) < 0)
649
- ) {
650
- return forward(1);
651
- }
652
- }
653
- preObjectToken = i > 1 ? tokens[i - 2] : [];
654
- startImplicitObject(s, {
655
- startsLine: !!startsLine,
656
- continuationLineIndent: preObjectToken.continuationLineIndent,
657
- });
658
- return forward(2);
659
- }
660
- // End implicit calls when chaining method calls
661
- // like e.g.:
662
-
663
- // f ->
664
- // a
665
- // .g b, ->
666
- // c
667
- // .h a
668
-
669
- // and also
670
-
671
- // f a
672
- // .g b
673
- // .h a
674
-
675
- // Mark all enclosing objects as not sameLine
676
- if (indexOf.call(LINEBREAKS, tag) >= 0) {
677
- for (k = stack.length - 1; k >= 0; k += -1) {
678
- stackItem = stack[k];
679
- if (!isImplicit(stackItem)) {
680
- break;
681
- }
682
- if (isImplicitObject(stackItem)) {
683
- stackItem[2].sameLine = false;
684
- }
685
- }
686
- }
687
- // End indented-continuation-line implicit objects once that indentation is over.
688
- if (tag === 'TERMINATOR' && token.endsContinuationLineIndentation) {
689
- ({ preContinuationLineIndent } = token.endsContinuationLineIndentation);
690
- while (
691
- inImplicitObject() &&
692
- (implicitObjectIndent = stackTop()[2].continuationLineIndent) != null &&
693
- implicitObjectIndent > preContinuationLineIndent
694
- ) {
695
- endImplicitObject();
696
- }
697
- }
698
- newLine = prevTag === 'OUTDENT' || prevToken.newLine;
699
- if (
700
- indexOf.call(IMPLICIT_END, tag) >= 0 ||
701
- (indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) ||
702
- ((tag === '..' || tag === '...') && this.findTagsBackwards(i, ['INDEX_START']))
703
- ) {
704
- while (inImplicit()) {
705
- [stackTag, stackIdx, { sameLine, startsLine }] = stackTop();
706
- // Close implicit calls when reached end of argument list
707
- if ((inImplicitCall() && prevTag !== ',') || (prevTag === ',' && tag === 'TERMINATOR' && nextTag == null)) {
708
- endImplicitCall();
709
- // Close implicit objects such as:
710
- // return a: 1, b: 2 unless true
711
- } else if (
712
- inImplicitObject() &&
713
- sameLine &&
714
- tag !== 'TERMINATOR' &&
715
- prevTag !== ':' &&
716
- !(
717
- (tag === 'POST_IF' || tag === 'FOR' || tag === 'WHILE' || tag === 'UNTIL') &&
718
- startsLine &&
719
- implicitObjectContinues(i + 1)
720
- )
721
- ) {
722
- endImplicitObject();
723
- // Close implicit objects when at end of line, line didn't end with a comma
724
- // and the implicit object didn't start the line or the next line doesn’t look like
725
- // the continuation of an object.
726
- } else if (inImplicitObject() && tag === 'TERMINATOR' && prevTag !== ',' && !(startsLine && this.looksObjectish(i + 1))) {
727
- endImplicitObject();
728
- } else if (inImplicitControl() && tokens[stackTop()[1]][0] === 'CLASS' && tag === 'TERMINATOR') {
729
- stack.pop();
730
- } else {
731
- break;
732
- }
733
- }
734
- }
735
- // Close implicit object if comma is the last character
736
- // and what comes after doesn’t look like it belongs.
737
- // This is used for trailing commas and calls, like:
738
-
739
- // x =
740
- // a: b,
741
- // c: d,
742
- // e = 2
743
-
744
- // and
745
-
746
- // f a, b: c, d: e, f, g: h: i, j
747
-
748
- if (
749
- tag === ',' &&
750
- !this.looksObjectish(i + 1) &&
751
- inImplicitObject() &&
752
- !((ref5 = this.tag(i + 2)) === 'FOROF' || ref5 === 'FORIN') &&
753
- (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))
754
- ) {
755
- // When nextTag is OUTDENT the comma is insignificant and
756
- // should just be ignored so embed it in the implicit object.
757
-
758
- // When it isn’t the comma go on to play a role in a call or
759
- // array further up the stack, so give it a chance.
760
- offset = nextTag === 'OUTDENT' ? 1 : 0;
761
- while (inImplicitObject()) {
762
- endImplicitObject(i + offset);
763
- }
764
- }
765
- return forward(1);
766
- });
767
- }
768
-
769
- // Make sure only strings and wrapped expressions are used in JSX attributes.
770
- enforceValidJSXAttributes() {
771
- return this.scanTokens(function (token, i, tokens) {
772
- var next, ref;
773
- if (token.jsxColon) {
774
- next = tokens[i + 1];
775
- if ((ref = next[0]) !== 'STRING_START' && ref !== 'STRING' && ref !== '(') {
776
- throwSyntaxError('expected wrapped or quoted JSX attribute', next[2]);
777
- }
778
- }
779
- return 1;
780
- });
781
- }
782
-
783
- // Not all tokens survive processing by the parser. To avoid comments getting
784
- // lost into the ether, find comments attached to doomed tokens and move them
785
- // to a token that will make it to the other side.
786
- rescueStowawayComments() {
787
- var dontShiftForward, insertPlaceholder, shiftCommentsBackward, shiftCommentsForward;
788
- insertPlaceholder = function (token, j, tokens, method) {
789
- if (tokens[j][0] !== 'TERMINATOR') {
790
- tokens[method](generate('TERMINATOR', '\n', tokens[j]));
791
- }
792
- return tokens[method](generate('JS', '', tokens[j], token));
793
- };
794
- dontShiftForward = function (i, tokens) {
795
- var j, ref;
796
- j = i + 1;
797
- while (j !== tokens.length && ((ref = tokens[j][0]), indexOf.call(DISCARDED, ref) >= 0)) {
798
- if (tokens[j][0] === 'INTERPOLATION_END') {
799
- return true;
800
- }
801
- j++;
802
- }
803
- return false;
804
- };
805
- shiftCommentsForward = function (token, i, tokens) {
806
- var comment, j, k, len, ref, ref1, ref2;
807
- // Find the next surviving token and attach this token’s comments to it,
808
- // with a flag that we know to output such comments *before* that
809
- // token’s own compilation. (Otherwise comments are output following
810
- // the token they’re attached to.)
811
- j = i;
812
- while (j !== tokens.length && ((ref = tokens[j][0]), indexOf.call(DISCARDED, ref) >= 0)) {
813
- j++;
814
- }
815
- if (!(j === tokens.length || ((ref1 = tokens[j][0]), indexOf.call(DISCARDED, ref1) >= 0))) {
816
- ref2 = token.comments;
817
- for (k = 0, len = ref2.length; k < len; k++) {
818
- comment = ref2[k];
819
- comment.unshift = true;
820
- }
821
- moveComments(token, tokens[j]);
822
- return 1; // All following tokens are doomed!
823
- } else {
824
- j = tokens.length - 1;
825
- insertPlaceholder(token, j, tokens, 'push');
826
- // The generated tokens were added to the end, not inline, so we don’t skip.
827
- return 1;
828
- }
829
- };
830
- shiftCommentsBackward = function (token, i, tokens) {
831
- var j, ref, ref1;
832
- // Find the last surviving token and attach this token’s comments to it.
833
- j = i;
834
- while (j !== -1 && ((ref = tokens[j][0]), indexOf.call(DISCARDED, ref) >= 0)) {
835
- j--;
836
- }
837
- if (!(j === -1 || ((ref1 = tokens[j][0]), indexOf.call(DISCARDED, ref1) >= 0))) {
838
- moveComments(token, tokens[j]);
839
- return 1; // All previous tokens are doomed!
840
- } else {
841
- insertPlaceholder(token, 0, tokens, 'unshift');
842
- // We added two tokens, so shift forward to account for the insertion.
843
- return 3;
844
- }
845
- };
846
- return this.scanTokens(function (token, i, tokens) {
847
- var dummyToken, j, ref, ref1, ret;
848
- if (!token.comments) {
849
- return 1;
850
- }
851
- ret = 1;
852
- if (((ref = token[0]), indexOf.call(DISCARDED, ref) >= 0)) {
853
- // This token won’t survive passage through the parser, so we need to
854
- // rescue its attached tokens and redistribute them to nearby tokens.
855
- // Comments that don’t start a new line can shift backwards to the last
856
- // safe token, while other tokens should shift forward.
857
- dummyToken = {
858
- comments: [],
859
- };
860
- j = token.comments.length - 1;
861
- while (j !== -1) {
862
- if (token.comments[j].newLine === false && token.comments[j].here === false) {
863
- dummyToken.comments.unshift(token.comments[j]);
864
- token.comments.splice(j, 1);
865
- }
866
- j--;
867
- }
868
- if (dummyToken.comments.length !== 0) {
869
- ret = shiftCommentsBackward(dummyToken, i - 1, tokens);
870
- }
871
- if (token.comments.length !== 0) {
872
- shiftCommentsForward(token, i, tokens);
873
- }
874
- } else if (!dontShiftForward(i, tokens)) {
875
- // If any of this token’s comments start a line—there’s only
876
- // whitespace between the preceding newline and the start of the
877
- // comment—and this isn’t one of the special `JS` tokens, then
878
- // shift this comment forward to precede the next valid token.
879
- // `Block.compileComments` also has logic to make sure that
880
- // “starting new line” comments follow or precede the nearest
881
- // newline relative to the token that the comment is attached to,
882
- // but that newline might be inside a `}` or `)` or other generated
883
- // token that we really want this comment to output after. Therefore
884
- // we need to shift the comments here, avoiding such generated and
885
- // discarded tokens.
886
- dummyToken = {
887
- comments: [],
888
- };
889
- j = token.comments.length - 1;
890
- while (j !== -1) {
891
- if (token.comments[j].newLine && !token.comments[j].unshift && !(token[0] === 'JS' && token.generated)) {
892
- dummyToken.comments.unshift(token.comments[j]);
893
- token.comments.splice(j, 1);
894
- }
895
- j--;
896
- }
897
- if (dummyToken.comments.length !== 0) {
898
- ret = shiftCommentsForward(dummyToken, i + 1, tokens);
899
- }
900
- }
901
- if (((ref1 = token.comments) != null ? ref1.length : void 0) === 0) {
902
- delete token.comments;
903
- }
904
- return ret;
905
- });
906
- }
907
-
908
- // Add location data to all tokens generated by the rewriter.
909
- addLocationDataToGeneratedTokens() {
910
- return this.scanTokens(function (token, i, tokens) {
911
- var column, line, nextLocation, prevLocation, rangeIndex, ref, ref1;
912
- if (token[2]) {
913
- return 1;
914
- }
915
- if (!(token.generated || token.explicit)) {
916
- return 1;
917
- }
918
- if (token.fromThen && token[0] === 'INDENT') {
919
- token[2] = token.origin[2];
920
- return 1;
921
- }
922
- if (token[0] === '{' && (nextLocation = (ref = tokens[i + 1]) != null ? ref[2] : void 0)) {
923
- ({
924
- first_line: line,
925
- first_column: column,
926
- range: [rangeIndex],
927
- } = nextLocation);
928
- } else if ((prevLocation = (ref1 = tokens[i - 1]) != null ? ref1[2] : void 0)) {
929
- ({
930
- last_line: line,
931
- last_column: column,
932
- range: [, rangeIndex],
933
- } = prevLocation);
934
- column += 1;
935
- } else {
936
- line = column = 0;
937
- rangeIndex = 0;
938
- }
939
- token[2] = {
940
- first_line: line,
941
- first_column: column,
942
- last_line: line,
943
- last_column: column,
944
- last_line_exclusive: line,
945
- last_column_exclusive: column,
946
- range: [rangeIndex, rangeIndex],
947
- };
948
- return 1;
949
- });
950
- }
951
-
952
- // `OUTDENT` tokens should always be positioned at the last character of the
953
- // previous token, so that AST nodes ending in an `OUTDENT` token end up with a
954
- // location corresponding to the last “real” token under the node.
955
- fixIndentationLocationData() {
956
- var findPrecedingComment;
957
- if (this.allComments == null) {
958
- this.allComments = extractAllCommentTokens(this.tokens);
959
- }
960
- findPrecedingComment = (token, { afterPosition, indentSize, first, indented }) => {
961
- var comment, k, l, lastMatching, matches, ref, ref1, tokenStart;
962
- tokenStart = token[2].range[0];
963
- matches = function (comment) {
964
- if (comment.outdented) {
965
- if (!(indentSize != null && comment.indentSize > indentSize)) {
966
- return false;
967
- }
968
- }
969
- if (indented && !comment.indented) {
970
- return false;
971
- }
972
- if (!(comment.locationData.range[0] < tokenStart)) {
973
- return false;
974
- }
975
- if (!(comment.locationData.range[0] > afterPosition)) {
976
- return false;
977
- }
978
- return true;
979
- };
980
- if (first) {
981
- lastMatching = null;
982
- ref = this.allComments;
983
- for (k = ref.length - 1; k >= 0; k += -1) {
984
- comment = ref[k];
985
- if (matches(comment)) {
986
- lastMatching = comment;
987
- } else if (lastMatching) {
988
- return lastMatching;
989
- }
990
- }
991
- return lastMatching;
992
- }
993
- ref1 = this.allComments;
994
- for (l = ref1.length - 1; l >= 0; l += -1) {
995
- comment = ref1[l];
996
- if (matches(comment)) {
997
- return comment;
998
- }
999
- }
1000
- return null;
1001
- };
1002
- return this.scanTokens(function (token, i, tokens) {
1003
- var isIndent, nextToken, nextTokenIndex, precedingComment, prevLocationData, prevToken, ref, ref1, ref2, useNextToken;
1004
- if (
1005
- !(
1006
- (ref = token[0]) === 'INDENT' ||
1007
- ref === 'OUTDENT' ||
1008
- (token.generated && token[0] === 'CALL_END' && !((ref1 = token.data) != null ? ref1.closingTagNameToken : void 0)) ||
1009
- (token.generated && token[0] === '}')
1010
- )
1011
- ) {
1012
- return 1;
1013
- }
1014
- isIndent = token[0] === 'INDENT';
1015
- prevToken = (ref2 = token.prevToken) != null ? ref2 : tokens[i - 1];
1016
- prevLocationData = prevToken[2];
1017
- // addLocationDataToGeneratedTokens() set the outdent’s location data
1018
- // to the preceding token’s, but in order to detect comments inside an
1019
- // empty "block" we want to look for comments preceding the next token.
1020
- useNextToken = token.explicit || token.generated;
1021
- if (useNextToken) {
1022
- nextToken = token;
1023
- nextTokenIndex = i;
1024
- while ((nextToken.explicit || nextToken.generated) && nextTokenIndex !== tokens.length - 1) {
1025
- nextToken = tokens[nextTokenIndex++];
1026
- }
1027
- }
1028
- precedingComment = findPrecedingComment(useNextToken ? nextToken : token, {
1029
- afterPosition: prevLocationData.range[0],
1030
- indentSize: token.indentSize,
1031
- first: isIndent,
1032
- indented: useNextToken,
1033
- });
1034
- if (isIndent) {
1035
- if (!(precedingComment != null ? precedingComment.newLine : void 0)) {
1036
- return 1;
1037
- }
1038
- }
1039
- if (token.generated && token[0] === 'CALL_END' && (precedingComment != null ? precedingComment.indented : void 0)) {
1040
- // We don’t want e.g. an implicit call at the end of an `if` condition to
1041
- // include a following indented comment.
1042
- return 1;
1043
- }
1044
- if (precedingComment != null) {
1045
- prevLocationData = precedingComment.locationData;
1046
- }
1047
- token[2] = {
1048
- first_line: precedingComment != null ? prevLocationData.first_line : prevLocationData.last_line,
1049
- first_column: precedingComment != null ? (isIndent ? 0 : prevLocationData.first_column) : prevLocationData.last_column,
1050
- last_line: prevLocationData.last_line,
1051
- last_column: prevLocationData.last_column,
1052
- last_line_exclusive: prevLocationData.last_line_exclusive,
1053
- last_column_exclusive: prevLocationData.last_column_exclusive,
1054
- range:
1055
- isIndent && precedingComment != null
1056
- ? [prevLocationData.range[0] - precedingComment.indentSize, prevLocationData.range[1]]
1057
- : prevLocationData.range,
1058
- };
1059
- return 1;
1060
- });
1061
- }
1062
-
1063
- // Because our grammar is LALR(1), it can’t handle some single-line
1064
- // expressions that lack ending delimiters. The **Rewriter** adds the implicit
1065
- // blocks, so it doesn’t need to. To keep the grammar clean and tidy, trailing
1066
- // newlines within expressions are removed and the indentation tokens of empty
1067
- // blocks are added.
1068
- normalizeLines() {
1069
- var action, closeElseTag, condition, ifThens, indent, leading_if_then, leading_switch_when, outdent, starter;
1070
- starter = indent = outdent = null;
1071
- leading_switch_when = null;
1072
- leading_if_then = null;
1073
- // Count `THEN` tags
1074
- ifThens = [];
1075
- condition = function (token, i) {
1076
- var ref, ref1, ref2, ref3;
1077
- return (
1078
- (token[1] !== ';' &&
1079
- ((ref = token[0]), indexOf.call(SINGLE_CLOSERS, ref) >= 0) &&
1080
- !(token[0] === 'TERMINATOR' && ((ref1 = this.tag(i + 1)), indexOf.call(EXPRESSION_CLOSE, ref1) >= 0)) &&
1081
- !(token[0] === 'ELSE' && (starter !== 'THEN' || leading_if_then || leading_switch_when)) &&
1082
- !(((ref2 = token[0]) === 'CATCH' || ref2 === 'FINALLY') && (starter === '->' || starter === '=>'))) ||
1083
- (((ref3 = token[0]), indexOf.call(CALL_CLOSERS, ref3) >= 0) &&
1084
- (this.tokens[i - 1].newLine || this.tokens[i - 1][0] === 'OUTDENT'))
1085
- );
1086
- };
1087
- action = function (token, i) {
1088
- if (token[0] === 'ELSE' && starter === 'THEN') {
1089
- ifThens.pop();
1090
- }
1091
- return this.tokens.splice(this.tag(i - 1) === ',' ? i - 1 : i, 0, outdent);
1092
- };
1093
- closeElseTag = (tokens, i) => {
1094
- var lastThen, outdentElse, tlen;
1095
- tlen = ifThens.length;
1096
- if (!(tlen > 0)) {
1097
- return i;
1098
- }
1099
- lastThen = ifThens.pop();
1100
- [, outdentElse] = this.indentation(tokens[lastThen]);
1101
- // Insert `OUTDENT` to close inner `IF`.
1102
- outdentElse[1] = tlen * 2;
1103
- tokens.splice(i, 0, outdentElse);
1104
- // Insert `OUTDENT` to close outer `IF`.
1105
- outdentElse[1] = 2;
1106
- tokens.splice(i + 1, 0, outdentElse);
1107
- // Remove outdents from the end.
1108
- this.detectEnd(
1109
- i + 2,
1110
- function (token, i) {
1111
- var ref;
1112
- return (ref = token[0]) === 'OUTDENT' || ref === 'TERMINATOR';
1113
- },
1114
- function (token, i) {
1115
- if (this.tag(i) === 'OUTDENT' && this.tag(i + 1) === 'OUTDENT') {
1116
- return tokens.splice(i, 2);
1117
- }
1118
- },
1119
- );
1120
- return i + 2;
1121
- };
1122
- return this.scanTokens(function (token, i, tokens) {
1123
- var conditionTag, j, k, ref, ref1, ref2, tag;
1124
- [tag] = token;
1125
- conditionTag =
1126
- (tag === '->' || tag === '=>') &&
1127
- this.findTagsBackwards(i, ['IF', 'WHILE', 'FOR', 'UNTIL', 'SWITCH', 'WHEN', 'LEADING_WHEN', '[', 'INDEX_START']) &&
1128
- !this.findTagsBackwards(i, ['THEN', '..', '...']);
1129
- if (tag === 'TERMINATOR') {
1130
- if (this.tag(i + 1) === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
1131
- tokens.splice(i, 1, ...this.indentation());
1132
- return 1;
1133
- }
1134
- if (((ref = this.tag(i + 1)), indexOf.call(EXPRESSION_CLOSE, ref) >= 0)) {
1135
- if (token[1] === ';' && this.tag(i + 1) === 'OUTDENT') {
1136
- tokens[i + 1].prevToken = token;
1137
- moveComments(token, tokens[i + 1]);
1138
- }
1139
- tokens.splice(i, 1);
1140
- return 0;
1141
- }
1142
- }
1143
- if (tag === 'CATCH') {
1144
- for (j = k = 1; k <= 2; j = ++k) {
1145
- if (!((ref1 = this.tag(i + j)) === 'OUTDENT' || ref1 === 'TERMINATOR' || ref1 === 'FINALLY')) {
1146
- continue;
1147
- }
1148
- tokens.splice(i + j, 0, ...this.indentation());
1149
- return 2 + j;
1150
- }
1151
- }
1152
- if (
1153
- (tag === '->' || tag === '=>') &&
1154
- ((ref2 = this.tag(i + 1)) === ',' || ref2 === ']' || (this.tag(i + 1) === '.' && token.newLine))
1155
- ) {
1156
- [indent, outdent] = this.indentation(tokens[i]);
1157
- tokens.splice(i + 1, 0, indent, outdent);
1158
- return 1;
1159
- }
1160
- if (
1161
- indexOf.call(SINGLE_LINERS, tag) >= 0 &&
1162
- this.tag(i + 1) !== 'INDENT' &&
1163
- !(tag === 'ELSE' && this.tag(i + 1) === 'IF') &&
1164
- !conditionTag
1165
- ) {
1166
- starter = tag;
1167
- [indent, outdent] = this.indentation(tokens[i]);
1168
- if (starter === 'THEN') {
1169
- indent.fromThen = true;
1170
- }
1171
- if (tag === 'THEN') {
1172
- leading_switch_when = this.findTagsBackwards(i, ['LEADING_WHEN']) && this.tag(i + 1) === 'IF';
1173
- leading_if_then = this.findTagsBackwards(i, ['IF']) && this.tag(i + 1) === 'IF';
1174
- }
1175
- if (tag === 'THEN' && this.findTagsBackwards(i, ['IF'])) {
1176
- ifThens.push(i);
1177
- }
1178
- // `ELSE` tag is not closed.
1179
- if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
1180
- i = closeElseTag(tokens, i);
1181
- }
1182
- tokens.splice(i + 1, 0, indent);
1183
- this.detectEnd(i + 2, condition, action);
1184
- if (tag === 'THEN') {
1185
- tokens.splice(i, 1);
1186
- }
1187
- return 1;
1188
- }
1189
- return 1;
1190
- });
1191
- }
1192
-
1193
- // Tag postfix conditionals as such, so that we can parse them with a
1194
- // different precedence.
1195
- tagPostfixConditionals() {
1196
- var action, condition, original;
1197
- original = null;
1198
- condition = function (token, i) {
1199
- var prevTag, tag;
1200
- [tag] = token;
1201
- [prevTag] = this.tokens[i - 1];
1202
- return tag === 'TERMINATOR' || (tag === 'INDENT' && indexOf.call(SINGLE_LINERS, prevTag) < 0);
1203
- };
1204
- action = function (token, i) {
1205
- if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
1206
- return (original[0] = 'POST_' + original[0]);
1207
- }
1208
- };
1209
- return this.scanTokens(function (token, i) {
1210
- if (token[0] !== 'IF') {
1211
- return 1;
1212
- }
1213
- original = token;
1214
- this.detectEnd(i + 1, condition, action);
1215
- return 1;
1216
- });
1217
- }
1218
-
1219
- // For tokens with extra data, we want to make that data visible to the grammar
1220
- // by wrapping the token value as a String() object and setting the data as
1221
- // properties of that object. The grammar should then be responsible for
1222
- // cleaning this up for the node constructor: unwrapping the token value to a
1223
- // primitive string and separately passing any expected token data properties
1224
- exposeTokenDataToGrammar() {
1225
- return this.scanTokens(function (token, i) {
1226
- var key, ref, ref1, val;
1227
- if (token.generated || (token.data && Object.keys(token.data).length !== 0)) {
1228
- token[1] = new String(token[1]);
1229
- ref1 = (ref = token.data) != null ? ref : {};
1230
- for (key in ref1) {
1231
- if (!hasProp.call(ref1, key)) continue;
1232
- val = ref1[key];
1233
- token[1][key] = val;
1234
- }
1235
- if (token.generated) {
1236
- token[1].generated = true;
1237
- }
1238
- }
1239
- return 1;
1240
- });
1241
- }
1242
-
1243
- // Generate the indentation tokens, based on another token on the same line.
1244
- indentation(origin) {
1245
- var indent, outdent;
1246
- indent = ['INDENT', 2];
1247
- outdent = ['OUTDENT', 2];
1248
- if (origin) {
1249
- indent.generated = outdent.generated = true;
1250
- indent.origin = outdent.origin = origin;
1251
- } else {
1252
- indent.explicit = outdent.explicit = true;
1253
- }
1254
- return [indent, outdent];
1255
- }
1256
-
1257
- // Look up a tag by token index.
1258
- tag(i) {
1259
- var ref;
1260
- return (ref = this.tokens[i]) != null ? ref[0] : void 0;
1261
- }
1262
- }
1263
-
1264
- Rewriter.prototype.generate = generate;
1265
-
1266
- return Rewriter;
1267
- }.call(this);
1268
-
1269
- // Constants
1270
- // ---------
1271
-
1272
- // List of the token pairs that must be balanced.
1273
- BALANCED_PAIRS = [
1274
- ['(', ')'],
1275
- ['[', ']'],
1276
- ['{', '}'],
1277
- ['INDENT', 'OUTDENT'],
1278
- ['CALL_START', 'CALL_END'],
1279
- ['PARAM_START', 'PARAM_END'],
1280
- ['INDEX_START', 'INDEX_END'],
1281
- ['STRING_START', 'STRING_END'],
1282
- ['INTERPOLATION_START', 'INTERPOLATION_END'],
1283
- ['REGEX_START', 'REGEX_END'],
1284
- ];
1285
-
1286
- // The inverse mappings of `BALANCED_PAIRS` we’re trying to fix up, so we can
1287
- // look things up from either end.
1288
- exports.INVERSES = INVERSES = {};
1289
-
1290
- // The tokens that signal the start/end of a balanced pair.
1291
- EXPRESSION_START = [];
1292
-
1293
- EXPRESSION_END = [];
1294
-
1295
- for (k = 0, len = BALANCED_PAIRS.length; k < len; k++) {
1296
- [left, right] = BALANCED_PAIRS[k];
1297
- EXPRESSION_START.push((INVERSES[right] = left));
1298
- EXPRESSION_END.push((INVERSES[left] = right));
1299
- }
1300
-
1301
- // Tokens that indicate the close of a clause of an expression.
1302
- EXPRESSION_CLOSE = ['CATCH', 'THEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
1303
-
1304
- // Tokens that, if followed by an `IMPLICIT_CALL`, indicate a function invocation.
1305
- IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
1306
-
1307
- // If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
1308
- IMPLICIT_CALL = [
1309
- 'IDENTIFIER',
1310
- 'JSX_TAG',
1311
- 'PROPERTY',
1312
- 'NUMBER',
1313
- 'INFINITY',
1314
- 'NAN',
1315
- 'STRING',
1316
- 'STRING_START',
1317
- 'REGEX',
1318
- 'REGEX_START',
1319
- 'JS',
1320
- 'NEW',
1321
- 'PARAM_START',
1322
- 'CLASS',
1323
- 'IF',
1324
- 'TRY',
1325
- 'SWITCH',
1326
- 'THIS',
1327
- 'DYNAMIC_IMPORT',
1328
- 'IMPORT_META',
1329
- 'NEW_TARGET',
1330
- 'UNDEFINED',
1331
- 'NULL',
1332
- 'BOOL',
1333
- 'UNARY',
1334
- 'DO',
1335
- 'DO_IIFE',
1336
- 'YIELD',
1337
- 'AWAIT',
1338
- 'UNARY_MATH',
1339
- 'SUPER',
1340
- 'THROW',
1341
- '@',
1342
- '->',
1343
- '=>',
1344
- '[',
1345
- '(',
1346
- '{',
1347
- '--',
1348
- '++',
1349
- ];
1350
-
1351
- IMPLICIT_UNSPACED_CALL = ['+', '-'];
1352
-
1353
- // Tokens that always mark the end of an implicit call for single-liners.
1354
- IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
1355
-
1356
- // Single-line flavors of block expressions that have unclosed endings.
1357
- // The grammar can’t disambiguate them, so we insert the implicit indentation.
1358
- SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
1359
-
1360
- SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
1361
-
1362
- // Tokens that end a line.
1363
- LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
1364
-
1365
- // Tokens that close open calls when they follow a newline.
1366
- CALL_CLOSERS = ['.', '?.', '::', '?::'];
1367
-
1368
- // Tokens that prevent a subsequent indent from ending implicit calls/objects
1369
- CONTROL_IN_IMPLICIT = ['IF', 'TRY', 'FINALLY', 'CATCH', 'CLASS', 'SWITCH'];
1370
-
1371
- // Tokens that are swallowed up by the parser, never leading to code generation.
1372
- // You can spot these in `grammar.coffee` because the `o` function second
1373
- // argument doesn’t contain a `new` call for these tokens.
1374
- // `STRING_START` isn’t on this list because its `locationData` matches that of
1375
- // the node that becomes `StringWithInterpolations`, and therefore
1376
- // `addDataToNode` attaches `STRING_START`’s tokens to that node.
1377
- DISCARDED = [
1378
- '(',
1379
- ')',
1380
- '[',
1381
- ']',
1382
- '{',
1383
- '}',
1384
- ':',
1385
- '.',
1386
- '..',
1387
- '...',
1388
- ',',
1389
- '=',
1390
- '++',
1391
- '--',
1392
- '?',
1393
- 'AS',
1394
- 'AWAIT',
1395
- 'CALL_START',
1396
- 'CALL_END',
1397
- 'DEFAULT',
1398
- 'DO',
1399
- 'DO_IIFE',
1400
- 'ELSE',
1401
- 'EXTENDS',
1402
- 'EXPORT',
1403
- 'FORIN',
1404
- 'FOROF',
1405
- 'FORFROM',
1406
- 'IMPORT',
1407
- 'INDENT',
1408
- 'INDEX_SOAK',
1409
- 'INTERPOLATION_START',
1410
- 'INTERPOLATION_END',
1411
- 'LEADING_WHEN',
1412
- 'OUTDENT',
1413
- 'PARAM_END',
1414
- 'REGEX_START',
1415
- 'REGEX_END',
1416
- 'RETURN',
1417
- 'STRING_END',
1418
- 'THROW',
1419
- 'UNARY',
1420
- 'YIELD',
1421
- ].concat(IMPLICIT_UNSPACED_CALL.concat(IMPLICIT_END.concat(CALL_CLOSERS.concat(CONTROL_IN_IMPLICIT))));
1422
-
1423
- // Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token
1424
- exports.UNFINISHED = UNFINISHED = [
1425
- '\\',
1426
- '.',
1427
- '?.',
1428
- '?::',
1429
- 'UNARY',
1430
- 'DO',
1431
- 'DO_IIFE',
1432
- 'MATH',
1433
- 'UNARY_MATH',
1434
- '+',
1435
- '-',
1436
- '**',
1437
- 'SHIFT',
1438
- 'RELATION',
1439
- 'COMPARE',
1440
- '&',
1441
- '^',
1442
- '|',
1443
- '&&',
1444
- '||',
1445
- 'BIN?',
1446
- 'EXTENDS',
1447
- ];
1448
- }).call(this);