mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
scanner, fmt: fix multi-level generics (#11517)
This commit is contained in:
parent
30e53c95c7
commit
9180647f99
@ -210,13 +210,14 @@ pub fn (mut f Fmt) short_module(name string) string {
|
||||
return f.mod2alias[name]
|
||||
}
|
||||
if name.ends_with('>') {
|
||||
x := name.trim_suffix('>').split('<')
|
||||
if x.len == 2 {
|
||||
main := f.short_module(x[0])
|
||||
genlist := x[1].split(',')
|
||||
genshorts := genlist.map(f.short_module(it)).join(',')
|
||||
return '$main<$genshorts>'
|
||||
generic_levels := name.trim_suffix('>').split('<')
|
||||
mut res := '${f.short_module(generic_levels[0])}'
|
||||
for i in 1 .. generic_levels.len {
|
||||
genshorts := generic_levels[i].split(',').map(f.short_module(it)).join(',')
|
||||
res += '<$genshorts'
|
||||
}
|
||||
res += '>'
|
||||
return res
|
||||
}
|
||||
vals := name.split('.')
|
||||
if vals.len < 2 {
|
||||
@ -1585,15 +1586,11 @@ fn (mut f Fmt) write_generic_call_if_require(node ast.CallExpr) {
|
||||
if node.concrete_types.len > 0 {
|
||||
f.write('<')
|
||||
for i, concrete_type in node.concrete_types {
|
||||
f.write(f.table.type_to_str_using_aliases(concrete_type, f.mod2alias))
|
||||
f.write(f.short_module(f.table.type_to_str_using_aliases(concrete_type, f.mod2alias)))
|
||||
if i != node.concrete_types.len - 1 {
|
||||
f.write(', ')
|
||||
}
|
||||
}
|
||||
// avoid `<Foo<int>>` => `<Foo<int> >`
|
||||
if f.out.last_n(1) == '>' {
|
||||
f.write(' ')
|
||||
}
|
||||
f.write('>')
|
||||
}
|
||||
}
|
||||
|
@ -916,9 +916,14 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||
s.pos++
|
||||
return s.new_token(.ge, '', 2)
|
||||
} else if nextc == `>` {
|
||||
if s.pos + 2 < s.text.len && s.text[s.pos + 2] == `=` {
|
||||
if s.pos + 2 < s.text.len {
|
||||
if s.text[s.pos + 2] == `=` {
|
||||
s.pos += 2
|
||||
return s.new_token(.right_shift_assign, '', 3)
|
||||
} else if s.text[s.pos + 2] in [`(`, `)`, `{`, `>`, `,`] {
|
||||
// multi-level generics such as Foo<Bar<baz>>{ }, func<Bar<baz>>( ), etc
|
||||
return s.new_token(.gt, '', 1)
|
||||
}
|
||||
}
|
||||
s.pos++
|
||||
return s.new_token(.right_shift, '', 2)
|
||||
|
@ -481,6 +481,35 @@ fn return_one<T>(rec int, useless T) T {
|
||||
return T(0)
|
||||
}
|
||||
|
||||
struct MultiLevel<T> {
|
||||
foo T
|
||||
}
|
||||
|
||||
fn get_multilevel_foo<T>(bar MultiLevel<T>) int {
|
||||
return bar.foo.foo
|
||||
}
|
||||
|
||||
fn get_multilevel_foo_2<T, U>(bar T, baz U) int {
|
||||
return bar.foo.foo + baz.foo.foo
|
||||
}
|
||||
|
||||
fn test_multi_level_generics() {
|
||||
one := MultiLevel<int>{
|
||||
foo: 10
|
||||
}
|
||||
two := MultiLevel<MultiLevel<int>>{
|
||||
foo: one
|
||||
}
|
||||
assert two.foo.foo == 10
|
||||
three := MultiLevel<MultiLevel<MultiLevel<int>>>{
|
||||
foo: two
|
||||
}
|
||||
assert three.foo.foo.foo == 10
|
||||
assert get_multilevel_foo<MultiLevel<int>>(two) == 10
|
||||
assert get_multilevel_foo_2<MultiLevel<MultiLevel<int>>, MultiLevel<MultiLevel<int>>>(two,
|
||||
two) == 20
|
||||
}
|
||||
|
||||
fn test_generic_detection() {
|
||||
v1, v2 := -1, 1
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user