From df8384b62e22ab99cc7be4b0d747e8e0f61c1241 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Thu, 30 Dec 2021 18:20:27 +0200 Subject: [PATCH] v.scanner: report the start of unfinished string literals too --- vlib/v/scanner/scanner.v | 38 +++++++++++++++++++ .../tests/unfinished_string_literal_err.out | 10 +++++ .../tests/unfinished_string_literal_err.vv | 6 +++ 3 files changed, 54 insertions(+) create mode 100644 vlib/v/scanner/tests/unfinished_string_literal_err.out create mode 100644 vlib/v/scanner/tests/unfinished_string_literal_err.vv diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index 0bcb4295b7..7a50884e9f 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -54,6 +54,7 @@ pub mut: tidx int eofs int pref &pref.Preferences + error_details []string errors []errors.Error warnings []errors.Warning notices []errors.Notice @@ -1142,6 +1143,11 @@ fn (s &Scanner) count_symbol_before(p int, sym byte) int { [direct_array_access] fn (mut s Scanner) ident_string() string { + lspos := token.Position{ + line_nr: s.line_nr + pos: s.pos + col: s.pos - s.last_nl_pos - 1 + } q := s.text[s.pos] is_quote := q == scanner.single_quote || q == scanner.double_quote is_raw := is_quote && s.pos > 0 && s.text[s.pos - 1] == `r` && !s.is_inside_string @@ -1172,6 +1178,9 @@ fn (mut s Scanner) ident_string() string { for { s.pos++ if s.pos >= s.text.len { + if lspos.line_nr + 1 < s.line_nr { + s.add_error_detail_with_pos('literal started here', lspos) + } s.error('unfinished string literal') break } @@ -1396,6 +1405,25 @@ pub fn (mut s Scanner) note(msg string) { } } +// call this *before* calling error or warn +pub fn (mut s Scanner) add_error_detail(msg string) { + s.error_details << msg +} + +pub fn (mut s Scanner) add_error_detail_with_pos(msg string, pos token.Position) { + details := util.formatted_error('details:', msg, s.file_path, pos) + s.add_error_detail(details) +} + +fn (mut s Scanner) eat_details() string { + mut details := '' + if s.error_details.len > 0 { + details = s.error_details.join('\n') + s.error_details = [] + } + return details +} + pub fn (mut s Scanner) warn(msg string) { if s.pref.warns_are_errors { s.error(msg) @@ -1406,8 +1434,12 @@ pub fn (mut s Scanner) warn(msg string) { pos: s.pos col: s.current_column() - 1 } + details := s.eat_details() if s.pref.output_mode == .stdout && !s.pref.check_only { eprintln(util.formatted_error('warning:', msg, s.file_path, pos)) + if details.len > 0 { + eprintln(details) + } } else { if s.pref.message_limit >= 0 && s.warnings.len >= s.pref.message_limit { s.should_abort = true @@ -1418,6 +1450,7 @@ pub fn (mut s Scanner) warn(msg string) { pos: pos reporter: .scanner message: msg + details: details } } } @@ -1428,8 +1461,12 @@ pub fn (mut s Scanner) error(msg string) { pos: s.pos col: s.current_column() - 1 } + details := s.eat_details() if s.pref.output_mode == .stdout && !s.pref.check_only { eprintln(util.formatted_error('error:', msg, s.file_path, pos)) + if details.len > 0 { + eprintln(details) + } exit(1) } else { if s.pref.fatal_errors { @@ -1444,6 +1481,7 @@ pub fn (mut s Scanner) error(msg string) { pos: pos reporter: .scanner message: msg + details: details } } } diff --git a/vlib/v/scanner/tests/unfinished_string_literal_err.out b/vlib/v/scanner/tests/unfinished_string_literal_err.out new file mode 100644 index 0000000000..65b9377ceb --- /dev/null +++ b/vlib/v/scanner/tests/unfinished_string_literal_err.out @@ -0,0 +1,10 @@ +vlib/v/scanner/tests/unfinished_string_literal_err.vv:7:1: error: unfinished string literal + 5 | + 6 | zzzz +vlib/v/scanner/tests/unfinished_string_literal_err.vv:4:6: details: literal started here + 2 | a := 'abc' + 3 | println(a) + 4 | x := 'asdka + | ^ + 5 | + 6 | zzzz diff --git a/vlib/v/scanner/tests/unfinished_string_literal_err.vv b/vlib/v/scanner/tests/unfinished_string_literal_err.vv new file mode 100644 index 0000000000..7a1cb5b9c7 --- /dev/null +++ b/vlib/v/scanner/tests/unfinished_string_literal_err.vv @@ -0,0 +1,6 @@ +// something +a := 'abc' +println(a) +x := 'asdka + +zzzz