jashkenas--coffeescript/test/error_messages.coffee

647 lines
13 KiB
CoffeeScript

# Error Formating
# ---------------
# Ensure that errors of different kinds (lexer, parser and compiler) are shown
# in a consistent way.
assertErrorFormat = (code, expectedErrorFormat) ->
throws (-> CoffeeScript.run code), (err) ->
err.colorful = no
eq expectedErrorFormat, "#{err}"
yes
test "lexer errors formating", ->
assertErrorFormat '''
normalObject = {}
insideOutObject = }{
''',
'''
[stdin]:2:19: error: unmatched }
insideOutObject = }{
^
'''
test "parser error formating", ->
assertErrorFormat '''
foo in bar or in baz
''',
'''
[stdin]:1:15: error: unexpected in
foo in bar or in baz
^^
'''
test "compiler error formatting", ->
assertErrorFormat '''
evil = (foo, eval, bar) ->
''',
'''
[stdin]:1:14: error: parameter name "eval" is not allowed
evil = (foo, eval, bar) ->
^^^^
'''
test "compiler error formatting with mixed tab and space", ->
assertErrorFormat """
\t if a
\t test
""",
'''
[stdin]:1:4: error: unexpected if
\t if a
\t ^^
'''
if require?
fs = require 'fs'
path = require 'path'
test "patchStackTrace line patching", ->
err = new Error 'error'
ok err.stack.match /test[\/\\]error_messages\.coffee:\d+:\d+\b/
test "patchStackTrace stack prelude consistent with V8", ->
err = new Error
ok err.stack.match /^Error\n/ # Notice no colon when no message.
err = new Error 'error'
ok err.stack.match /^Error: error\n/
test "#2849: compilation error in a require()d file", ->
# Create a temporary file to require().
ok not fs.existsSync 'test/syntax-error.coffee'
fs.writeFileSync 'test/syntax-error.coffee', 'foo in bar or in baz'
try
assertErrorFormat '''
require './test/syntax-error'
''',
"""
#{path.join __dirname, 'syntax-error.coffee'}:1:15: error: unexpected in
foo in bar or in baz
^^
"""
finally
fs.unlink 'test/syntax-error.coffee'
test "#1096: unexpected generated tokens", ->
# Unexpected interpolation
assertErrorFormat '{"#{key}": val}', '''
[stdin]:1:3: error: unexpected interpolation
{"#{key}": val}
^^
'''
# Implicit ends
assertErrorFormat 'a:, b', '''
[stdin]:1:3: error: unexpected ,
a:, b
^
'''
# Explicit ends
assertErrorFormat '(a:)', '''
[stdin]:1:4: error: unexpected )
(a:)
^
'''
# Unexpected end of file
assertErrorFormat 'a:', '''
[stdin]:1:3: error: unexpected end of input
a:
^
'''
assertErrorFormat 'a +', '''
[stdin]:1:4: error: unexpected end of input
a +
^
'''
# Unexpected implicit object
assertErrorFormat '''
for i in [1]:
1
''', '''
[stdin]:1:13: error: unexpected :
for i in [1]:
^
'''
# Unexpected regex
assertErrorFormat '{/a/i: val}', '''
[stdin]:1:2: error: unexpected /a/i
{/a/i: val}
^^^^
'''
assertErrorFormat '{///a///i: val}', '''
[stdin]:1:2: error: unexpected ///a///i
{///a///i: val}
^^^^^^^^
'''
assertErrorFormat '{///#{a}///i: val}', '''
[stdin]:1:2: error: unexpected ///#{a}///i
{///#{a}///i: val}
^^^^^^^^^^^
'''
test "#1316: unexpected end of interpolation", ->
assertErrorFormat '''
"#{+}"
''', '''
[stdin]:1:5: error: unexpected end of interpolation
"#{+}"
^
'''
assertErrorFormat '''
"#{++}"
''', '''
[stdin]:1:6: error: unexpected end of interpolation
"#{++}"
^
'''
assertErrorFormat '''
"#{-}"
''', '''
[stdin]:1:5: error: unexpected end of interpolation
"#{-}"
^
'''
assertErrorFormat '''
"#{--}"
''', '''
[stdin]:1:6: error: unexpected end of interpolation
"#{--}"
^
'''
assertErrorFormat '''
"#{~}"
''', '''
[stdin]:1:5: error: unexpected end of interpolation
"#{~}"
^
'''
assertErrorFormat '''
"#{!}"
''', '''
[stdin]:1:5: error: unexpected end of interpolation
"#{!}"
^
'''
assertErrorFormat '''
"#{not}"
''', '''
[stdin]:1:7: error: unexpected end of interpolation
"#{not}"
^
'''
assertErrorFormat '''
"#{5) + (4}_"
''', '''
[stdin]:1:5: error: unmatched )
"#{5) + (4}_"
^
'''
# #2918
assertErrorFormat '''
"#{foo.}"
''', '''
[stdin]:1:8: error: unexpected end of interpolation
"#{foo.}"
^
'''
test "#3325: implicit indentation errors", ->
assertErrorFormat '''
i for i in a then i
''', '''
[stdin]:1:14: error: unexpected then
i for i in a then i
^^^^
'''
test "explicit indentation errors", ->
assertErrorFormat '''
a = b
c
''', '''
[stdin]:2:1: error: unexpected indentation
c
^^
'''
test "unclosed strings", ->
assertErrorFormat '''
'
''', '''
[stdin]:1:1: error: missing '
'
^
'''
assertErrorFormat '''
"
''', '''
[stdin]:1:1: error: missing "
"
^
'''
assertErrorFormat """
'''
""", """
[stdin]:1:1: error: missing '''
'''
^^^
"""
assertErrorFormat '''
"""
''', '''
[stdin]:1:1: error: missing """
"""
^^^
'''
assertErrorFormat '''
"#{"
''', '''
[stdin]:1:4: error: missing "
"#{"
^
'''
assertErrorFormat '''
"""#{"
''', '''
[stdin]:1:6: error: missing "
"""#{"
^
'''
assertErrorFormat '''
"#{"""
''', '''
[stdin]:1:4: error: missing """
"#{"""
^^^
'''
assertErrorFormat '''
"""#{"""
''', '''
[stdin]:1:6: error: missing """
"""#{"""
^^^
'''
assertErrorFormat '''
///#{"""
''', '''
[stdin]:1:6: error: missing """
///#{"""
^^^
'''
assertErrorFormat '''
"a
#{foo """
bar
#{ +'12 }
baz
"""} b"
''', '''
[stdin]:4:11: error: missing '
#{ +'12 }
^
'''
# https://github.com/jashkenas/coffeescript/issues/3301#issuecomment-31735168
assertErrorFormat '''
# Note the double escaping; this would be `"""a\"""` real code.
"""a\\"""
''', '''
[stdin]:2:1: error: missing """
"""a\\"""
^^^
'''
test "unclosed heregexes", ->
assertErrorFormat '''
///
''', '''
[stdin]:1:1: error: missing ///
///
^^^
'''
# https://github.com/jashkenas/coffeescript/issues/3301#issuecomment-31735168
assertErrorFormat '''
# Note the double escaping; this would be `///a\///` real code.
///a\\///
''', '''
[stdin]:2:1: error: missing ///
///a\\///
^^^
'''
test "unexpected token after string", ->
# Parsing error.
assertErrorFormat '''
'foo'bar
''', '''
[stdin]:1:6: error: unexpected bar
'foo'bar
^^^
'''
assertErrorFormat '''
"foo"bar
''', '''
[stdin]:1:6: error: unexpected bar
"foo"bar
^^^
'''
# Lexing error.
assertErrorFormat '''
'foo'bar'
''', '''
[stdin]:1:9: error: missing '
'foo'bar'
^
'''
assertErrorFormat '''
"foo"bar"
''', '''
[stdin]:1:9: error: missing "
"foo"bar"
^
'''
test "#3348: Location data is wrong in interpolations with leading whitespace", ->
assertErrorFormat '''
"#{ {"#{key}": val} }"
''', '''
[stdin]:1:7: error: unexpected interpolation
"#{ {"#{key}": val} }"
^^
'''
test "octal escapes", ->
assertErrorFormat '''
"a\\0\\tb\\\\\\07c"
''', '''
[stdin]:1:10: error: octal escape sequences are not allowed \\07
"a\\0\\tb\\\\\\07c"
\ \ \ \ ^\^^
'''
assertErrorFormat '''
"a
#{b} \\1"
''', '''
[stdin]:2:8: error: octal escape sequences are not allowed \\1
#{b} \\1"
^\^
'''
assertErrorFormat '''
/a\\0\\tb\\\\\\07c/
''', '''
[stdin]:1:10: error: octal escape sequences are not allowed \\07
/a\\0\\tb\\\\\\07c/
\ \ \ \ ^\^^
'''
assertErrorFormat '''
///a
#{b} \\01///
''', '''
[stdin]:2:8: error: octal escape sequences are not allowed \\01
#{b} \\01///
^\^^
'''
test "#3795: invalid escapes", ->
assertErrorFormat '''
"a\\0\\tb\\\\\\x7g"
''', '''
[stdin]:1:10: error: invalid escape sequence \\x7g
"a\\0\\tb\\\\\\x7g"
\ \ \ \ ^\^^^
'''
assertErrorFormat '''
"a
#{b} \\uA02
c"
''', '''
[stdin]:2:8: error: invalid escape sequence \\uA02
#{b} \\uA02
^\^^^^
'''
assertErrorFormat '''
/a\\u002space/
''', '''
[stdin]:1:3: error: invalid escape sequence \\u002s
/a\\u002space/
^\^^^^^
'''
assertErrorFormat '''
///a \\u002 0 space///
''', '''
[stdin]:1:6: error: invalid escape sequence \\u002
///a \\u002 0 space///
^\^^^^^
'''
assertErrorFormat '''
///a
#{b} \\x0
c///
''', '''
[stdin]:2:8: error: invalid escape sequence \\x0
#{b} \\x0
^\^^
'''
test "illegal herecomment", ->
assertErrorFormat '''
###
Regex: /a*/g
###
''', '''
[stdin]:2:12: error: block comments cannot contain */
Regex: /a*/g
^^
'''
test "#1724: regular expressions beginning with *", ->
assertErrorFormat '''
/* foo/
''', '''
[stdin]:1:2: error: regular expressions cannot begin with *
/* foo/
^
'''
assertErrorFormat '''
///
* foo
///
''', '''
[stdin]:2:3: error: regular expressions cannot begin with *
* foo
^
'''
test "invalid regex flags", ->
assertErrorFormat '''
/a/ii
''', '''
[stdin]:1:4: error: invalid regular expression flags ii
/a/ii
^^
'''
assertErrorFormat '''
/a/G
''', '''
[stdin]:1:4: error: invalid regular expression flags G
/a/G
^
'''
assertErrorFormat '''
/a/gimi
''', '''
[stdin]:1:4: error: invalid regular expression flags gimi
/a/gimi
^^^^
'''
assertErrorFormat '''
/a/g_
''', '''
[stdin]:1:4: error: invalid regular expression flags g_
/a/g_
^^
'''
assertErrorFormat '''
///a///ii
''', '''
[stdin]:1:8: error: invalid regular expression flags ii
///a///ii
^^
'''
doesNotThrow -> CoffeeScript.compile '/a/ymgi'
test "missing `)`, `}`, `]`", ->
assertErrorFormat '''
(
''', '''
[stdin]:1:1: error: missing )
(
^
'''
assertErrorFormat '''
{
''', '''
[stdin]:1:1: error: missing }
{
^
'''
assertErrorFormat '''
[
''', '''
[stdin]:1:1: error: missing ]
[
^
'''
assertErrorFormat '''
obj = {a: [1, (2+
''', '''
[stdin]:1:15: error: missing )
obj = {a: [1, (2+
^
'''
assertErrorFormat '''
"#{
''', '''
[stdin]:1:3: error: missing }
"#{
^
'''
assertErrorFormat '''
"""
foo#{ bar "#{1}"
''', '''
[stdin]:2:7: error: missing }
foo#{ bar "#{1}"
^
'''
test "unclosed regexes", ->
assertErrorFormat '''
/
''', '''
[stdin]:1:1: error: missing / (unclosed regex)
/
^
'''
assertErrorFormat '''
# Note the double escaping; this would be `/a\/` real code.
/a\\/
''', '''
[stdin]:2:1: error: missing / (unclosed regex)
/a\\/
^
'''
assertErrorFormat '''
/// ^
a #{""" ""#{if /[/].test "|" then 1 else 0}"" """}
///
''', '''
[stdin]:2:18: error: missing / (unclosed regex)
a #{""" ""#{if /[/].test "|" then 1 else 0}"" """}
^
'''
test "duplicate function arguments", ->
assertErrorFormat '''
(foo, bar, foo) ->
''', '''
[stdin]:1:12: error: multiple parameters named foo
(foo, bar, foo) ->
^^^
'''
assertErrorFormat '''
(@foo, bar, @foo) ->
''', '''
[stdin]:1:13: error: multiple parameters named @foo
(@foo, bar, @foo) ->
^^^^
'''
test "reserved words", ->
assertErrorFormat '''
case
''', '''
[stdin]:1:1: error: reserved word 'case'
case
^^^^
'''
assertErrorFormat '''
for = 1
''', '''
[stdin]:1:1: error: reserved word 'for' can't be assigned
for = 1
^^^
'''
test "invalid numbers", ->
assertErrorFormat '''
0X0
''', '''
[stdin]:1:2: error: radix prefix in '0X0' must be lowercase
0X0
^
'''
assertErrorFormat '''
10E0
''', '''
[stdin]:1:3: error: exponential notation in '10E0' must be indicated with a lowercase 'e'
10E0
^
'''
assertErrorFormat '''
018
''', '''
[stdin]:1:1: error: decimal literal '018' must not be prefixed with '0'
018
^^^
'''
assertErrorFormat '''
010
''', '''
[stdin]:1:1: error: octal literal '010' must be prefixed with '0o'
010
^^^
'''