mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
* fix #3933 * tests
This commit is contained in:
parent
84d596d534
commit
70b510bcb7
3 changed files with 89 additions and 3 deletions
|
@ -281,7 +281,7 @@
|
|||
stack = [];
|
||||
start = null;
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var endImplicitCall, endImplicitObject, forward, implicitObjectContinues, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, isImplicit, isImplicitCall, isImplicitObject, k, newLine, nextTag, nextToken, offset, prevTag, prevToken, ref, ref1, ref2, s, sameLine, stackIdx, stackItem, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
|
||||
var endImplicitCall, endImplicitObject, forward, implicitObjectContinues, inControlFlow, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, isImplicit, isImplicitCall, isImplicitObject, k, newLine, nextTag, nextToken, offset, prevTag, prevToken, ref, ref1, ref2, s, sameLine, stackIdx, stackItem, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
|
||||
[tag] = token;
|
||||
[prevTag] = prevToken = i > 0 ? tokens[i - 1] : [];
|
||||
[nextTag] = nextToken = i < tokens.length - 1 ? tokens[i + 1] : [];
|
||||
|
@ -420,10 +420,31 @@
|
|||
}
|
||||
start = stack.pop();
|
||||
}
|
||||
inControlFlow = () => {
|
||||
var controlFlow, isFunc, seenFor, tagCurrentLine;
|
||||
seenFor = this.findTagsBackwards(i, ['FOR']) && this.findTagsBackwards(i, ['FORIN', 'FOROF', 'FORFROM']);
|
||||
controlFlow = seenFor || this.findTagsBackwards(i, ['WHILE', 'UNTIL', 'LOOP', 'LEADING_WHEN']);
|
||||
if (!controlFlow) {
|
||||
return false;
|
||||
}
|
||||
isFunc = false;
|
||||
tagCurrentLine = token[2].first_line;
|
||||
this.detectEnd(i, function(token, i) {
|
||||
var ref;
|
||||
return ref = token[0], indexOf.call(LINEBREAKS, ref) >= 0;
|
||||
}, function(token, i) {
|
||||
var first_line;
|
||||
[prevTag, , {first_line}] = tokens[i - 1] || [];
|
||||
return isFunc = tagCurrentLine === first_line && (prevTag === '->' || prevTag === '=>');
|
||||
}, {
|
||||
returnOnNegativeLevel: true
|
||||
});
|
||||
return isFunc;
|
||||
};
|
||||
// Recognize standard implicit calls like
|
||||
// f a, f() b, f? c, h[0] d etc.
|
||||
// Added support for spread dots on the left side: f ...a
|
||||
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)) {
|
||||
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()) {
|
||||
if (tag === '?') {
|
||||
tag = token[0] = 'FUNC_EXIST';
|
||||
}
|
||||
|
|
|
@ -263,6 +263,20 @@ exports.Rewriter = class Rewriter
|
|||
stack.pop()
|
||||
start = stack.pop()
|
||||
|
||||
inControlFlow = =>
|
||||
seenFor = @findTagsBackwards(i, ['FOR']) and @findTagsBackwards(i, ['FORIN', 'FOROF', 'FORFROM'])
|
||||
controlFlow = seenFor or @findTagsBackwards i, ['WHILE', 'UNTIL', 'LOOP', 'LEADING_WHEN']
|
||||
return no unless controlFlow
|
||||
isFunc = no
|
||||
tagCurrentLine = token[2].first_line
|
||||
@detectEnd i,
|
||||
(token, i) -> token[0] in LINEBREAKS
|
||||
(token, i) ->
|
||||
[prevTag, ,{first_line}] = tokens[i - 1] || []
|
||||
isFunc = tagCurrentLine is first_line and prevTag in ['->', '=>']
|
||||
returnOnNegativeLevel: yes
|
||||
isFunc
|
||||
|
||||
# Recognize standard implicit calls like
|
||||
# f a, f() b, f? c, h[0] d etc.
|
||||
# Added support for spread dots on the left side: f ...a
|
||||
|
@ -271,7 +285,8 @@ exports.Rewriter = class Rewriter
|
|||
(nextTag in IMPLICIT_CALL or
|
||||
(nextTag is '...' and @tag(i + 2) in IMPLICIT_CALL and not @findTagsBackwards(i, ['INDEX_START', '['])) or
|
||||
nextTag in IMPLICIT_UNSPACED_CALL and
|
||||
not nextToken.spaced and not nextToken.newLine)
|
||||
not nextToken.spaced and not nextToken.newLine) and
|
||||
not inControlFlow()
|
||||
tag = token[0] = 'FUNC_EXIST' if tag is '?'
|
||||
startImplicitCall i + 1
|
||||
return forward(2)
|
||||
|
|
|
@ -1777,3 +1777,53 @@ test "#4811: '///' inside a heregex comment does not close the heregex", ->
|
|||
/// .* # comment ///
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "#3933: prevent implicit calls when cotrol flow is missing `THEN`", ->
|
||||
assertErrorFormat '''
|
||||
for a in b do ->
|
||||
''','''
|
||||
[stdin]:1:12: error: unexpected do
|
||||
for a in b do ->
|
||||
^^
|
||||
'''
|
||||
|
||||
assertErrorFormat '''
|
||||
for a in b ->
|
||||
''','''
|
||||
[stdin]:1:12: error: unexpected ->
|
||||
for a in b ->
|
||||
^^
|
||||
'''
|
||||
|
||||
assertErrorFormat '''
|
||||
for a in b do =>
|
||||
''','''
|
||||
[stdin]:1:12: error: unexpected do
|
||||
for a in b do =>
|
||||
^^
|
||||
'''
|
||||
|
||||
assertErrorFormat '''
|
||||
while a do ->
|
||||
''','''
|
||||
[stdin]:1:9: error: unexpected do
|
||||
while a do ->
|
||||
^^
|
||||
'''
|
||||
|
||||
assertErrorFormat '''
|
||||
until a do =>
|
||||
''','''
|
||||
[stdin]:1:9: error: unexpected do
|
||||
until a do =>
|
||||
^^
|
||||
'''
|
||||
|
||||
assertErrorFormat '''
|
||||
switch
|
||||
when a ->
|
||||
''','''
|
||||
[stdin]:2:10: error: unexpected ->
|
||||
when a ->
|
||||
^^
|
||||
'''
|
Loading…
Reference in a new issue