From 95d43c54bfbebe8c2e439ce8aa2b4665211d793f Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Tue, 12 Jul 2022 23:52:44 -0700 Subject: [PATCH] cmd/{cloner,viewer}: add support for map values with pointers Signed-off-by: Maisem Ali --- cmd/cloner/cloner.go | 15 +++++++++++---- cmd/viewer/tests/tests.go | 1 + cmd/viewer/tests/tests_clone.go | 8 ++++++++ cmd/viewer/tests/tests_view.go | 7 +++++++ cmd/viewer/viewer.go | 11 +++++++---- 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/cmd/cloner/cloner.go b/cmd/cloner/cloner.go index 3e8d76c21..60126180b 100644 --- a/cmd/cloner/cloner.go +++ b/cmd/cloner/cloner.go @@ -153,18 +153,25 @@ func gen(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named) { } writef("}") case *types.Map: + elem := ft.Elem() writef("if dst.%s != nil {", fname) - writef("\tdst.%s = map[%s]%s{}", fname, it.QualifiedName(ft.Key()), it.QualifiedName(ft.Elem())) - if sliceType, isSlice := ft.Elem().(*types.Slice); isSlice { + writef("\tdst.%s = map[%s]%s{}", fname, it.QualifiedName(ft.Key()), it.QualifiedName(elem)) + if sliceType, isSlice := elem.(*types.Slice); isSlice { n := it.QualifiedName(sliceType.Elem()) writef("\tfor k := range src.%s {", fname) // use zero-length slice instead of nil to ensure // the key is always copied. writef("\t\tdst.%s[k] = append([]%s{}, src.%s[k]...)", fname, n, fname) writef("\t}") - } else if codegen.ContainsPointers(ft.Elem()) { + } else if codegen.ContainsPointers(elem) { writef("\tfor k, v := range src.%s {", fname) - writef("\t\tdst.%s[k] = v.Clone()", fname) + switch elem.(type) { + case *types.Pointer: + writef("\t\tdst.%s[k] = v.Clone()", fname) + default: + writef("\t\tv2 := v.Clone()") + writef("\t\tdst.%s[k] = *v2", fname) + } writef("\t}") } else { writef("\tfor k, v := range src.%s {", fname) diff --git a/cmd/viewer/tests/tests.go b/cmd/viewer/tests/tests.go index cd099362a..847460709 100644 --- a/cmd/viewer/tests/tests.go +++ b/cmd/viewer/tests/tests.go @@ -31,6 +31,7 @@ type Map struct { SliceIntPtr map[string][]*int PointerKey map[*string]int `json:"-"` StructWithPtrKey map[StructWithPtrs]int `json:"-"` + StructWithPtr map[string]StructWithPtrs } type StructWithPtrs struct { diff --git a/cmd/viewer/tests/tests_clone.go b/cmd/viewer/tests/tests_clone.go index dddb7b1d9..396be03b9 100644 --- a/cmd/viewer/tests/tests_clone.go +++ b/cmd/viewer/tests/tests_clone.go @@ -127,6 +127,13 @@ func (src *Map) Clone() *Map { dst.StructWithPtrKey[k] = v } } + if dst.StructWithPtr != nil { + dst.StructWithPtr = map[string]StructWithPtrs{} + for k, v := range src.StructWithPtr { + v2 := v.Clone() + dst.StructWithPtr[k] = *v2 + } + } return dst } @@ -143,6 +150,7 @@ var _MapCloneNeedsRegeneration = Map(struct { SliceIntPtr map[string][]*int PointerKey map[*string]int StructWithPtrKey map[StructWithPtrs]int + StructWithPtr map[string]StructWithPtrs }{}) // Clone makes a deep copy of StructWithSlices. diff --git a/cmd/viewer/tests/tests_view.go b/cmd/viewer/tests/tests_view.go index 3261d927f..03aa1a922 100644 --- a/cmd/viewer/tests/tests_view.go +++ b/cmd/viewer/tests/tests_view.go @@ -231,6 +231,12 @@ func (v MapView) SliceIntPtr() map[string][]*int { panic("unsupported" func (v MapView) PointerKey() map[*string]int { panic("unsupported") } func (v MapView) StructWithPtrKey() map[StructWithPtrs]int { panic("unsupported") } +func (v MapView) StructWithPtr() views.MapFn[string, StructWithPtrs, StructWithPtrsView] { + return views.MapFnOf(v.ж.StructWithPtr, func(t StructWithPtrs) StructWithPtrsView { + return t.View() + }) +} + // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _MapViewNeedsRegeneration = Map(struct { Int map[string]int @@ -244,6 +250,7 @@ var _MapViewNeedsRegeneration = Map(struct { SliceIntPtr map[string][]*int PointerKey map[*string]int StructWithPtrKey map[StructWithPtrs]int + StructWithPtr map[string]StructWithPtrs }{}) // View returns a readonly view of StructWithSlices. diff --git a/cmd/viewer/viewer.go b/cmd/viewer/viewer.go index a156bf375..5f58f2cd9 100644 --- a/cmd/viewer/viewer.go +++ b/cmd/viewer/viewer.go @@ -228,11 +228,14 @@ func genView(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named, thi strucT := u args.FieldType = it.QualifiedName(fieldType) if codegen.ContainsPointers(strucT) { - writeTemplate("unsupportedField") - continue + args.MapFn = "t.View()" + template = "mapFnField" + args.MapValueType = it.QualifiedName(mElem) + args.MapValueView = args.MapValueType + "View" + } else { + template = "mapField" + args.MapValueType = it.QualifiedName(mElem) } - template = "mapField" - args.MapValueType = it.QualifiedName(mElem) case *types.Basic: template = "mapField" args.MapValueType = it.QualifiedName(mElem)