mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-05-03 03:00:14 -04:00
Restrict indented return arg to object (#4605)
* throw multiline implicit object [Fixes #3199] * only return * fix from code review * test error on non-object * test error on call indented non-object * unique test names
This commit is contained in:
committed by
Geoffrey Booth
parent
e4bf1631e1
commit
799bc6e81c
@@ -143,6 +143,8 @@
|
||||
Return: [
|
||||
o('RETURN Expression', function() {
|
||||
return new Return($2);
|
||||
}), o('RETURN INDENT Object OUTDENT', function() {
|
||||
return new Return(new Value($3));
|
||||
}), o('RETURN', function() {
|
||||
return new Return;
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 1.12.6
|
||||
(function() {
|
||||
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, REGEX_INVALID_ESCAPE, RELATION, RESERVED, Rewriter, SHIFT, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_INVALID_ESCAPE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, UNICODE_CODE_POINT_ESCAPE, VALID_FLAGS, WHITESPACE, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, ref, ref1, repeat, starts, throwSyntaxError,
|
||||
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, REGEX_INVALID_ESCAPE, RELATION, RESERVED, Rewriter, SHIFT, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_INVALID_ESCAPE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, UNFINISHED, UNICODE_CODE_POINT_ESCAPE, VALID_FLAGS, WHITESPACE, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, ref, ref1, repeat, starts, throwSyntaxError,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
slice = [].slice;
|
||||
|
||||
@@ -450,7 +450,7 @@
|
||||
return indent.length;
|
||||
}
|
||||
if (size > this.indent) {
|
||||
if (noNewlines || this.tag() === 'RETURN') {
|
||||
if (noNewlines) {
|
||||
this.indebt = size - this.indent;
|
||||
this.suppressNewlines();
|
||||
return indent.length;
|
||||
@@ -874,7 +874,7 @@
|
||||
|
||||
Lexer.prototype.unfinished = function() {
|
||||
var ref2;
|
||||
return LINE_CONTINUER.test(this.chunk) || ((ref2 = this.tag()) === '\\' || ref2 === '.' || ref2 === '?.' || ref2 === '?::' || ref2 === 'UNARY' || ref2 === 'MATH' || ref2 === 'UNARY_MATH' || ref2 === '+' || ref2 === '-' || ref2 === '**' || ref2 === 'SHIFT' || ref2 === 'RELATION' || ref2 === 'COMPARE' || ref2 === '&' || ref2 === '^' || ref2 === '|' || ref2 === '&&' || ref2 === '||' || ref2 === 'BIN?' || ref2 === 'THROW' || ref2 === 'EXTENDS' || ref2 === 'DEFAULT');
|
||||
return LINE_CONTINUER.test(this.chunk) || (ref2 = this.tag(), indexOf.call(UNFINISHED, ref2) >= 0);
|
||||
};
|
||||
|
||||
Lexer.prototype.formatString = function(str, options) {
|
||||
@@ -1161,4 +1161,6 @@
|
||||
|
||||
INDENTABLE_CLOSERS = [')', '}', ']'];
|
||||
|
||||
UNFINISHED = ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-', '**', 'SHIFT', 'RELATION', 'COMPARE', '&', '^', '|', '&&', '||', 'BIN?', 'THROW', 'EXTENDS', 'DEFAULT'];
|
||||
|
||||
}).call(this);
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -211,6 +211,7 @@ grammar =
|
||||
# A return statement from a function body.
|
||||
Return: [
|
||||
o 'RETURN Expression', -> new Return $2
|
||||
o 'RETURN INDENT Object OUTDENT', -> new Return new Value $3
|
||||
o 'RETURN', -> new Return
|
||||
]
|
||||
|
||||
|
||||
@@ -378,7 +378,7 @@ exports.Lexer = class Lexer
|
||||
return indent.length
|
||||
|
||||
if size > @indent
|
||||
if noNewlines or @tag() is 'RETURN'
|
||||
if noNewlines
|
||||
@indebt = size - @indent
|
||||
@suppressNewlines()
|
||||
return indent.length
|
||||
@@ -759,9 +759,7 @@ exports.Lexer = class Lexer
|
||||
# Are we in the midst of an unfinished expression?
|
||||
unfinished: ->
|
||||
LINE_CONTINUER.test(@chunk) or
|
||||
@tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-',
|
||||
'**', 'SHIFT', 'RELATION', 'COMPARE', '&', '^', '|', '&&', '||',
|
||||
'BIN?', 'THROW', 'EXTENDS', 'DEFAULT']
|
||||
@tag() in UNFINISHED
|
||||
|
||||
formatString: (str, options) ->
|
||||
@replaceUnicodeCodePointEscapes str.replace(STRING_OMIT, '$1'), options
|
||||
@@ -1094,3 +1092,8 @@ LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']
|
||||
|
||||
# Additional indent in front of these is ignored.
|
||||
INDENTABLE_CLOSERS = [')', '}', ']']
|
||||
|
||||
# Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token
|
||||
UNFINISHED = ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-',
|
||||
'**', 'SHIFT', 'RELATION', 'COMPARE', '&', '^', '|', '&&', '||',
|
||||
'BIN?', 'THROW', 'EXTENDS', 'DEFAULT']
|
||||
|
||||
@@ -1328,3 +1328,45 @@ test "#4283: error message for implicit call", ->
|
||||
console.log {search, users, contacts users_to_display}
|
||||
^^^^^^^^
|
||||
'''
|
||||
|
||||
test "#3199: error message for call indented non-object", ->
|
||||
assertErrorFormat '''
|
||||
fn = ->
|
||||
fn
|
||||
1
|
||||
''', '''
|
||||
[stdin]:3:1: error: unexpected indentation
|
||||
1
|
||||
^^
|
||||
'''
|
||||
|
||||
test "#3199: error message for call indented comprehension", ->
|
||||
assertErrorFormat '''
|
||||
fn = ->
|
||||
fn
|
||||
x for x in [1, 2, 3]
|
||||
''', '''
|
||||
[stdin]:3:1: error: unexpected indentation
|
||||
x for x in [1, 2, 3]
|
||||
^^
|
||||
'''
|
||||
|
||||
test "#3199: error message for return indented non-object", ->
|
||||
assertErrorFormat '''
|
||||
return
|
||||
1
|
||||
''', '''
|
||||
[stdin]:2:3: error: unexpected number
|
||||
1
|
||||
^
|
||||
'''
|
||||
|
||||
test "#3199: error message for return indented comprehension", ->
|
||||
assertErrorFormat '''
|
||||
return
|
||||
x for x in [1, 2, 3]
|
||||
''', '''
|
||||
[stdin]:2:3: error: unexpected identifier
|
||||
x for x in [1, 2, 3]
|
||||
^
|
||||
'''
|
||||
|
||||
@@ -298,3 +298,10 @@ test "#1275: allow indentation before closing brackets", ->
|
||||
a = 1
|
||||
)
|
||||
eq 1, a
|
||||
|
||||
test "#3199: return multiline implicit object", ->
|
||||
y = do ->
|
||||
if no then return
|
||||
type: 'a'
|
||||
msg: 'b'
|
||||
eq undefined, y
|
||||
|
||||
Reference in New Issue
Block a user