Переглянути джерело

cmd/{cloner,viewer}: add support for map values with pointers

Signed-off-by: Maisem Ali <[email protected]>
Maisem Ali 3 роки тому
батько
коміт
95d43c54bf

+ 11 - 4
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)

+ 1 - 0
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 {

+ 8 - 0
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.

+ 7 - 0
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.

+ 7 - 4
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)