scanner, fmt: fix multi-level generics (#11517)
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('>')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,5 +23,5 @@ fn main() {
|
|||
// generic
|
||||
assert multi_generic_args<int, string>(0, 's')
|
||||
assert multi_generic_args<Foo1, Foo2>(Foo1{}, Foo2{})
|
||||
assert multi_generic_args<Foo<int>, Foo<int> >(Foo<int>{}, Foo<int>{})
|
||||
assert multi_generic_args<Foo<int>, Foo<int>>(Foo<int>{}, Foo<int>{})
|
||||
}
|
||||
|
|
|
@ -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] == `=` {
|
||||
s.pos += 2
|
||||
return s.new_token(.right_shift_assign, '', 3)
|
||||
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
|
||||
|
||||
|
@ -493,7 +522,7 @@ fn test_generic_detection() {
|
|||
// generic
|
||||
assert multi_generic_args<int, string>(0, 's')
|
||||
assert multi_generic_args<Foo1, Foo2>(Foo1{}, Foo2{})
|
||||
assert multi_generic_args<Foo<int>, Foo<int> >(Foo<int>{}, Foo<int>{})
|
||||
assert multi_generic_args<Foo<int>, Foo<int>>(Foo<int>{}, Foo<int>{})
|
||||
|
||||
// TODO: assert multi_generic_args<Foo<int>, Foo<int>>(Foo1{}, Foo2{})
|
||||
assert multi_generic_args<simplemodule.Data, int>(simplemodule.Data{}, 0)
|
||||
|
|
Loading…
Reference in New Issue