MCPcopy Create free account
hub / github.com/goadesign/goa / transformUnion

Function transformUnion

codegen/go_transform.go:447–528  ·  view source on GitHub ↗

transformUnion generates Go code to transform source union to target union. Note: transport to/from service transforms are always object to union or union to object. The only case a transform is union to union is when converting a projected type from/to a service type.

(source, target *expr.AttributeExpr, sourceVar, targetVar string, newVar bool, ta *TransformAttrs)

Source from the content-addressed store, hash-verified

445// union to object. The only case a transform is union to union is when
446// converting a projected type from/to a service type.
447func transformUnion(source, target *expr.AttributeExpr, sourceVar, targetVar string, newVar bool, ta *TransformAttrs) (string, error) {
448 if !expr.IsUnion(target.Type) {
449 return "", fmt.Errorf("cannot transform union %s to non-union %s", source.Type.Name(), target.Type.Name())
450 }
451 srcUnion, tgtUnion := expr.AsUnion(source.Type), expr.AsUnion(target.Type)
452 if len(srcUnion.Values) != len(tgtUnion.Values) {
453 return "", fmt.Errorf("cannot transform union: number of union types differ (%s has %d, %s has %d)",
454 source.Type.Name(), len(srcUnion.Values), target.Type.Name(), len(tgtUnion.Values))
455 }
456 for i, st := range srcUnion.Values {
457 if err := IsCompatible(st.Attribute.Type, tgtUnion.Values[i].Attribute.Type, sourceVar, targetVar); err != nil {
458 return "", fmt.Errorf("cannot transform union %s to %s: type at index %d: %w",
459 source.Type.Name(), target.Type.Name(), i, err)
460 }
461 }
462
463 // Unions are generated as concrete sum-type structs with Kind/AsX/SetX
464 // helpers. Transform by branching on the runtime Kind discriminator.
465 unionPkg := ta.TargetCtx.Pkg(target)
466 typeRef := ta.TargetCtx.Scope.Ref(target, unionPkg)
467
468 // Use deterministic temp var: 'obj' at top-level, 'tmp' for nested assignments.
469 tempVarName := "obj"
470 if strings.HasPrefix(targetVar, "obj.") {
471 tempVarName = "tmp"
472 }
473
474 cases := make([]map[string]any, 0, len(srcUnion.Values))
475 for i, st := range srcUnion.Values {
476 if st == nil || st.Attribute == nil {
477 continue
478 }
479 if i >= len(tgtUnion.Values) {
480 break
481 }
482 tt := tgtUnion.Values[i]
483 if tt == nil || tt.Attribute == nil {
484 continue
485 }
486 castPkg := ta.TargetCtx.Pkg(tt.Attribute)
487 // When generating transforms outside of the type's package, some nested
488 // helper user types may not carry struct:pkg:path metadata. In that case
489 // default to the union type package rather than the current file package.
490 if castPkg == ta.TargetCtx.DefaultPkg && unionPkg != "" && unionPkg != ta.TargetCtx.DefaultPkg {
491 castPkg = unionPkg
492 }
493 useHelper := false
494 if _, ok := st.Attribute.Type.(expr.UserType); ok && expr.IsObject(st.Attribute.Type) {
495 if _, ok := tt.Attribute.Type.(expr.UserType); ok && expr.IsObject(tt.Attribute.Type) {
496 useHelper = true
497 }
498 }
499 cases = append(cases, map[string]any{
500 "CaseName": st.Name,
501 "SourceFieldName": Goify(st.Name, true),
502 "TargetFieldName": Goify(tt.Name, true),
503 "SourceAttr": st.Attribute,
504 "TargetAttr": tt.Attribute,

Callers 2

transformAttributeFunction · 0.85
transformObjectFunction · 0.85

Calls 11

IsUnionFunction · 0.92
AsUnionFunction · 0.92
IsObjectFunction · 0.92
IsCompatibleFunction · 0.85
GoifyFunction · 0.85
PkgMethod · 0.80
ExecuteMethod · 0.80
transformHelperNameFunction · 0.70
NameMethod · 0.65
RefMethod · 0.65
StringMethod · 0.65

Tested by

no test coverage detected