Change how error messages are shown
Instead of throwing the syntax errors with their source file location and needing to then catch them and call a `prettyErrorMessage` function in order to get the formatted error message, now syntax errors know how to pretty-print themselves (their `toString` method gets overridden). An intermediate `catch` & re-`throw` is needed at the level of `CoffeeScript.compile` and friends. But the benefit of this approach is that now libraries that use the `CoffeeScript` object directly don't need to bother catching the possible compilation errors and calling a special function in order to get the nice error messages; they can just print the error itself (or let it bubble up) and the error will know how to pretty-print itself.
This commit is contained in:
parent
51c625205b
commit
3f9cdcf1fa
|
@ -1,6 +1,6 @@
|
||||||
// Generated by CoffeeScript 1.6.3
|
// Generated by CoffeeScript 1.6.3
|
||||||
(function() {
|
(function() {
|
||||||
var Lexer, Module, SourceMap, child_process, compile, compileFile, ext, fileExtensions, findExtension, fork, formatSourcePosition, fs, getSourceMap, helpers, lexer, loadFile, parser, path, sourceMaps, vm, _i, _len,
|
var Lexer, Module, SourceMap, child_process, compile, compileFile, ext, fileExtensions, findExtension, fork, formatSourcePosition, fs, getSourceMap, helpers, lexer, loadFile, parser, path, sourceMaps, vm, withPrettyErrors, _i, _len,
|
||||||
__hasProp = {}.hasOwnProperty,
|
__hasProp = {}.hasOwnProperty,
|
||||||
__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; };
|
__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; };
|
||||||
|
|
||||||
|
@ -26,11 +26,25 @@
|
||||||
|
|
||||||
exports.helpers = helpers;
|
exports.helpers = helpers;
|
||||||
|
|
||||||
exports.compile = compile = function(code, options) {
|
withPrettyErrors = function(fn) {
|
||||||
var answer, currentColumn, currentLine, fragment, fragments, header, js, map, merge, newLines, _i, _len;
|
return function(code, options) {
|
||||||
|
var err;
|
||||||
if (options == null) {
|
if (options == null) {
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
return fn.call(this, code, options);
|
||||||
|
} catch (_error) {
|
||||||
|
err = _error;
|
||||||
|
err.code || (err.code = code);
|
||||||
|
err.filename || (err.filename = options.filename);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.compile = compile = withPrettyErrors(function(code, options) {
|
||||||
|
var answer, currentColumn, currentLine, fragment, fragments, header, js, map, merge, newLines, _i, _len;
|
||||||
merge = helpers.merge;
|
merge = helpers.merge;
|
||||||
if (options.sourceMap) {
|
if (options.sourceMap) {
|
||||||
map = new SourceMap;
|
map = new SourceMap;
|
||||||
|
@ -73,19 +87,19 @@
|
||||||
} else {
|
} else {
|
||||||
return js;
|
return js;
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
exports.tokens = function(code, options) {
|
exports.tokens = withPrettyErrors(function(code, options) {
|
||||||
return lexer.tokenize(code, options);
|
return lexer.tokenize(code, options);
|
||||||
};
|
});
|
||||||
|
|
||||||
exports.nodes = function(source, options) {
|
exports.nodes = withPrettyErrors(function(source, options) {
|
||||||
if (typeof source === 'string') {
|
if (typeof source === 'string') {
|
||||||
return parser.parse(lexer.tokenize(source, options));
|
return parser.parse(lexer.tokenize(source, options));
|
||||||
} else {
|
} else {
|
||||||
return parser.parse(source);
|
return parser.parse(source);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
exports.run = function(code, options) {
|
exports.run = function(code, options) {
|
||||||
var answer, mainModule, _ref;
|
var answer, mainModule, _ref;
|
||||||
|
@ -178,8 +192,8 @@
|
||||||
});
|
});
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
err = _error;
|
err = _error;
|
||||||
err.filename = filename;
|
err.filename || (err.filename = filename);
|
||||||
err.code = stripped;
|
err.code || (err.code = stripped);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
return answer;
|
return answer;
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
compileScript = function(file, input, base) {
|
compileScript = function(file, input, base) {
|
||||||
var compiled, err, message, o, options, t, task, useColors;
|
var compiled, err, message, o, options, t, task;
|
||||||
if (base == null) {
|
if (base == null) {
|
||||||
base = null;
|
base = null;
|
||||||
}
|
}
|
||||||
|
@ -195,8 +195,7 @@
|
||||||
if (CoffeeScript.listeners('failure').length) {
|
if (CoffeeScript.listeners('failure').length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
useColors = process.stdout.isTTY && !process.env.NODE_DISABLE_COLORS;
|
message = err.stack || ("" + err);
|
||||||
message = helpers.prettyErrorMessage(err, file || '[stdin]', input, useColors);
|
|
||||||
if (o.watch) {
|
if (o.watch) {
|
||||||
return printLine(message + '\x07');
|
return printLine(message + '\x07');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Generated by CoffeeScript 1.6.3
|
// Generated by CoffeeScript 1.6.3
|
||||||
(function() {
|
(function() {
|
||||||
var buildLocationData, extend, flatten, last, repeat, _ref;
|
var buildLocationData, extend, flatten, last, repeat, syntaxErrorToString, _ref;
|
||||||
|
|
||||||
exports.starts = function(string, literal, start) {
|
exports.starts = function(string, literal, start) {
|
||||||
return literal === string.substr(start, literal.length);
|
return literal === string.substr(start, literal.length);
|
||||||
|
@ -188,38 +188,41 @@
|
||||||
|
|
||||||
exports.throwSyntaxError = function(message, location) {
|
exports.throwSyntaxError = function(message, location) {
|
||||||
var error;
|
var error;
|
||||||
if (location.last_line == null) {
|
|
||||||
location.last_line = location.first_line;
|
|
||||||
}
|
|
||||||
if (location.last_column == null) {
|
|
||||||
location.last_column = location.first_column;
|
|
||||||
}
|
|
||||||
error = new SyntaxError(message);
|
error = new SyntaxError(message);
|
||||||
error.location = location;
|
error.location = location;
|
||||||
|
error.toString = syntaxErrorToString;
|
||||||
|
delete error.stack;
|
||||||
throw error;
|
throw error;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.prettyErrorMessage = function(error, filename, code, useColors) {
|
syntaxErrorToString = function() {
|
||||||
var codeLine, colorize, end, first_column, first_line, last_column, last_line, marker, message, start, _ref1;
|
var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, start, _ref1, _ref2;
|
||||||
if (!error.location) {
|
if (!(this.code && this.location)) {
|
||||||
return error.stack || ("" + error);
|
return Error.prototype.toString.call(this);
|
||||||
}
|
}
|
||||||
filename = error.filename || filename;
|
_ref1 = this.location, first_line = _ref1.first_line, first_column = _ref1.first_column, last_line = _ref1.last_line, last_column = _ref1.last_column;
|
||||||
code = error.code || code;
|
if (last_line == null) {
|
||||||
_ref1 = error.location, first_line = _ref1.first_line, first_column = _ref1.first_column, last_line = _ref1.last_line, last_column = _ref1.last_column;
|
last_line = first_line;
|
||||||
codeLine = code.split('\n')[first_line];
|
}
|
||||||
|
if (last_column == null) {
|
||||||
|
last_column = first_column;
|
||||||
|
}
|
||||||
|
filename = this.filename || '[stdin]';
|
||||||
|
codeLine = this.code.split('\n')[first_line];
|
||||||
start = first_column;
|
start = first_column;
|
||||||
end = first_line === last_line ? last_column + 1 : codeLine.length;
|
end = first_line === last_line ? last_column + 1 : codeLine.length;
|
||||||
marker = repeat(' ', start) + repeat('^', end - start);
|
marker = repeat(' ', start) + repeat('^', end - start);
|
||||||
if (useColors) {
|
if (typeof process !== "undefined" && process !== null) {
|
||||||
|
colorsEnabled = process.stdout.isTTY && !process.env.NODE_DISABLE_COLORS;
|
||||||
|
}
|
||||||
|
if ((_ref2 = this.colorful) != null ? _ref2 : colorsEnabled) {
|
||||||
colorize = function(str) {
|
colorize = function(str) {
|
||||||
return "\x1B[1;31m" + str + "\x1B[0m";
|
return "\x1B[1;31m" + str + "\x1B[0m";
|
||||||
};
|
};
|
||||||
codeLine = codeLine.slice(0, start) + colorize(codeLine.slice(start, end)) + codeLine.slice(end);
|
codeLine = codeLine.slice(0, start) + colorize(codeLine.slice(start, end)) + codeLine.slice(end);
|
||||||
marker = colorize(marker);
|
marker = colorize(marker);
|
||||||
}
|
}
|
||||||
message = "" + filename + ":" + (first_line + 1) + ":" + (first_column + 1) + ": error: " + error.message + "\n" + codeLine + "\n" + marker;
|
return "" + filename + ":" + (first_line + 1) + ":" + (first_column + 1) + ": error: " + this.message + "\n" + codeLine + "\n" + marker;
|
||||||
return message;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Generated by CoffeeScript 1.6.3
|
// Generated by CoffeeScript 1.6.3
|
||||||
(function() {
|
(function() {
|
||||||
var CoffeeScript, addHistory, addMultilineHandler, fs, merge, nodeREPL, path, prettyErrorMessage, replDefaults, vm, _ref;
|
var CoffeeScript, addHistory, addMultilineHandler, fs, merge, nodeREPL, path, replDefaults, vm;
|
||||||
|
|
||||||
fs = require('fs');
|
fs = require('fs');
|
||||||
|
|
||||||
|
@ -12,17 +12,17 @@
|
||||||
|
|
||||||
CoffeeScript = require('./coffee-script');
|
CoffeeScript = require('./coffee-script');
|
||||||
|
|
||||||
_ref = require('./helpers'), merge = _ref.merge, prettyErrorMessage = _ref.prettyErrorMessage;
|
merge = require('./helpers').merge;
|
||||||
|
|
||||||
replDefaults = {
|
replDefaults = {
|
||||||
prompt: 'coffee> ',
|
prompt: 'coffee> ',
|
||||||
historyFile: process.env.HOME ? path.join(process.env.HOME, '.coffee_history') : void 0,
|
historyFile: process.env.HOME ? path.join(process.env.HOME, '.coffee_history') : void 0,
|
||||||
historyMaxInputSize: 10240,
|
historyMaxInputSize: 10240,
|
||||||
"eval": function(input, context, filename, cb) {
|
"eval": function(input, context, filename, cb) {
|
||||||
var Assign, Block, Literal, Value, ast, err, js, _ref1;
|
var Assign, Block, Literal, Value, ast, err, js, _ref;
|
||||||
input = input.replace(/\uFF00/g, '\n');
|
input = input.replace(/\uFF00/g, '\n');
|
||||||
input = input.replace(/^\(([\s\S]*)\n\)$/m, '$1');
|
input = input.replace(/^\(([\s\S]*)\n\)$/m, '$1');
|
||||||
_ref1 = require('./nodes'), Block = _ref1.Block, Assign = _ref1.Assign, Value = _ref1.Value, Literal = _ref1.Literal;
|
_ref = require('./nodes'), Block = _ref.Block, Assign = _ref.Assign, Value = _ref.Value, Literal = _ref.Literal;
|
||||||
try {
|
try {
|
||||||
ast = CoffeeScript.nodes(input);
|
ast = CoffeeScript.nodes(input);
|
||||||
ast = new Block([new Assign(new Value(new Literal('_')), ast, '=')]);
|
ast = new Block([new Assign(new Value(new Literal('_')), ast, '=')]);
|
||||||
|
@ -33,7 +33,8 @@
|
||||||
return cb(null, vm.runInContext(js, context, filename));
|
return cb(null, vm.runInContext(js, context, filename));
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
err = _error;
|
err = _error;
|
||||||
return cb(prettyErrorMessage(err, filename, input, true));
|
err.code || (err.code = input);
|
||||||
|
return cb(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -132,13 +133,13 @@
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
start: function(opts) {
|
start: function(opts) {
|
||||||
var build, major, minor, repl, _ref1;
|
var build, major, minor, repl, _ref;
|
||||||
if (opts == null) {
|
if (opts == null) {
|
||||||
opts = {};
|
opts = {};
|
||||||
}
|
}
|
||||||
_ref1 = process.versions.node.split('.').map(function(n) {
|
_ref = process.versions.node.split('.').map(function(n) {
|
||||||
return parseInt(n);
|
return parseInt(n);
|
||||||
}), major = _ref1[0], minor = _ref1[1], build = _ref1[2];
|
}), major = _ref[0], minor = _ref[1], build = _ref[2];
|
||||||
if (major === 0 && minor < 8) {
|
if (major === 0 && minor < 8) {
|
||||||
console.warn("Node 0.8.0+ required for CoffeeScript REPL");
|
console.warn("Node 0.8.0+ required for CoffeeScript REPL");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|
|
@ -20,6 +20,17 @@ fileExtensions = ['.coffee', '.litcoffee', '.coffee.md']
|
||||||
# Expose helpers for testing.
|
# Expose helpers for testing.
|
||||||
exports.helpers = helpers
|
exports.helpers = helpers
|
||||||
|
|
||||||
|
# Function wrapper to add source file information to SyntaxErrors thrown by the
|
||||||
|
# lexer/parser/compiler.
|
||||||
|
withPrettyErrors = (fn) ->
|
||||||
|
(code, options = {}) ->
|
||||||
|
try
|
||||||
|
fn.call @, code, options
|
||||||
|
catch err
|
||||||
|
err.code or= code
|
||||||
|
err.filename or= options.filename
|
||||||
|
throw err
|
||||||
|
|
||||||
# Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
|
# Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
|
||||||
#
|
#
|
||||||
# If `options.sourceMap` is specified, then `options.filename` must also be specified. All
|
# If `options.sourceMap` is specified, then `options.filename` must also be specified. All
|
||||||
|
@ -29,7 +40,7 @@ exports.helpers = helpers
|
||||||
# in which case this returns a `{js, v3SourceMap, sourceMap}`
|
# in which case this returns a `{js, v3SourceMap, sourceMap}`
|
||||||
# object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for doing programatic
|
# object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for doing programatic
|
||||||
# lookups.
|
# lookups.
|
||||||
exports.compile = compile = (code, options = {}) ->
|
exports.compile = compile = withPrettyErrors (code, options) ->
|
||||||
{merge} = helpers
|
{merge} = helpers
|
||||||
|
|
||||||
if options.sourceMap
|
if options.sourceMap
|
||||||
|
@ -70,13 +81,13 @@ exports.compile = compile = (code, options = {}) ->
|
||||||
js
|
js
|
||||||
|
|
||||||
# Tokenize a string of CoffeeScript code, and return the array of tokens.
|
# Tokenize a string of CoffeeScript code, and return the array of tokens.
|
||||||
exports.tokens = (code, options) ->
|
exports.tokens = withPrettyErrors (code, options) ->
|
||||||
lexer.tokenize code, options
|
lexer.tokenize code, options
|
||||||
|
|
||||||
# Parse a string of CoffeeScript code or an array of lexed tokens, and
|
# Parse a string of CoffeeScript code or an array of lexed tokens, and
|
||||||
# return the AST. You can then compile it by calling `.compile()` on the root,
|
# return the AST. You can then compile it by calling `.compile()` on the root,
|
||||||
# or traverse it by using `.traverseChildren()` with a callback.
|
# or traverse it by using `.traverseChildren()` with a callback.
|
||||||
exports.nodes = (source, options) ->
|
exports.nodes = withPrettyErrors (source, options) ->
|
||||||
if typeof source is 'string'
|
if typeof source is 'string'
|
||||||
parser.parse lexer.tokenize source, options
|
parser.parse lexer.tokenize source, options
|
||||||
else
|
else
|
||||||
|
@ -150,8 +161,8 @@ compileFile = (filename, sourceMap) ->
|
||||||
# As the filename and code of a dynamically loaded file will be different
|
# As the filename and code of a dynamically loaded file will be different
|
||||||
# from the original file compiled with CoffeeScript.run, add that
|
# from the original file compiled with CoffeeScript.run, add that
|
||||||
# information to error so it can be pretty-printed later.
|
# information to error so it can be pretty-printed later.
|
||||||
err.filename = filename
|
err.filename or= filename
|
||||||
err.code = stripped
|
err.code or= stripped
|
||||||
throw err
|
throw err
|
||||||
|
|
||||||
answer
|
answer
|
||||||
|
|
|
@ -141,8 +141,7 @@ compileScript = (file, input, base=null) ->
|
||||||
catch err
|
catch err
|
||||||
CoffeeScript.emit 'failure', err, task
|
CoffeeScript.emit 'failure', err, task
|
||||||
return if CoffeeScript.listeners('failure').length
|
return if CoffeeScript.listeners('failure').length
|
||||||
useColors = process.stdout.isTTY and not process.env.NODE_DISABLE_COLORS
|
message = err.stack or "#{err}"
|
||||||
message = helpers.prettyErrorMessage err, file or '[stdin]', input, useColors
|
|
||||||
if o.watch
|
if o.watch
|
||||||
printLine message + '\x07'
|
printLine message + '\x07'
|
||||||
else
|
else
|
||||||
|
|
|
@ -134,44 +134,45 @@ exports.isCoffee = (file) -> /\.((lit)?coffee|coffee\.md)$/.test file
|
||||||
# Determine if a filename represents a Literate CoffeeScript file.
|
# Determine if a filename represents a Literate CoffeeScript file.
|
||||||
exports.isLiterate = (file) -> /\.(litcoffee|coffee\.md)$/.test file
|
exports.isLiterate = (file) -> /\.(litcoffee|coffee\.md)$/.test file
|
||||||
|
|
||||||
# Throws a SyntaxError with a source file location data attached to it in a
|
# Throws a SyntaxError from a given location.
|
||||||
# property called `location`.
|
# The error's `toString` will return an error message following the "standard"
|
||||||
|
# format <filename>:<line>:<col>: <message> plus the line with the error and a
|
||||||
|
# marker showing where the error is.
|
||||||
exports.throwSyntaxError = (message, location) ->
|
exports.throwSyntaxError = (message, location) ->
|
||||||
location.last_line ?= location.first_line
|
|
||||||
location.last_column ?= location.first_column
|
|
||||||
error = new SyntaxError message
|
error = new SyntaxError message
|
||||||
error.location = location
|
error.location = location
|
||||||
|
error.toString = syntaxErrorToString
|
||||||
|
|
||||||
|
# Prevent compiler error from showing the compiler's stacktrace.
|
||||||
|
delete error.stack
|
||||||
|
|
||||||
throw error
|
throw error
|
||||||
|
|
||||||
# Creates a nice error message like, following the "standard" format
|
syntaxErrorToString = ->
|
||||||
# <filename>:<line>:<col>: <message> plus the line with the error and a marker
|
return Error::toString.call @ unless @code and @location
|
||||||
# showing where the error is.
|
|
||||||
exports.prettyErrorMessage = (error, filename, code, useColors) ->
|
|
||||||
return error.stack or "#{error}" unless error.location
|
|
||||||
|
|
||||||
# Prefer original source file information stored in the error if present.
|
{first_line, first_column, last_line, last_column} = @location
|
||||||
filename = error.filename or filename
|
last_line ?= first_line
|
||||||
code = error.code or code
|
last_column ?= first_column
|
||||||
|
|
||||||
{first_line, first_column, last_line, last_column} = error.location
|
filename = @filename or '[stdin]'
|
||||||
codeLine = code.split('\n')[first_line]
|
codeLine = @code.split('\n')[first_line]
|
||||||
start = first_column
|
start = first_column
|
||||||
# Show only the first line on multi-line errors.
|
# Show only the first line on multi-line errors.
|
||||||
end = if first_line is last_line then last_column + 1 else codeLine.length
|
end = if first_line is last_line then last_column + 1 else codeLine.length
|
||||||
marker = repeat(' ', start) + repeat('^', end - start)
|
marker = repeat(' ', start) + repeat('^', end - start)
|
||||||
|
|
||||||
if useColors
|
# Check to see if we're running on a color-enabled TTY.
|
||||||
|
if process?
|
||||||
|
colorsEnabled = process.stdout.isTTY and not process.env.NODE_DISABLE_COLORS
|
||||||
|
|
||||||
|
if @colorful ? colorsEnabled
|
||||||
colorize = (str) -> "\x1B[1;31m#{str}\x1B[0m"
|
colorize = (str) -> "\x1B[1;31m#{str}\x1B[0m"
|
||||||
codeLine = codeLine[...start] + colorize(codeLine[start...end]) + codeLine[end..]
|
codeLine = codeLine[...start] + colorize(codeLine[start...end]) + codeLine[end..]
|
||||||
marker = colorize marker
|
marker = colorize marker
|
||||||
|
|
||||||
message = """
|
"""
|
||||||
#{filename}:#{first_line + 1}:#{first_column + 1}: error: #{error.message}
|
#{filename}:#{first_line + 1}:#{first_column + 1}: error: #{@message}
|
||||||
#{codeLine}
|
#{codeLine}
|
||||||
#{marker}
|
#{marker}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Uncomment to add stacktrace.
|
|
||||||
#message += "\n#{error.stack}"
|
|
||||||
|
|
||||||
message
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ path = require 'path'
|
||||||
vm = require 'vm'
|
vm = require 'vm'
|
||||||
nodeREPL = require 'repl'
|
nodeREPL = require 'repl'
|
||||||
CoffeeScript = require './coffee-script'
|
CoffeeScript = require './coffee-script'
|
||||||
{merge, prettyErrorMessage} = require './helpers'
|
{merge} = require './helpers'
|
||||||
|
|
||||||
replDefaults =
|
replDefaults =
|
||||||
prompt: 'coffee> ',
|
prompt: 'coffee> ',
|
||||||
|
@ -29,7 +29,9 @@ replDefaults =
|
||||||
js = ast.compile bare: yes, locals: Object.keys(context)
|
js = ast.compile bare: yes, locals: Object.keys(context)
|
||||||
cb null, vm.runInContext(js, context, filename)
|
cb null, vm.runInContext(js, context, filename)
|
||||||
catch err
|
catch err
|
||||||
cb prettyErrorMessage(err, filename, input, yes)
|
# AST's `compile` does not add source code information to syntax errors.
|
||||||
|
err.code or= input
|
||||||
|
cb err
|
||||||
|
|
||||||
addMultilineHandler = (repl) ->
|
addMultilineHandler = (repl) ->
|
||||||
{rli, inputStream, outputStream} = repl
|
{rli, inputStream, outputStream} = repl
|
||||||
|
|
|
@ -4,12 +4,10 @@
|
||||||
# Ensure that errors of different kinds (lexer, parser and compiler) are shown
|
# Ensure that errors of different kinds (lexer, parser and compiler) are shown
|
||||||
# in a consistent way.
|
# in a consistent way.
|
||||||
|
|
||||||
{prettyErrorMessage} = CoffeeScript.helpers
|
|
||||||
|
|
||||||
assertErrorFormat = (code, expectedErrorFormat) ->
|
assertErrorFormat = (code, expectedErrorFormat) ->
|
||||||
throws (-> CoffeeScript.run code), (err) ->
|
throws (-> CoffeeScript.run code), (err) ->
|
||||||
message = prettyErrorMessage err, 'test.coffee', code
|
err.colorful = no
|
||||||
eq expectedErrorFormat, message
|
eq expectedErrorFormat, "#{err}"
|
||||||
yes
|
yes
|
||||||
|
|
||||||
test "lexer errors formating", ->
|
test "lexer errors formating", ->
|
||||||
|
@ -18,7 +16,7 @@ test "lexer errors formating", ->
|
||||||
insideOutObject = }{
|
insideOutObject = }{
|
||||||
''',
|
''',
|
||||||
'''
|
'''
|
||||||
test.coffee:2:19: error: unmatched }
|
[stdin]:2:19: error: unmatched }
|
||||||
insideOutObject = }{
|
insideOutObject = }{
|
||||||
^
|
^
|
||||||
'''
|
'''
|
||||||
|
@ -28,7 +26,7 @@ test "parser error formating", ->
|
||||||
foo in bar or in baz
|
foo in bar or in baz
|
||||||
''',
|
''',
|
||||||
'''
|
'''
|
||||||
test.coffee:1:15: error: unexpected RELATION
|
[stdin]:1:15: error: unexpected RELATION
|
||||||
foo in bar or in baz
|
foo in bar or in baz
|
||||||
^^
|
^^
|
||||||
'''
|
'''
|
||||||
|
@ -38,7 +36,7 @@ test "compiler error formatting", ->
|
||||||
evil = (foo, eval, bar) ->
|
evil = (foo, eval, bar) ->
|
||||||
''',
|
''',
|
||||||
'''
|
'''
|
||||||
test.coffee:1:14: error: parameter name "eval" is not allowed
|
[stdin]:1:14: error: parameter name "eval" is not allowed
|
||||||
evil = (foo, eval, bar) ->
|
evil = (foo, eval, bar) ->
|
||||||
^^^^
|
^^^^
|
||||||
'''
|
'''
|
||||||
|
|
Loading…
Reference in New Issue