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]
|
return f.mod2alias[name]
|
||||||
}
|
}
|
||||||
if name.ends_with('>') {
|
if name.ends_with('>') {
|
||||||
x := name.trim_suffix('>').split('<')
|
generic_levels := name.trim_suffix('>').split('<')
|
||||||
if x.len == 2 {
|
mut res := '${f.short_module(generic_levels[0])}'
|
||||||
main := f.short_module(x[0])
|
for i in 1 .. generic_levels.len {
|
||||||
genlist := x[1].split(',')
|
genshorts := generic_levels[i].split(',').map(f.short_module(it)).join(',')
|
||||||
genshorts := genlist.map(f.short_module(it)).join(',')
|
res += '<$genshorts'
|
||||||
return '$main<$genshorts>'
|
|
||||||
}
|
}
|
||||||
|
res += '>'
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
vals := name.split('.')
|
vals := name.split('.')
|
||||||
if vals.len < 2 {
|
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 {
|
if node.concrete_types.len > 0 {
|
||||||
f.write('<')
|
f.write('<')
|
||||||
for i, concrete_type in node.concrete_types {
|
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 {
|
if i != node.concrete_types.len - 1 {
|
||||||
f.write(', ')
|
f.write(', ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// avoid `<Foo<int>>` => `<Foo<int> >`
|
|
||||||
if f.out.last_n(1) == '>' {
|
|
||||||
f.write(' ')
|
|
||||||
}
|
|
||||||
f.write('>')
|
f.write('>')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,5 +23,5 @@ fn main() {
|
||||||
// generic
|
// generic
|
||||||
assert multi_generic_args<int, string>(0, 's')
|
assert multi_generic_args<int, string>(0, 's')
|
||||||
assert multi_generic_args<Foo1, Foo2>(Foo1{}, Foo2{})
|
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++
|
s.pos++
|
||||||
return s.new_token(.ge, '', 2)
|
return s.new_token(.ge, '', 2)
|
||||||
} else if nextc == `>` {
|
} else if nextc == `>` {
|
||||||
if s.pos + 2 < s.text.len && s.text[s.pos + 2] == `=` {
|
if s.pos + 2 < s.text.len {
|
||||||
s.pos += 2
|
if s.text[s.pos + 2] == `=` {
|
||||||
return s.new_token(.right_shift_assign, '', 3)
|
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++
|
s.pos++
|
||||||
return s.new_token(.right_shift, '', 2)
|
return s.new_token(.right_shift, '', 2)
|
||||||
|
|
|
@ -481,6 +481,35 @@ fn return_one<T>(rec int, useless T) T {
|
||||||
return T(0)
|
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() {
|
fn test_generic_detection() {
|
||||||
v1, v2 := -1, 1
|
v1, v2 := -1, 1
|
||||||
|
|
||||||
|
@ -493,7 +522,7 @@ fn test_generic_detection() {
|
||||||
// generic
|
// generic
|
||||||
assert multi_generic_args<int, string>(0, 's')
|
assert multi_generic_args<int, string>(0, 's')
|
||||||
assert multi_generic_args<Foo1, Foo2>(Foo1{}, Foo2{})
|
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{})
|
// TODO: assert multi_generic_args<Foo<int>, Foo<int>>(Foo1{}, Foo2{})
|
||||||
assert multi_generic_args<simplemodule.Data, int>(simplemodule.Data{}, 0)
|
assert multi_generic_args<simplemodule.Data, int>(simplemodule.Data{}, 0)
|
||||||
|
|
Loading…
Reference in New Issue