@makano/rew 1.1.8 → 1.1.9

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