transformUnionData returns data needed by both transformUnion functions.
(source, target *expr.AttributeExpr, ta *transformAttrs)
| 747 | |
| 748 | // transformUnionData returns data needed by both transformUnion functions. |
| 749 | func transformUnionData(source, target *expr.AttributeExpr, ta *transformAttrs) *unionData { |
| 750 | src := expr.AsUnion(source.Type) |
| 751 | tgt := expr.AsUnion(target.Type) |
| 752 | srcValues := make([]*expr.NamedAttributeExpr, len(src.Values)) |
| 753 | copy(srcValues, src.Values) |
| 754 | tgtValues := make([]*expr.NamedAttributeExpr, len(tgt.Values)) |
| 755 | copy(tgtValues, tgt.Values) |
| 756 | |
| 757 | sourceValueTypeRefs := make([]string, len(src.Values)) |
| 758 | targetWrapperRefs := make([]string, len(src.Values)) |
| 759 | if ta.proto { |
| 760 | // Go -> protobuf: when union members are user types, switch on the |
| 761 | // actual user type rather than synthetic wrapper types. Only non-user |
| 762 | // types (primitives, maps, arrays) require per-branch wrapper types. |
| 763 | unionPkg := ta.SourceCtx.Pkg(source) |
| 764 | samePkg := true |
| 765 | commonPkg := "" |
| 766 | for _, v := range src.Values { |
| 767 | ut, ok := v.Attribute.Type.(expr.UserType) |
| 768 | if !ok { |
| 769 | samePkg = false |
| 770 | break |
| 771 | } |
| 772 | if loc := codegen.UserTypeLocation(ut); loc != nil { |
| 773 | if commonPkg == "" { |
| 774 | commonPkg = loc.PackageName() |
| 775 | } else if commonPkg != loc.PackageName() { |
| 776 | samePkg = false |
| 777 | break |
| 778 | } |
| 779 | } else { |
| 780 | samePkg = false |
| 781 | break |
| 782 | } |
| 783 | } |
| 784 | for i, v := range src.Values { |
| 785 | if _, ok := v.Attribute.Type.(expr.UserType); ok { |
| 786 | sourceValueTypeRefs[i] = ta.SourceCtx.Scope.Ref(v.Attribute, ta.SourceCtx.Pkg(v.Attribute)) |
| 787 | continue |
| 788 | } |
| 789 | // Non-user types are represented via per-branch defined wrapper types. |
| 790 | w := codegen.Goify(src.Name(), true) + codegen.Goify(v.Name, true) |
| 791 | pkg := unionPkg |
| 792 | if samePkg && commonPkg != "" { |
| 793 | pkg = commonPkg |
| 794 | } |
| 795 | if pkg != "" { |
| 796 | sourceValueTypeRefs[i] = pkg + "." + w |
| 797 | } else { |
| 798 | sourceValueTypeRefs[i] = w |
| 799 | } |
| 800 | } |
| 801 | } else { |
| 802 | // Protobuf -> Go: switch on protobuf oneof variants and cast converted |
| 803 | // value into Go-side wrappers when required. |
| 804 | for i, v := range src.Values { |
| 805 | fieldName := ta.SourceCtx.Scope.Field(v.Attribute, v.Name, true) |
| 806 | sourceValueTypeRefs[i] = ta.message + "_" + fieldName |
no test coverage detected