mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
Disallow single-line IF expr ELSE
without THEN
* Supplement missing block before `ELSE` token only for multi-line `if`. * Don't prematurely remove `TERMINATOR` before `ELSE` (so we can differentiate single- and multi-line forms). * Cleanup: Remove `WHEN` from `EXPRESSION_CLOSE`. (Only `LEADING_WHEN` tokens are preceded by a `TERMINATOR`.) * Cleanup: Remove really old, inapplicable text from comment.
This commit is contained in:
parent
f48aa44386
commit
fdd5796f5e
3 changed files with 26 additions and 21 deletions
|
@ -365,19 +365,21 @@
|
|||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var j, tag, _i, _ref, _ref1;
|
||||
var j, tag, _i, _ref, _ref1, _ref2;
|
||||
tag = token[0];
|
||||
if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
|
||||
tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation())));
|
||||
return 2;
|
||||
if (tag === 'TERMINATOR') {
|
||||
if (this.tag(i + 1) === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
|
||||
tokens.splice.apply(tokens, [i, 1].concat(__slice.call(this.indentation())));
|
||||
return 1;
|
||||
}
|
||||
if ((_ref = this.tag(i + 1)) === 'THEN' || _ref === 'ELSE') {
|
||||
tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (tag === 'CATCH') {
|
||||
for (j = _i = 1; _i <= 2; j = ++_i) {
|
||||
if (!((_ref = this.tag(i + j)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) {
|
||||
if (!((_ref1 = this.tag(i + j)) === 'OUTDENT' || _ref1 === 'TERMINATOR' || _ref1 === 'FINALLY')) {
|
||||
continue;
|
||||
}
|
||||
tokens.splice.apply(tokens, [i + j, 0].concat(__slice.call(this.indentation())));
|
||||
|
@ -386,7 +388,7 @@
|
|||
}
|
||||
if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
starter = tag;
|
||||
_ref1 = this.indentation(true), indent = _ref1[0], outdent = _ref1[1];
|
||||
_ref2 = this.indentation(true), indent = _ref2[0], outdent = _ref2[1];
|
||||
if (starter === 'THEN') {
|
||||
indent.fromThen = true;
|
||||
}
|
||||
|
@ -466,7 +468,7 @@
|
|||
EXPRESSION_END.push(INVERSES[left] = rite);
|
||||
}
|
||||
|
||||
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
|
||||
EXPRESSION_CLOSE = ['CATCH', 'FINALLY'].concat(EXPRESSION_END);
|
||||
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
|
||||
|
|
|
@ -355,8 +355,7 @@ class exports.Rewriter
|
|||
|
||||
# Because our grammar is LALR(1), it can't handle some single-line
|
||||
# expressions that lack ending delimiters. The **Rewriter** adds the implicit
|
||||
# blocks, so it doesn't need to. ')' can close a single-line block,
|
||||
# but we need to make sure it's balanced.
|
||||
# blocks, so it doesn't need to.
|
||||
addImplicitIndentation: ->
|
||||
starter = indent = outdent = null
|
||||
|
||||
|
@ -370,12 +369,13 @@ class exports.Rewriter
|
|||
|
||||
@scanTokens (token, i, tokens) ->
|
||||
[tag] = token
|
||||
if tag is 'TERMINATOR' and @tag(i + 1) is 'THEN'
|
||||
tokens.splice i, 1
|
||||
return 0
|
||||
if tag is 'ELSE' and @tag(i - 1) isnt 'OUTDENT'
|
||||
tokens.splice i, 0, @indentation()...
|
||||
return 2
|
||||
if tag is 'TERMINATOR'
|
||||
if @tag(i + 1) is 'ELSE' and @tag(i - 1) isnt 'OUTDENT'
|
||||
tokens.splice i, 1, @indentation()...
|
||||
return 1
|
||||
if @tag(i + 1) in ['THEN', 'ELSE']
|
||||
tokens.splice i, 1
|
||||
return 0
|
||||
if tag is 'CATCH'
|
||||
for j in [1..2] when @tag(i + j) in ['OUTDENT', 'TERMINATOR', 'FINALLY']
|
||||
tokens.splice i + j, 0, @indentation()...
|
||||
|
@ -452,7 +452,7 @@ for [left, rite] in BALANCED_PAIRS
|
|||
EXPRESSION_END .push INVERSES[left] = rite
|
||||
|
||||
# Tokens that indicate the close of a clause of an expression.
|
||||
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat EXPRESSION_END
|
||||
EXPRESSION_CLOSE = ['CATCH', 'FINALLY'].concat EXPRESSION_END
|
||||
|
||||
# Tokens that, if followed by an `IMPLICIT_CALL`, indicate a function invocation.
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']
|
||||
|
|
|
@ -84,4 +84,7 @@ test "#2944: implicit call with a regex argument", ->
|
|||
CoffeeScript.compile 'o[key] /regex/'
|
||||
|
||||
test "#3001: `own` shouldn't be allowed in a `for`-`in` loop", ->
|
||||
cantCompile "a for own b in c"
|
||||
cantCompile "a for own b in c"
|
||||
|
||||
test "#2994: single-line `if` requires `then`", ->
|
||||
cantCompile "if b else x"
|
||||
|
|
Loading…
Reference in a new issue