scanner: fix new string interpolation println('{a}{b}{c}{d}') (#16258)

This commit is contained in:
yuyi 2022-10-31 02:18:31 +08:00 committed by GitHub
parent 914f03a1a2
commit 64cbadc6f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 16 deletions

View file

@ -47,6 +47,7 @@ const verify_known_failing_exceptions = [
'vlib/builtin/int_test.v' /* special number formatting that should be tested */,
// TODOs and unfixed vfmt bugs
'vlib/v/gen/js/tests/js.v', /* local `hello` fn, gets replaced with module `hello` aliased as `hl` */
'vlib/v/tests/string_new_interpolation_test.v', /* new string interpolation */
]
const vfmt_verify_list = [

View file

@ -1214,7 +1214,7 @@ fn (mut s Scanner) ident_string() string {
u_escapes_pos << s.pos - 1
}
}
// ${var} (ignore in vfmt mode) (skip \$)
// '${var}' (ignore in vfmt mode) (skip \$)
if prevc == `$` && c == `{` && !is_raw
&& s.count_symbol_before(s.pos - 2, scanner.backslash) % 2 == 0 {
s.is_inside_string = true
@ -1223,7 +1223,7 @@ fn (mut s Scanner) ident_string() string {
s.pos -= 2
break
}
// $var
// '$var'
if prevc == `$` && util.is_name_char(c) && !is_raw
&& s.count_symbol_before(s.pos - 2, scanner.backslash) % 2 == 0 {
s.is_inside_string = true
@ -1231,7 +1231,7 @@ fn (mut s Scanner) ident_string() string {
s.pos -= 2
break
}
// {var} (ignore in vfmt mode) (skip \{)
// '{var}' (ignore in vfmt mode) (skip \{)
if c == `{` && util.is_name_char(s.text[s.pos + 1]) && prevc != `$` && !is_raw
&& s.count_symbol_before(s.pos - 1, scanner.backslash) % 2 == 0 {
// Detect certain strings with "{" that are not interpolation:
@ -1258,6 +1258,33 @@ fn (mut s Scanner) ident_string() string {
break
}
}
// '{var1}{var2}'
if prevc == `{` && util.is_name_char(c) && s.text[s.pos - 2] !in [`$`, `{`] && !is_raw
&& s.count_symbol_before(s.pos - 2, scanner.backslash) % 2 == 0 {
// Detect certain strings with "{" that are not interpolation:
// e.g. "{init: " (no "}" at the end)
mut is_valid_inter := true
for i := s.pos; i < s.text.len; i++ {
if s.text[i] == `}` {
// No } in this string, so it's not a valid `{x}` interpolation
break
}
if s.text[i] in [`=`, `:`, `\n`, s.inter_quote] {
// We reached the end of the line or string without reaching "}".
// Also if there's "=", there's no way it's a valid interpolation expression:
// e.g. `println("{a.b = 42}")` `println('{foo:bar}')`
is_valid_inter = false
break
}
}
if is_valid_inter {
s.is_inside_string = true
s.is_enclosed_inter = true
// so that s.pos points to $ at the next step
s.pos -= 2
break
}
}
if c != scanner.backslash {
backslash_count = 0
}

View file

@ -0,0 +1,9 @@
fn test_string_new_interpolation() {
a, b, c, d := 1, 2, 3, 4
println('{a}{b}{c}{d}')
assert '{a}{b}{c}{d}' == '1234'
println('{a} {b} {c} {d}')
assert '{a} {b} {c} {d}' == '1 2 3 4'
}