Repository: goadesign/goa (go)

Issue:
v3 Using tags and complicated types in a response tries to use pointers
When writing an http response that has multiple responses based on a tag, if one of the responses uses a sub-field that is a struct from a type, the generated code will try to get pointers of the fields, despite the requirement for values.
```golang
package design

import . "goa.design/goa/v3/dsl"

var _ = API("multi-response", func() {})

var Data = Type("data", func() {
	Attribute("id", Int64)
	Attribute("name", String)
	Required("id", "name")
})

var _ = Service("test", func() {
	Method("multi", func() {
		Result(func() {
			Attribute("tag", String)
			Attribute("body", Data)
			Required("tag")
		})

		HTTP(func() {
			GET("/")
			Response(StatusOK, func() {
				Tag("tag", "data")
				Body("body")
			})
			Response(StatusNoContent, func() {
				Body(Empty)
			})
		})
	})
})
```
The above design will have the error in the `NewMultiOKResponseBody` function in `gen/http/test/server/types.go`

Pull request:
Properly handle explicit response body
in client result initialization method. The code didn't account for
explicit body using a result attribute whose type contains required
attribute. The "requiredness" was lost in the function computing the
body type.

Fix #2655

Patch:
diff --git a/codegen/go_transform.go b/codegen/go_transform.go
index a603ee7b..c74f5ee8 100644
--- a/codegen/go_transform.go
+++ b/codegen/go_transform.go
@@ -265,7 +265,7 @@ func transformArray(source, target *expr.Array, sourceVar, targetVar string, new
 		"TargetVar":      targetVar,
 		"NewVar":         newVar,
 		"TransformAttrs": ta,
-		"LoopVar":        string(105 + strings.Count(targetVar, "[")),
+		"LoopVar":        string(rune(105 + strings.Count(targetVar, "["))),
 		"IsStruct":       expr.IsObject(target.ElemType.Type),
 	}
 	var buf bytes.Buffer
