1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

ast, parser: fix wrong type name of nested generics (#16749)

This commit is contained in:
yuyi 2022-12-24 12:19:51 +08:00 committed by GitHub
parent e9cad6f09d
commit 0128d2dd1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 15 deletions

View File

@ -1154,6 +1154,37 @@ pub fn (t &Table) clean_generics_type_str(typ Type) string {
return result.all_before('[')
}
fn strip_extra_struct_types(name string) string {
mut start := 0
mut is_start := false
mut nested_count := 0
mut strips := []string{}
for i, ch in name {
if ch == `<` {
if is_start {
nested_count++
} else {
is_start = true
start = i
}
} else if ch == `>` {
if nested_count > 0 {
nested_count--
} else {
strips << name.substr(start, i + 1)
strips << ''
is_start = false
}
}
}
if strips.len > 0 {
return name.replace_each(strips)
} else {
return name
}
}
// import_aliases is a map of imported symbol aliases 'module.Type' => 'Type'
pub fn (t &Table) type_to_str_using_aliases(typ Type, import_aliases map[string]string) string {
cache_key := (u64(import_aliases.len) << 32) | u64(typ)
@ -1280,6 +1311,7 @@ pub fn (t &Table) type_to_str_using_aliases(typ Type, import_aliases map[string]
import_aliases))
res = '${variant_names.join('|')}'
} else {
res = strip_extra_struct_types(res)
res = t.shorten_user_defined_typenames(res, import_aliases)
}
}
@ -1363,20 +1395,22 @@ fn (t Table) shorten_user_defined_typenames(originalname string, import_aliases
}
// types defined by the user
// mod.submod.submod2.Type => submod2.Type
mut parts := res.split('.')
if parts.len > 1 {
ind := parts.len - 2
if t.is_fmt {
// Rejoin the module parts for correct usage of aliases
parts[ind] = parts[..ind + 1].join('.')
}
if parts[ind] in import_aliases {
parts[ind] = import_aliases[parts[ind]]
}
if res.count('[') < 2 {
mut parts := res.split('.')
if parts.len > 1 {
ind := parts.len - 2
if t.is_fmt {
// Rejoin the module parts for correct usage of aliases
parts[ind] = parts[..ind + 1].join('.')
}
if parts[ind] in import_aliases {
parts[ind] = import_aliases[parts[ind]]
}
res = parts[ind..].join('.')
} else {
res = parts[0]
res = parts[ind..].join('.')
} else {
res = parts[0]
}
}
}
return res

View File

@ -654,14 +654,14 @@ pub fn (mut p Parser) find_type_or_add_placeholder(name string, language ast.Lan
if p.struct_init_generic_types.len > 0 && sym.info.generic_types.len > 0
&& p.struct_init_generic_types != sym.info.generic_types {
generic_names := p.struct_init_generic_types.map(p.table.sym(it).name)
mut sym_name := sym.name + '['
mut sym_name := sym.name + '<'
for i, gt in generic_names {
sym_name += gt
if i != generic_names.len - 1 {
sym_name += ','
}
}
sym_name += ']'
sym_name += '>'
existing_idx := p.table.type_idxs[sym_name]
if existing_idx > 0 {
idx = existing_idx

View File

@ -80,4 +80,15 @@ fn test_generics_struct_init_with_inconsistent_generic_types() {
assert ry2[1].b.a.b == 'four'
assert ry2[1].b.b.a == 'four'
assert ry2[1].b.b.b == 4
zx1 := []Tuple2[int, Tuple2[string, int]]{}
println(typeof(zx1).name)
println(typeof(rx1).name)
zx2 := []Tuple2[int, Tuple2[Tuple2[string, int], Tuple2[int, string]]]{}
println(typeof(zx2).name)
println(typeof(rx2).name)
assert typeof(zx1).name == '[]Tuple2[int, Tuple2[string, int]]'
assert typeof(zx2).name == '[]Tuple2[int, Tuple2[Tuple2[string, int], Tuple2[int, string]]]'
assert typeof(zx1).name == typeof(rx1).name
assert typeof(zx2).name == typeof(rx2).name
}