Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Meta("struct:pkg:path", "foo/bar") doesn't work. #3361

Closed
Albert-Coding opened this issue Sep 20, 2023 · 9 comments
Closed

Meta("struct:pkg:path", "foo/bar") doesn't work. #3361

Albert-Coding opened this issue Sep 20, 2023 · 9 comments

Comments

@Albert-Coding
Copy link

When using Meta("struct:pkg:path", "foo/bar"), code produced doesn't compile.

Example code:

package design

import . "goa.design/goa/v3/dsl"

var _ = API("admin_and_internal_grpc_api", func() {
	Server("admin_grpc_server", func() { Services("admin_grpc_service") })
	Server("internal_grpc_server", func() { Services("internal_grpc_service") })
})

var _ = Service("admin_grpc_service", func() {
	Method("CreateThing", func() {
		Payload(func() { Field(1, "event", Event) })
		Result(Boolean, "success")
		GRPC(func() {})
	})
})

var _ = Service("internal_grpc_service", func() {
	Method("CreateThing", func() {
		Payload(func() { Field(1, "event", Event) })
		Result(Boolean, "success")
		GRPC(func() {})
	})
})

var Event = Type("Event", func() {
	Meta("struct:pkg:path", "common/payloads")
	Field(1, "associations", Associations)
})

var Associations = Type("Associations", func() {
	Meta("struct:pkg:path", "common/payloads")
	Field(1, "resources", ArrayOf(Resource))
})

var Resource = Type("Resource", func() {
	Meta("struct:pkg:path", "common/data")
	Field(1, "name", String)
})

Produces code like:

package payloads

type Event struct {
	Associations *payloads.Associations
}

and

package payloads

type Associations struct {
	Resources []*data.Resource
}
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@Albert-Coding
Copy link
Author

Poke

Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@Albert-Coding
Copy link
Author

Poke

@tchssk
Copy link
Member

tchssk commented Jan 30, 2024

There are two issues:

  1. Unneeded package name prefix for a qualified identifier (e.g. payloads.Associations) (resolved by Treat nested paths for struct:pkg:path Meta #3469)
  2. Missing imports (e.g. data)

The second issue is unclear whether it is a specification or a bug. The Meta DSL's godoc says:

Note: If that meta tag is used more that once in the same design, but with different values in the meta statement (ex. one type has Meta("struct:pkg:path", "types1") and another has Meta("struct:pkg:path", "types2")) then those two types cannot both contain a field of the same user type. For the same reason, you may not set a different custom package in a user type than the one set on a containing user type.

This specification can be reproduced by changing design as follows.

-Field(1, "resources", ArrayOf(Resource))
+Field(1, "resources", Resource)

goa gen outputs the following error:

attribute: type "Resource" has conflicting packages common/data and common/payloads

Should Goa print the same error for Array types?
Or can we improve the specification by resolving the missing imports?

@raphael
Copy link
Member

raphael commented Jan 30, 2024

Thank you for looking into this! This limitation was to help keep the implementation simple.

The main use case for struct:pkg:path is to make it possible for the code generated from two different services in the same design to share the same type definitions (by using the same package path in types defined in both). This makes it convenient for user code as the same type can be reused across as opposed to having to instantiate service specific structs. The intent (at least initially) was not to make it possible to define a complex set of packages. At the end of the day the code is generated so creating a modular set of packages has limited benefits.

For example making it possible to define multiple packages for types that are related would mean having to write code that detect circular dependencies. In general the code that deals with external packages is already pretty complex so my vote would be to make sure that the ArrayOf case generates the proper error message.

That being said if there is a strong case for making it possible to create multiple packages with types that have fields defined across the packages and if we can find an easy way to support it then that's great.

@tchssk
Copy link
Member

tchssk commented Feb 1, 2024

That's nice, but it will take some time to design, so I'll add an error message for now.
Thank you.

@raphael
Copy link
Member

raphael commented Feb 7, 2024

Great, thank you for the PR!

@raphael
Copy link
Member

raphael commented Mar 10, 2024

Closing this issue, the TL;DR is that there was a bug and a missing validation. The decision is to not allow defining complex package types so as to keep the code simple.

@raphael raphael closed this as completed Mar 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants