mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
scanner: fix multi-level string interpolation in if/match branch (#24805)
This commit is contained in:
parent
bd465b5254
commit
f7b6a420d8
3 changed files with 102 additions and 1 deletions
|
@ -45,7 +45,10 @@ fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type {
|
|||
inside_interface_deref_save := c.inside_interface_deref
|
||||
c.inside_interface_deref = true
|
||||
for i, mut expr in node.exprs {
|
||||
expected_type := c.expected_type
|
||||
c.expected_type = ast.string_type
|
||||
mut ftyp := c.expr(mut expr)
|
||||
c.expected_type = expected_type
|
||||
ftyp = c.type_resolver.get_type_or_default(expr, c.check_expr_option_or_result_call(expr,
|
||||
ftyp))
|
||||
if ftyp == ast.void_type || ftyp == 0 {
|
||||
|
|
|
@ -35,6 +35,8 @@ pub mut:
|
|||
is_inter_end bool
|
||||
is_enclosed_inter bool
|
||||
is_nested_enclosed_inter bool
|
||||
string_count int
|
||||
str_dollar_needs_rcbr []bool = []
|
||||
line_comment string
|
||||
last_lt int = -1 // position of latest <
|
||||
is_print_line_on_error bool
|
||||
|
@ -797,6 +799,12 @@ pub fn (mut s Scanner) text_scan() token.Token {
|
|||
return s.new_token(.question, '?', 1)
|
||||
}
|
||||
single_quote, double_quote {
|
||||
if s.string_count == 1 && s.str_dollar_needs_rcbr.len == 0 {
|
||||
s.string_count = 0
|
||||
return s.new_token(.string, '', 1)
|
||||
} else {
|
||||
s.string_count++
|
||||
}
|
||||
start_line := s.line_nr
|
||||
ident_string := s.ident_string()
|
||||
return s.new_multiline_token(.string, ident_string, ident_string.len + 2,
|
||||
|
@ -823,10 +831,14 @@ pub fn (mut s Scanner) text_scan() token.Token {
|
|||
// Skip { in `${` in strings
|
||||
if s.is_inside_string || s.is_enclosed_inter {
|
||||
if s.text[s.pos - 1] == `$` {
|
||||
s.str_dollar_needs_rcbr << true
|
||||
continue
|
||||
} else {
|
||||
s.str_dollar_needs_rcbr << false
|
||||
s.inter_cbr_count++
|
||||
}
|
||||
} else {
|
||||
s.str_dollar_needs_rcbr << false
|
||||
}
|
||||
return s.new_token(.lcbr, '', 1)
|
||||
}
|
||||
|
@ -840,7 +852,12 @@ pub fn (mut s Scanner) text_scan() token.Token {
|
|||
`}` {
|
||||
// s = `hello $name !`
|
||||
// s = `hello ${name} !`
|
||||
if (s.is_enclosed_inter || s.is_nested_enclosed_inter) && s.inter_cbr_count == 0 {
|
||||
if ((s.is_enclosed_inter || s.is_nested_enclosed_inter) && s.inter_cbr_count == 0)
|
||||
|| (s.all_tokens.last().kind != .string && s.str_dollar_needs_rcbr.len > 0
|
||||
&& s.str_dollar_needs_rcbr.last()) {
|
||||
if s.str_dollar_needs_rcbr.len > 0 {
|
||||
s.str_dollar_needs_rcbr.delete_last()
|
||||
}
|
||||
if s.pos < s.text.len - 1 {
|
||||
s.pos++
|
||||
} else {
|
||||
|
@ -854,6 +871,7 @@ pub fn (mut s Scanner) text_scan() token.Token {
|
|||
} else {
|
||||
s.is_enclosed_inter = false
|
||||
}
|
||||
s.string_count--
|
||||
return s.new_token(.string, '', 1)
|
||||
}
|
||||
if s.is_nested_enclosed_inter {
|
||||
|
@ -865,6 +883,14 @@ pub fn (mut s Scanner) text_scan() token.Token {
|
|||
ident_string := s.ident_string()
|
||||
return s.new_token(.string, ident_string, ident_string.len + 2) // + two quotes
|
||||
} else {
|
||||
if s.str_dollar_needs_rcbr.len > 0 {
|
||||
if s.str_dollar_needs_rcbr.last() {
|
||||
s.str_dollar_needs_rcbr.delete_last()
|
||||
s.pos++
|
||||
return s.new_token(.string, '', 1)
|
||||
}
|
||||
s.str_dollar_needs_rcbr.delete_last()
|
||||
}
|
||||
if s.inter_cbr_count > 0 {
|
||||
s.inter_cbr_count--
|
||||
}
|
||||
|
@ -1255,9 +1281,14 @@ pub fn (mut s Scanner) ident_string() string {
|
|||
// end of string
|
||||
if c == s.quote && (is_raw || backslash_count & 1 == 0) {
|
||||
// handle '123\\' backslash at the end
|
||||
s.string_count--
|
||||
break
|
||||
}
|
||||
if c == s.inter_quote && (s.is_inter_start || s.is_enclosed_inter) {
|
||||
s.string_count--
|
||||
break
|
||||
}
|
||||
if c == s.quote && s.string_count == 0 {
|
||||
break
|
||||
}
|
||||
if c == b_cr {
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
fn foo() ?string {
|
||||
return none
|
||||
}
|
||||
|
||||
fn test_string_interpolation_multi_level() {
|
||||
x := 0
|
||||
|
||||
assert '${if x == 0 {
|
||||
'${x}'
|
||||
} else {
|
||||
'${'${x + 1}'}'
|
||||
}}' == '0'
|
||||
|
||||
assert '${foo() or { '${if x == 0 {
|
||||
'${x}'
|
||||
} else {
|
||||
'${x + 1}'
|
||||
}}' }}' == '0'
|
||||
|
||||
println('${match true {
|
||||
true { '${x}' }
|
||||
else { '${x + 1}' }
|
||||
}}' == '0')
|
||||
|
||||
// codegen error
|
||||
// assert '${match true { true { '${x}' } else { '${x + 1}' } }}' == '0'
|
||||
|
||||
assert '${if x == 0 {
|
||||
'${match x {
|
||||
1 { x == 1 }
|
||||
else { x != 0 }
|
||||
}}'
|
||||
} else {
|
||||
''
|
||||
}}' == 'false'
|
||||
|
||||
assert '${if x == 0 {
|
||||
'${if x == 1 {
|
||||
'${if x == 2 {
|
||||
'${x + 2}'
|
||||
} else {
|
||||
'${1}'
|
||||
}}'
|
||||
} else {
|
||||
'${if x == 0 {
|
||||
'${match x {
|
||||
2 {
|
||||
'true'
|
||||
}
|
||||
else {
|
||||
'${x + 3}'
|
||||
}
|
||||
}}'
|
||||
} else {
|
||||
'${false}'
|
||||
}}'
|
||||
}}'
|
||||
} else {
|
||||
''
|
||||
}}' == '3'
|
||||
|
||||
assert '${if m := foo() {
|
||||
'${m}'
|
||||
} else {
|
||||
'${x + 1}'
|
||||
}}' == '1'
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue