From b7afe6b236a42e88294cc77495e386113f99cdcc Mon Sep 17 00:00:00 2001 From: yuyi Date: Wed, 9 Aug 2023 13:49:47 +0800 Subject: [PATCH] scanner: add error for invalid newline rune literal, make errors more informative (#19091) --- vlib/v/scanner/scanner.v | 28 ++++++++++++++----- .../tests/empty_character_literal_err.out | 6 ++-- .../tests/newline_character_literal_err.out | 13 +++++++++ .../tests/newline_character_literal_err.vv | 5 ++++ 4 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 vlib/v/scanner/tests/newline_character_literal_err.out create mode 100644 vlib/v/scanner/tests/newline_character_literal_err.vv diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index 18f35a764d..c0e38334e4 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -1472,17 +1472,23 @@ fn (mut s Scanner) ident_char() string { u := c.runes() if u.len != 1 { if escaped_hex || escaped_unicode { - s.error('invalid character literal `${orig}` => `${c}` (${u}) (escape sequence did not refer to a singular rune)') + s.error_with_pos('invalid character literal `${orig}` => `${c}` (${u}) (escape sequence did not refer to a singular rune)', + lspos) } else if u.len == 0 { s.add_error_detail_with_pos('use quotes for strings, backticks for characters', lspos) - s.error('invalid empty character literal `${orig}`') + s.error_with_pos('invalid empty character literal `${orig}`', lspos) } else { s.add_error_detail_with_pos('use quotes for strings, backticks for characters', lspos) - s.error('invalid character literal `${orig}` => `${c}` (${u}) (more than one character)') + s.error_with_pos('invalid character literal `${orig}` => `${c}` (${u}) (more than one character)', + lspos) } } + } else if c == '\n' { + s.add_error_detail_with_pos('use quotes for strings, backticks for characters', + lspos) + s.error_with_pos('invalid character literal, use \`\\n\` instead', lspos) } // Escapes a `'` character if c == "'" { @@ -1566,15 +1572,19 @@ fn (mut s Scanner) eat_details() string { } pub fn (mut s Scanner) warn(msg string) { - if s.pref.warns_are_errors { - s.error(msg) - return - } pos := token.Pos{ line_nr: s.line_nr pos: s.pos col: s.current_column() - 1 } + s.warn_with_pos(msg, pos) +} + +pub fn (mut s Scanner) warn_with_pos(msg string, pos token.Pos) { + if s.pref.warns_are_errors { + s.error_with_pos(msg, pos) + return + } details := s.eat_details() if s.pref.output_mode == .stdout && !s.pref.check_only { util.show_compiler_message('warning:', @@ -1604,6 +1614,10 @@ pub fn (mut s Scanner) error(msg string) { pos: s.pos col: s.current_column() - 1 } + s.error_with_pos(msg, pos) +} + +pub fn (mut s Scanner) error_with_pos(msg string, pos token.Pos) { details := s.eat_details() if s.pref.output_mode == .stdout && !s.pref.check_only { util.show_compiler_message('error:', diff --git a/vlib/v/scanner/tests/empty_character_literal_err.out b/vlib/v/scanner/tests/empty_character_literal_err.out index 1c47473954..8354d7b773 100644 --- a/vlib/v/scanner/tests/empty_character_literal_err.out +++ b/vlib/v/scanner/tests/empty_character_literal_err.out @@ -1,10 +1,10 @@ -vlib/v/scanner/tests/empty_character_literal_err.vv:2:8: error: invalid empty character literal `` +vlib/v/scanner/tests/empty_character_literal_err.vv:2:7: error: invalid empty character literal `` 1 | fn main() { 2 | a := `` - | ^ + | ^ 3 | println(a) 4 | } -Details: +Details: vlib/v/scanner/tests/empty_character_literal_err.vv:2:7: details: use quotes for strings, backticks for characters 1 | fn main() { 2 | a := `` diff --git a/vlib/v/scanner/tests/newline_character_literal_err.out b/vlib/v/scanner/tests/newline_character_literal_err.out new file mode 100644 index 0000000000..3fafff92c0 --- /dev/null +++ b/vlib/v/scanner/tests/newline_character_literal_err.out @@ -0,0 +1,13 @@ +vlib/v/scanner/tests/newline_character_literal_err.vv:2:7: error: invalid character literal, use `\n` instead + 1 | fn main() { + 2 | a := ` + | ^ + 3 | ` + 4 | println(a) +Details: +vlib/v/scanner/tests/newline_character_literal_err.vv:2:7: details: use quotes for strings, backticks for characters + 1 | fn main() { + 2 | a := ` + | ^ + 3 | ` + 4 | println(a) diff --git a/vlib/v/scanner/tests/newline_character_literal_err.vv b/vlib/v/scanner/tests/newline_character_literal_err.vv new file mode 100644 index 0000000000..0634f664f1 --- /dev/null +++ b/vlib/v/scanner/tests/newline_character_literal_err.vv @@ -0,0 +1,5 @@ +fn main() { + a := ` +` + println(a) +}