예제 #1
0
func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
	if len(t.Members) == 0 {
		// at least do something with in/out to avoid "declared and not used" errors
		sw.Do("_ = in\n_ = out\n", nil)
	}
	for _, m := range t.Members {
		t := m.Type
		if t.Kind == types.Alias {
			copied := *t.Underlying
			copied.Name = t.Name
			t = &copied
		}
		args := map[string]interface{}{
			"type": t,
			"name": m.Name,
		}
		switch t.Kind {
		case types.Builtin:
			sw.Do("out.$.name$ = in.$.name$\n", args)
		case types.Map, types.Slice, types.Pointer:
			sw.Do("if in.$.name$ != nil {\n", args)
			sw.Do("in, out := &in.$.name$, &out.$.name$\n", args)
			g.generateFor(t, sw)
			sw.Do("} else {\n", nil)
			sw.Do("out.$.name$ = nil\n", args)
			sw.Do("}\n", nil)
		case types.Struct:
			if hasDeepCopyMethod(t) {
				sw.Do("out.$.name$ = in.$.name$.DeepCopy()\n", args)
			} else if t.IsAssignable() {
				sw.Do("out.$.name$ = in.$.name$\n", args)
			} else if g.copyableAndInBounds(t) {
				funcName := g.funcNameTmpl(t)
				sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, c); err != nil {\n", funcName), args)
				sw.Do("return err\n", nil)
				sw.Do("}\n", nil)
			} else {
				sw.Do("if newVal, err := c.DeepCopy(&in.$.name$); err != nil {\n", args)
				sw.Do("return err\n", nil)
				sw.Do("} else {\n", nil)
				sw.Do("out.$.name$ = *newVal.(*$.type|raw$)\n", args)
				sw.Do("}\n", nil)
			}
		default:
			sw.Do("if in.$.name$ == nil {\n", args)
			sw.Do("out.$.name$ = nil\n", args)
			sw.Do("} else if newVal, err := c.DeepCopy(&in.$.name$); err != nil {\n", args)
			sw.Do("return err\n", nil)
			sw.Do("} else {\n", nil)
			sw.Do("out.$.name$ = *newVal.(*$.type|raw$)\n", args)
			sw.Do("}\n", nil)
		}
	}
}
예제 #2
0
func isDirectlyAssignable(inType, outType *types.Type) bool {
	// TODO: This should maybe check for actual assignability between the two
	// types, rather than superficial traits that happen to indicate it is
	// assignable in the ways we currently use this code.
	return inType.IsAssignable() && (inType.IsPrimitive() || isSamePackage(inType, outType))
}