gen: fix autogeneration of .str() methods for sumtypes that have child types with custom .str() methods

pull/8298/head
Delyan Angelov 2021-01-23 17:03:17 +02:00
parent 74115fe70a
commit 4065a0327a
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
2 changed files with 48 additions and 3 deletions

View File

@ -600,11 +600,13 @@ fn (mut g Gen) gen_str_for_union_sum_type(info table.SumType, styp string, str_f
g.gen_str_for_type(typ)
}
sym := g.table.get_type_symbol(typ)
if sym.kind == .struct_ {
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
deref := if sym_has_str_method && str_method_expects_ptr { ' ' } else { '*' }
if sym.kind == .struct_ && !sym_has_str_method {
func_name = 'indent_$func_name'
}
g.auto_str_funcs.write('\t\tcase $typ: return _STR("${clean_sum_type_v_type_name}($value_fmt)", 2, ${func_name}(*($typ_str*)x._$sym.cname')
if sym.kind == .struct_ {
g.auto_str_funcs.write('\t\tcase $typ: return _STR("${clean_sum_type_v_type_name}($value_fmt)", 2, ${func_name}(${deref}($typ_str*)x._$sym.cname')
if sym.kind == .struct_ && !sym_has_str_method {
g.auto_str_funcs.write(', indent_count')
}
g.auto_str_funcs.writeln('));')

View File

@ -0,0 +1,43 @@
// Test whether a sumtype that has multiple subtypes,
// some with custom .str() methods, can be converted to a string,
// i.e. whether its own autogenerated .str() method will work.
// NB: Dictionary.str() calls $v.str() in the string interpolation,
// which in turn can call Dictionary.str(), i.e. they are mutually
// recursive.
type Object = Dictionary | Stream | bool | f32 | int | string
struct Dictionary {
items map[string]Object
}
struct Stream {
mut:
content string
}
fn (dict Dictionary) str() string {
mut temp := []string{}
for k, v in dict.items {
temp << ' << "$k": ' + v.str().replace('\n', ' ')
}
return '\n' + temp.join('\n') + '\n'
}
fn test_str_of_sumtype_works() {
o := Object(Dictionary{
items: {
'abc': Object(Stream{
content: 'xyz'
})
'aaa': Object(int(321))
'bbb': Object(f32(3.14))
}
})
so := o.str()
println(so)
assert so.starts_with('Object(')
assert so.contains('<< "abc": Object(Stream{')
assert so.contains('<< "aaa": Object(321)')
assert so.contains('<< "bbb": Object(3.14')
assert so.ends_with(')')
}