[PRISM] Include file and line in error message

This commit is contained in:
Kevin Newton 2024-03-27 13:37:01 -04:00
parent 51e6becd39
commit eb995a6410
4 changed files with 25 additions and 13 deletions

View File

@ -529,7 +529,7 @@ assert_equal %q{1}, %q{
}
def assert_syntax_error expected, code, message = ''
assert_match /^#{Regexp.escape(expected)}/,
"begin eval(%q{#{code}}, nil, '', 0)"'; rescue SyntaxError => e; e.message[/(?:\A:(?:\d+:)?(?: syntax error,)?|\^) (.*)/, 1] end', message
"begin eval(%q{#{code}}, nil, '', 0)"'; rescue SyntaxError => e; e.message[/(?:\^|\A:(?:\d+:)?(?! syntax errors? found)(?: syntax error,)?) (.*)/, 1] end', message
end
assert_syntax_error "unterminated string meets end of file", '().."', '[ruby-dev:29732]'
assert_equal %q{[]}, %q{$&;[]}, '[ruby-dev:31068]'

View File

@ -19686,7 +19686,15 @@ pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list,
// blank lines based on the maximum number of digits in the line numbers
// that are going to be displaid.
pm_error_format_t error_format;
int32_t max_line_number = errors[error_list->size - 1].line - start_line;
int32_t first_line_number = errors[0].line;
int32_t last_line_number = errors[error_list->size - 1].line;
// If we have a maximum line number that is negative, then we're going to
// use the absolute value for comparison but multiple by 10 to additionally
// have a column for the negative sign.
if (first_line_number < 0) first_line_number = (-first_line_number) * 10;
if (last_line_number < 0) last_line_number = (-last_line_number) * 10;
int32_t max_line_number = first_line_number > last_line_number ? first_line_number : last_line_number;
if (max_line_number < 10) {
if (colorize) {
@ -19841,7 +19849,7 @@ pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list,
// Here we determine how many lines of padding to display after the
// error, depending on where the next error is in source.
last_line = error->line;
int32_t next_line = (index == error_list->size - 1) ? ((int32_t) newline_list->size) : errors[index + 1].line;
int32_t next_line = (index == error_list->size - 1) ? (((int32_t) newline_list->size) + parser->start_line) : errors[index + 1].line;
if (next_line - last_line > 1) {
pm_buffer_append_string(buffer, " ", 2);

View File

@ -8373,9 +8373,13 @@ pm_parse_process_error_utf8_p(const pm_parser_t *parser, const pm_location_t *lo
static VALUE
pm_parse_process_error(const pm_parse_result_t *result)
{
const pm_diagnostic_t *head = (const pm_diagnostic_t *) result->parser.error_list.head;
const pm_parser_t *parser = &result->parser;
const pm_diagnostic_t *head = (const pm_diagnostic_t *) parser->error_list.head;
bool valid_utf8 = true;
pm_buffer_t buffer = { 0 };
const pm_string_t *filepath = &parser->filepath;
for (const pm_diagnostic_t *error = head; error != NULL; error = (const pm_diagnostic_t *) error->node.next) {
// Any errors with the level PM_ERROR_LEVEL_ARGUMENT effectively take
// over as the only argument that gets raised. This is to allow priority
@ -8389,20 +8393,24 @@ pm_parse_process_error(const pm_parse_result_t *result)
// contain invalid byte sequences. So if any source examples include
// invalid UTF-8 byte sequences, we will skip showing source examples
// entirely.
if (valid_utf8 && !pm_parse_process_error_utf8_p(&result->parser, &error->location)) {
if (valid_utf8 && !pm_parse_process_error_utf8_p(parser, &error->location)) {
valid_utf8 = false;
}
}
pm_buffer_t buffer = { 0 };
pm_buffer_append_string(&buffer, "syntax errors found\n", 20);
pm_buffer_append_format(
&buffer,
"%.*s:%" PRIi32 ": syntax error%s found\n",
(int) pm_string_length(filepath),
pm_string_source(filepath),
(int32_t) pm_location_line_number(parser, &head->location),
(parser->error_list.size > 1) ? "s" : ""
);
if (valid_utf8) {
pm_parser_errors_format(&result->parser, &result->parser.error_list, &buffer, rb_stderr_tty_p(), true);
}
else {
const pm_string_t *filepath = &result->parser.filepath;
for (const pm_diagnostic_t *error = head; error != NULL; error = (pm_diagnostic_t *) error->node.next) {
if (error != head) pm_buffer_append_byte(&buffer, '\n');
pm_buffer_append_format(&buffer, "%.*s:%" PRIi32 ": %s", (int) pm_string_length(filepath), pm_string_source(filepath), (int32_t) pm_location_line_number(&result->parser, &error->location), error->message);

View File

@ -33,8 +33,6 @@ MSpec.register(:exclude, "A Symbol literal raises an SyntaxError at parse time w
## Core
MSpec.register(:exclude, "IO.popen with a leading Array argument accepts a trailing Hash of Process.exec options")
MSpec.register(:exclude, "IO.popen with a leading Array argument accepts an IO mode argument following the Array")
MSpec.register(:exclude, "Kernel#eval includes file and line information in syntax error")
MSpec.register(:exclude, "Kernel#eval evaluates string with given filename and negative linenumber")
MSpec.register(:exclude, "Kernel#eval with a magic encoding comment allows spaces before the magic encoding comment")
MSpec.register(:exclude, "Kernel#eval with a magic encoding comment allows a shebang line and some spaces before the magic encoding comment")
MSpec.register(:exclude, "TracePoint#eval_script is the evald source code")
@ -60,6 +58,4 @@ MSpec.register(:exclude, "Coverage.result does not clear counters when stop: fal
MSpec.register(:exclude, "Coverage.result clears counters (sets 0 values) when stop: false and clear: true specified")
MSpec.register(:exclude, "Coverage.result does not clear counters when stop: false and clear: false specified")
MSpec.register(:exclude, "Coverage.start measures coverage within eval")
MSpec.register(:exclude, "ERB#filename raises an exception if there are errors processing content")
MSpec.register(:exclude, "ERB#filename uses '(erb)' as filename when filename is not set")
MSpec.register(:exclude, "Socket.gethostbyaddr using an IPv6 address with an explicit address family raises SocketError when the address is not supported by the family")