@@ -299,7 +299,7 @@ func transformMap(source, target *expr.Map, sourceVar, targetVar string, newVar
 		"IsElemStruct":   expr.IsObject(target.ElemType.Type),
 	}
 	if depth := MapDepth(target); depth > 0 {
-		data["LoopVar"] = string(97 + depth)
+		data["LoopVar"] = string(rune(97 + depth))
 	}
 	var buf bytes.Buffer
 	if err := transformGoMapT.Execute(&buf, data); err != nil {
diff --git a/expr/http_response.go b/expr/http_response.go
index 40376d9c..dc3bb1d3 100644
--- a/expr/http_response.go
+++ b/expr/http_response.go
@@ -256,22 +256,24 @@ func (r *HTTPResponseExpr) Validate(e *HTTPEndpointExpr) *eval.ValidationErrors
 func (r *HTTPResponseExpr) Finalize(a *HTTPEndpointExpr, svcAtt *AttributeExpr) {
 	r.Parent = a
 
-	// Initialize the body attributes (if an object) with the corresponding
-	// result attributes.
-	svcObj := AsObject(svcAtt.Type)
 	if r.Body != nil {
+		bodyAtt := svcAtt
+		if o, ok := r.Body.Meta["origin:attribute"]; ok {
+			bodyAtt = svcAtt.Find(o[0])
+		}
+		bodyObj := AsObject(bodyAtt.Type)
 		if body := AsObject(r.Body.Type); body != nil {
 			for _, nat := range *body {
 				n := nat.Name
 				n = strings.Split(n, ":")[0]
 				var att, patt *AttributeExpr
 				var required bool
-				if svcObj != nil {
-					att = svcObj.Attribute(n)
-					required = svcAtt.IsRequired(n)
+				if bodyObj != nil {
+					att = bodyObj.Attribute(n)
+					required = bodyAtt.IsRequired(n)
 				} else {
-					att = svcAtt
-					required = svcAtt.Type != Empty
+					att = bodyAtt
+					required = bodyAtt.Type != Empty
 				}
 				initAttrFromDesign(att, patt)
 				if required {
@@ -292,7 +294,7 @@ func (r *HTTPResponseExpr) Finalize(a *HTTPEndpointExpr, svcAtt *AttributeExpr)
 			}
 		}
 		if r.Body.Meta == nil {
-			r.Body.Meta = svcAtt.Meta
+			r.Body.Meta = bodyAtt.Meta
 		}
 	}
 	// Set response content type if empty and if set in the result type
diff --git a/grpc/codegen/protobuf_transform.go b/grpc/codegen/protobuf_transform.go
index 6ae88429..a9a3c9c3 100644
--- a/grpc/codegen/protobuf_transform.go
+++ b/grpc/codegen/protobuf_transform.go
@@ -364,7 +364,7 @@ func transformArray(source, target *expr.Array, sourceVar, targetVar string, new
 		"TargetVar":      targetVar,
 		"NewVar":         newVar,
 		"TransformAttrs": ta,
-		"LoopVar":        string(105 + strings.Count(targetVar, "[")),
+		"LoopVar":        string(rune(105 + strings.Count(targetVar, "["))),
 	}
 	var buf bytes.Buffer
 	if err := transformGoArrayT.Execute(&buf, data); err != nil {
@@ -439,7 +439,7 @@ func transformMap(source, target *expr.Map, sourceVar, targetVar string, newVar
 		"LoopVar":        "",
 	}
 	if depth := codegen.MapDepth(target); depth > 0 {
-		data["LoopVar"] = string(97 + depth)
+		data["LoopVar"] = string(rune(97 + depth))
 	}
 	var buf bytes.Buffer
 	if err := transformGoMapT.Execute(&buf, data); err != nil {
diff --git a/http/codegen/server.go b/http/codegen/server.go
index 7dae6eab..8c3590d2 100644
--- a/http/codegen/server.go
+++ b/http/codegen/server.go
@@ -242,7 +242,7 @@ func mapQueryDecodeData(dt expr.DataType, varName string, inc int) map[string]in
 	return map[string]interface{}{
 		"Type":      dt,
 		"VarName":   varName,
-		"Loop":      string(97 + inc),
+		"Loop":      string(rune(97 + inc)),
 		"Increment": inc + 1,
 		"Depth":     codegen.MapDepth(expr.AsMap(dt)),
 	}


Test patch:
diff --git a/http/codegen/client_body_types_test.go b/http/codegen/client_body_types_test.go
index 81b62e03..0289c6f8 100644
--- a/http/codegen/client_body_types_test.go
+++ b/http/codegen/client_body_types_test.go
@@ -45,6 +45,7 @@ func TestBodyTypeInit(t *testing.T) {
 		{"body-path-user-validate", testdata.PayloadBodyPathUserValidateDSL, 2, BodyPathUserValidateInitCode},
 		{"body-primitive-array-user-validate", testdata.PayloadBodyPrimitiveArrayUserValidateDSL, 2, BodyPrimitiveArrayUserValidateInitCode},
 		{"result-body-user", testdata.ResultBodyObjectHeaderDSL, 2, ResultBodyObjectHeaderInitCode},
+		{"result-body-user-required", testdata.ResultBodyUserRequiredDSL, 3, ResultBodyUserRequiredInitCode},
 		{"result-body-inline-object", testdata.ResultBodyInlineObjectDSL, 2, ResultBodyInlineObjectInitCode},
 		{"result-explicit-body-primitive", testdata.ExplicitBodyPrimitiveResultMultipleViewsDSL, 1, ExplicitBodyPrimitiveResultMultipleViewsInitCode},
 		{"result-explicit-body-user-type", testdata.ExplicitBodyUserResultMultipleViewsDSL, 3, ExplicitBodyUserResultMultipleViewsInitCode},
@@ -186,6 +187,20 @@ func NewMethodBodyObjectHeaderResultOK(body *MethodBodyObjectHeaderResponseBody,
 }
 `
 
+const ResultBodyUserRequiredInitCode = `// NewMethodBodyUserRequiredResultOK builds a "ServiceBodyUserRequired" service
+// "MethodBodyUserRequired" endpoint result from a HTTP "OK" response.
+func NewMethodBodyUserRequiredResultOK(body *MethodBodyUserRequiredResponseBody) *servicebodyuserrequired.MethodBodyUserRequiredResult {
+	v := &servicebodyuserrequired.Body{
+		A: *body.A,
+	}
+	res := &servicebodyuserrequired.MethodBodyUserRequiredResult{
+		Body: v,
+	}
+
+	return res
+}
+`
+
 const ResultBodyInlineObjectInitCode = `// NewMethodBodyInlineObjectResultTypeOK builds a "ServiceBodyInlineObject"
 // service "MethodBodyInlineObject" endpoint result from a HTTP "OK" response.
 func NewMethodBodyInlineObjectResultTypeOK(body *MethodBodyInlineObjectResponseBody) *servicebodyinlineobject.ResultType {
diff --git a/http/codegen/testdata/result_dsls.go b/http/codegen/testdata/result_dsls.go
index 19b1bbd2..e1acbd59 100644
--- a/http/codegen/testdata/result_dsls.go
+++ b/http/codegen/testdata/result_dsls.go
@@ -585,6 +585,26 @@ var ResultBodyObjectHeaderDSL = func() {
 	})
 }
 
+var ResultBodyUserRequiredDSL = func() {
+	var Bod = Type("body", func() {
+		Attribute("a")
+		Required("a")
+	})
+	Service("ServiceBodyUserRequired", func() {
+		Method("MethodBodyUserRequired", func() {
+			Result(func() {
+				Attribute("body", Bod)
+			})
+			HTTP(func() {
+				GET("/")
+				Response(StatusOK, func() {
+					Body("body")
+				})
+			})
+		})
+	})
+}
+
 var ResultBodyUserDSL = func() {
 	var ResultType = Type("ResultType", func() {
 		Attribute("a", String)