From 916b1b41df6d4a787b8b2cc5b6994b9545ea441e Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 14 Apr 2026 12:45:25 +0300 Subject: [PATCH] scanner: v parser should provide more accurate error msg (fixes #25309) --- vlib/v/scanner/scanner.v | 20 +++++++++++++++++++ .../string_interpolation_missing_rcbr_err.out | 7 +++++++ .../string_interpolation_missing_rcbr_err.vv | 6 ++++++ 3 files changed, 33 insertions(+) create mode 100644 vlib/v/scanner/tests/string_interpolation_missing_rcbr_err.out create mode 100644 vlib/v/scanner/tests/string_interpolation_missing_rcbr_err.vv diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index 06354b1a1..2b1debeb3 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -812,6 +812,16 @@ pub fn (mut s Scanner) text_scan() token.Token { return s.new_token(.question, '?', 1) } single_quote, double_quote { + if s.is_likely_unclosed_string_interpolation(c) { + s.error_with_pos('expected `}` to close string interpolation', token.Pos{ + len: 1 + line_nr: s.line_nr + pos: s.pos + col: u16_col(s.current_column() - 1) + file_idx: s.file_idx + last_line: s.line_nr + }) + } s.str_helper_tokens << c start_line := s.line_nr ident_string := s.ident_string() @@ -1857,6 +1867,16 @@ fn (s Scanner) str_quote() u8 { return 255 } +@[direct_array_access; inline] +fn (s &Scanner) is_likely_unclosed_string_interpolation(current_quote u8) bool { + if current_quote != s.quote || s.str_helper_tokens.len == 0 || s.str_quote() != 255 + || s.all_tokens.len == 0 { + return false + } + prev_tok := s.all_tokens[s.all_tokens.len - 1] + return prev_tok.kind in [.number, .string, .chartoken, .rpar, .rsbr, .rcbr] +} + @[inline] fn u16_col(col int) u16 { return if col < 0 { u16(0) } else { u16(col) } diff --git a/vlib/v/scanner/tests/string_interpolation_missing_rcbr_err.out b/vlib/v/scanner/tests/string_interpolation_missing_rcbr_err.out new file mode 100644 index 000000000..f84799026 --- /dev/null +++ b/vlib/v/scanner/tests/string_interpolation_missing_rcbr_err.out @@ -0,0 +1,7 @@ +vlib/v/scanner/tests/string_interpolation_missing_rcbr_err.vv:4:23: error: expected `}` to close string interpolation + 2 | + 3 | fn main() { + 4 | broken := '${foo()' + '${bar})' + | ^ + 5 | _ = '\t${broken}' + 6 | } diff --git a/vlib/v/scanner/tests/string_interpolation_missing_rcbr_err.vv b/vlib/v/scanner/tests/string_interpolation_missing_rcbr_err.vv new file mode 100644 index 000000000..7dc212060 --- /dev/null +++ b/vlib/v/scanner/tests/string_interpolation_missing_rcbr_err.vv @@ -0,0 +1,6 @@ +module main + +fn main() { + broken := '${foo()' + '${bar})' + _ = '\t${broken}' +} -- 2.39.5