Repository: goadesign/goa
Pull request #3508 (2024-04-15 23:51:22)

Fix handling of custom gen packages
With user defined type protobuf names.


Patch:
diff --git a/expr/grpc_endpoint.go b/expr/grpc_endpoint.go
index 92e1e221..a884d3fd 100644
--- a/expr/grpc_endpoint.go
+++ b/expr/grpc_endpoint.go
@@ -333,12 +333,13 @@ func (e *GRPCEndpointExpr) Finalize() {
 			}
 		}
 		if ut, ok := e.MethodExpr.Payload.Type.(UserType); ok {
-			// merge Meta defined in the method payload type with the request
-			if ut.Attribute().Meta != nil {
+			// propagate the user set protobuf struct name from the user type to
+			// the request message.
+			if proto, ok := ut.Attribute().Meta.Last("struct:name:proto"); ok {
 				if e.Request.Meta == nil {
 					e.Request.Meta = ut.Attribute().Meta
 				} else {
-					e.Request.Meta.Merge(ut.Attribute().Meta)
+					e.Request.Meta["struct:name:proto"] = []string{proto}
 				}
 			}
 		}
diff --git a/expr/grpc_response.go b/expr/grpc_response.go
index 1d56f4d9..30b911d8 100644
--- a/expr/grpc_response.go
+++ b/expr/grpc_response.go
@@ -187,12 +187,13 @@ func (r *GRPCResponseExpr) Finalize(a *GRPCEndpointExpr, svcAtt *AttributeExpr)
 			}
 		}
 		if ut, ok := svcAtt.Type.(UserType); ok {
-			// merge Meta defined in the method result type with the response
-			if ut.Attribute().Meta != nil {
+			// propagate the user set protobuf struct name from the user type to
+			// the request message.
+			if proto, ok := ut.Attribute().Meta.Last("struct:name:proto"); ok {
 				if r.Message.Meta == nil {
 					r.Message.Meta = ut.Attribute().Meta
 				} else {
-					r.Message.Meta.Merge(ut.Attribute().Meta)
+					r.Message.Meta["struct:name:proto"] = []string{proto}
 				}
 			}
 		}


Test patch:
diff --git a/grpc/codegen/server_types_test.go b/grpc/codegen/server_types_test.go
index ea5e87c3..f6e52d01 100644
--- a/grpc/codegen/server_types_test.go
+++ b/grpc/codegen/server_types_test.go
@@ -19,6 +19,7 @@ func TestServerTypeFiles(t *testing.T) {
 		{"server-payload-with-duplicate-use", testdata.PayloadWithMultipleUseTypesDSL, testdata.PayloadWithMultipleUseTypesServerTypeCode},
 		{"server-payload-with-alias-type", testdata.PayloadWithAliasTypeDSL, testdata.PayloadWithAliasTypeServerTypeCode},
 		{"server-payload-with-mixed-attributes", testdata.PayloadWithMixedAttributesDSL, testdata.PayloadWithMixedAttributesServerTypeCode},
+		{"server-payload-with-custom-type-package", testdata.PayloadWithCustomTypePackageDSL, testdata.PayloadWithCustomTypePackageServerTypeCode},
 		{"server-result-collection", testdata.ResultWithCollectionDSL, testdata.ResultWithCollectionServerTypeCode},
 		{"server-with-errors", testdata.UnaryRPCWithErrorsDSL, testdata.WithErrorsServerTypeCode},
 		{"server-elem-validation", testdata.ElemValidationDSL, testdata.ElemValidationServerTypesFile},
diff --git a/grpc/codegen/testdata/dsls.go b/grpc/codegen/testdata/dsls.go
index 7091dbea..f7c7c5c7 100644
--- a/grpc/codegen/testdata/dsls.go
+++ b/grpc/codegen/testdata/dsls.go
@@ -628,6 +628,20 @@ var PayloadWithMultipleUseTypesDSL = func() {
 	})
 }
 
+var PayloadWithCustomTypePackageDSL = func() {
+	var CustomType = Type("CustomType", func() {
+		Field(1, "Field", Int)
+		Meta("struct:pkg:path", "types")
+	})
+	Service("ServicePayloadWithCustomTypePackage", func() {
+		Method("MethodPayloadWithCustomTypePackage", func() {
+			Payload(CustomType)
+			Result(CustomType)
+			GRPC(func() {})
+		})
+	})
+}
+
 var PayloadWithAliasTypeDSL = func() {
 	var IntAlias = Type("IntAlias", Int)
 	var PayloadAliasT = Type("PayloadAliasT", func() {
diff --git a/grpc/codegen/testdata/server_type_code.go b/grpc/codegen/testdata/server_type_code.go
index c6acec68..58c85461 100644
--- a/grpc/codegen/testdata/server_type_code.go
+++ b/grpc/codegen/testdata/server_type_code.go
@@ -315,6 +315,31 @@ func NewStreamingMethodStreamingRequestAPayload(v *service_payload_with_mixed_at
 }
 `
 
+const PayloadWithCustomTypePackageServerTypeCode = `// NewMethodPayloadWithCustomTypePackagePayload builds the payload of the
+// "MethodPayloadWithCustomTypePackage" endpoint of the
+// "ServicePayloadWithCustomTypePackage" service from the gRPC request type.
+func NewMethodPayloadWithCustomTypePackagePayload(message *service_payload_with_custom_type_packagepb.MethodPayloadWithCustomTypePackageRequest) *types.CustomType {
+	v := &types.CustomType{}
+	if message.Field != nil {
+		field := int(*message.Field)
+		v.Field = &field
+	}
+	return v
+}
+
+// NewProtoMethodPayloadWithCustomTypePackageResponse builds the gRPC response
+// type from the result of the "MethodPayloadWithCustomTypePackage" endpoint of
+// the "ServicePayloadWithCustomTypePackage" service.
+func NewProtoMethodPayloadWithCustomTypePackageResponse(result *types.CustomType) *service_payload_with_custom_type_packagepb.MethodPayloadWithCustomTypePackageResponse {
+	message := &service_payload_with_custom_type_packagepb.MethodPayloadWithCustomTypePackageResponse{}
+	if result.Field != nil {
+		field := int32(*result.Field)
+		message.Field = &field
+	}
+	return message
+}
+`
+
 const WithErrorsServerTypeCode = `// NewMethodUnaryRPCWithErrorsPayload builds the payload of the
 // "MethodUnaryRPCWithErrors" endpoint of the "ServiceUnaryRPCWithErrors"
 // service from the gRPC request type.