Repository: goadesign/goa (go)

Issue:
bug: Generated service_interceptors.go file does not import package for Attributes in ReadPayload with Meta("struct:pkg:path")
When defining a service interceptor with a ReadPayload that includes a type with the Meta("struct:pkg:path"), the generated service_interceptors.go file does not import that package. This results in a compile error in the output codegen when referencing that type. I am using goa v3.20.0.

Minimal example:
```
var _ = Service("example", func() {
	ServerInterceptor(ResourceID)

	Method("get", func() {
		Payload(func() {
			Attribute("id", String)
			Attribute("tenantID", TenantID)
			Required("tenantID", "id")
		})

		Result(Int)

		HTTP(func() {
			GET("{tenantID}/resource/{id}")
			Response(StatusOK)
		})
	})
})

var ResourceID = Interceptor("TenantID", func() {
	ReadPayload(func() {
		Attribute("tenantID", TenantID)
	})
})

var TenantID = Type("TenantID", String, func() {
	Meta("struct:pkg:path", "ids")
})
```

service_interceptors.go that does not have the needed import:
```
package example

import (
	"context"

	goa "goa.design/goa/v3/pkg"
)

...

	// TenantIDPayload provides type-safe access to the method payload.
	// It allows reading and writing specific fields of the payload as defined
	// in the design.
	TenantIDPayload interface {
		TenantID() TenantID
	}
)
```

service.go that does have the needed import:
```
service.go:

package example

import (
	"context"

	ids "goa.design/examples/basic/gen/ids"
)

... 

// GetPayload is the payload type of the example service get method.
type GetPayload struct {
	ID       string
	TenantID ids.TenantID
}
```

Expected behavior: service_interceptors.go imports the ids package and uses it when referencing the TenantID type.


Pull request:
Properly handle interceptor types in custom packages
Fixes #3665

Patch:
diff --git a/codegen/service/service_data.go b/codegen/service/service_data.go
index e62dd4ea..c29d8631 100644
--- a/codegen/service/service_data.go
+++ b/codegen/service/service_data.go
@@ -1476,9 +1476,13 @@ func collectAttributes(attrNames, parent *expr.AttributeExpr, scope *codegen.Nam
 		if parentAttr == nil {
 			continue
 		}
+		var pkg string
+		if loc := codegen.UserTypeLocation(parentAttr.Type); loc != nil {
+			pkg = loc.PackageName()
+		}
 		data[i] = &AttributeData{
 			Name:    codegen.Goify(nat.Name, true),
-			TypeRef: scope.GoTypeRef(parentAttr),
+			TypeRef: scope.GoFullTypeRef(parentAttr, pkg),
 			Pointer: parent.IsPrimitivePointer(nat.Name, true),
 		}
 	}


Test patch:
diff --git a/codegen/service/interceptors_test.go b/codegen/service/interceptors_test.go
index e20c1cc7..7bb993d5 100644
--- a/codegen/service/interceptors_test.go
+++ b/codegen/service/interceptors_test.go
@@ -181,6 +181,34 @@ func TestCollectAttributes(t *testing.T) {
 			},
 			want: []*AttributeData{nil},
 		},
+		{
+			name: "user-type-with-package",
+			attrNames: &expr.AttributeExpr{
+				Type: &expr.Object{
+					{Name: "user", Attribute: &expr.AttributeExpr{Type: expr.String}},
+				},
+			},
+			parent: &expr.AttributeExpr{
+				Type: &expr.Object{
+					{Name: "user", Attribute: &expr.AttributeExpr{
+						Type: &expr.UserTypeExpr{
+							AttributeExpr: &expr.AttributeExpr{
+								Type: &expr.Object{
+									{Name: "name", Attribute: &expr.AttributeExpr{Type: expr.Primitive(expr.StringKind)}},
+								},
+								Meta: map[string][]string{
+									"struct:pkg:path": {"goa.design/goa/example/user"},
+								},
+							},
+							TypeName: "User",
+						},
+					}},
+				},
+			},
+			want: []*AttributeData{
+				{Name: "User", TypeRef: "*user.User", Pointer: false},
+			},
+		},
 	}
 
 	for _, tc := range cases {