From 60bc43de8e421dcfebdc24e9cdddd25a6ab152e4 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 2 Dec 2024 13:05:07 -0800 Subject: [PATCH] Fix error messages for unterminated ( and { If we hit an EOF token, and the character before the EOF is a newline, we should make EOF token start at the previous newline. That way any errors reported will occur on that line. For example "foo(\n" should report an error on line 1 even though the EOF technically occurs on line 2. [Bug #20918] https://bugs.ruby-lang.org/issues/20918 --- src/prism.c | 8 ++++++++ test/prism/errors/unterminated_block.txt | 4 ++++ test/prism/errors/unterminated_method_parameters.txt | 3 +++ test/prism/errors_test.rb | 11 +++++++++++ 4 files changed, 26 insertions(+) create mode 100644 test/prism/errors/unterminated_block.txt create mode 100644 test/prism/errors/unterminated_method_parameters.txt diff --git a/src/prism.c b/src/prism.c index 1b3cb10b61..a968e2dbbc 100644 --- a/src/prism.c +++ b/src/prism.c @@ -10700,6 +10700,14 @@ parser_lex(pm_parser_t *parser) { // We'll check if we're at the end of the file. If we are, then we // need to return the EOF token. if (parser->current.end >= parser->end) { + // If we hit EOF, but the EOF came immediately after a newline, + // set the start of the token to the newline. This way any EOF + // errors will be reported as happening on that line rather than + // a line after. For example "foo(\n" should report an error + // on line 1 even though EOF technically occurs on line 2. + if (parser->current.start > parser->start && (*(parser->current.start - 1) == '\n')) { + parser->current.start -= 1; + } LEX(PM_TOKEN_EOF); } diff --git a/test/prism/errors/unterminated_block.txt b/test/prism/errors/unterminated_block.txt new file mode 100644 index 0000000000..8cc772db16 --- /dev/null +++ b/test/prism/errors/unterminated_block.txt @@ -0,0 +1,4 @@ +foo { + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected a block beginning with `{` to end with `}` + diff --git a/test/prism/errors/unterminated_method_parameters.txt b/test/prism/errors/unterminated_method_parameters.txt new file mode 100644 index 0000000000..e71371ba16 --- /dev/null +++ b/test/prism/errors/unterminated_method_parameters.txt @@ -0,0 +1,3 @@ +foo( + ^ unexpected end-of-input; expected a `)` to close the arguments + diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index f46cb942a2..a96c2e488d 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -32,6 +32,17 @@ class ErrorsTest < TestCase end end + def test_newline_preceding_eof + err = Prism.parse("foo(").errors.first + assert_equal 1, err.location.start_line + + err = Prism.parse("foo(\n").errors.first + assert_equal 1, err.location.start_line + + err = Prism.parse("foo(\n\n\n\n\n").errors.first + assert_equal 5, err.location.start_line + end + def test_embdoc_ending source = <<~RUBY =begin\n=end