goplantuml icon indicating copy to clipboard operation
goplantuml copied to clipboard

doesn't draw the IS-A relation when type implements an interface in different packages

Open hitzhangjie opened this issue 3 years ago • 6 comments

image

Type helloworldServiceImpl implements the interface defined in package helloworld, the IS-A relation is not drawed.

the generated plantuml is :

@startuml

package "main" {
	class "helloworldServiceImpl" as main.helloworldServiceImpl <<E,#FFCC00>> {
		+Hello(ctx: context.Context, req: *helloworld.Request, rsp: *helloworld.Response): error
	}
}


	main.helloworldServiceImpl ..> helloworld.Request : <<use>> 
	main.helloworldServiceImpl ..> helloworld.Response : <<use>> 

package "helloworld" {
	interface "HelloworldClientProxy" as helloworld.HelloworldClientProxy {
		+Hello(ctx: context.Context, req: *helloworld.Request, opts: client.Option): (rsp: *helloworld.Response, err: error)
	}
}


	helloworld.HelloworldClientProxy ..> helloworld.Request : <<use>> 
	helloworld.HelloworldClientProxy ..> helloworld.Response : <<return>> 

package "helloworld" {
	class "HelloworldClientProxyImpl" as helloworld.HelloworldClientProxyImpl <<V,Orchid>> {
		-client: client.Client
		-opts: client.Option
		+Hello(ctx: context.Context, req: *helloworld.Request, opts: client.Option): (rsp: *helloworld.Response, err: error)
	}
}


	helloworld.HelloworldClientProxyImpl ..> helloworld.Request : <<use>> 
	helloworld.HelloworldClientProxyImpl ..> helloworld.Response : <<return>> 

package "helloworld" {
	interface "HelloworldService" as helloworld.HelloworldService {
		+Hello(ctx: context.Context, req: *helloworld.Request, rsp: *helloworld.Response): err: error
	}
}


	helloworld.HelloworldService ..> helloworld.Request : <<use>> 
	helloworld.HelloworldService ..> helloworld.Response : <<use>> 

package "helloworld" {
	class "Request" as helloworld.Request <<E,#FFCC00>> {
		-state: impl.MessageState
		-sizeCache: int32
		-unknownFields: []byte
		+Reset()
		+String(): string
		+ProtoMessage()
		+ProtoReflect(): protoreflect.Message
		+Descriptor(): ([]byte, []int)
	}
}



package "helloworld" {
	class "Response" as helloworld.Response <<E,#FFCC00>> {
		-state: impl.MessageState
		-sizeCache: int32
		-unknownFields: []byte
		+Reset()
		+String(): string
		+ProtoMessage()
		+ProtoReflect(): protoreflect.Message
		+Descriptor(): ([]byte, []int)
	}
}



	helloworld.HelloworldClientProxyImpl -up-|> helloworld.HelloworldClientProxy


@enduml

hitzhangjie avatar Jan 06 '21 10:01 hitzhangjie

It would be interesting to see the code, since the example you posted has two different signatures in the Hello Method.

Hello(ctx: context.Context, req: *helloworld.Request, opts: client.Option): (rsp: *helloworld.Response, err: error) Hello(ctx: context.Context, req: *helloworld.Request, rsp: *helloworld.Response): err: error

Notice the parameters and the returns are different. If the code is the same, then this means this tool just helped you see it :) . If not, then the tools is taking the information wrong :(. Is it possible for you to confirm this? Notice that the HelloworldClientProxyImpl does have the correct signature and it does indeed represents the correct relationship with the interface

jfeliu007 avatar Jan 06 '21 16:01 jfeliu007

  • interface type: HelloworldService, the right-most rectange in the picture
  • implemention type: helloworldServiceImpl, the left-most rectange in the picture

they have the same signature: Hello(ctx: context.Context, req: *helloworld.Request, rsp: *helloworld.Response): err: error

hitzhangjie avatar Jan 06 '21 18:01 hitzhangjie

I see, my mistake. Usually in my code I don't reference the package within the same package. For example. Plantuml has the following structure

type Struct struct {
	PackageName         string
	Functions           []*Function
	Fields              []*Field
	Type                string
	Composition         map[string]struct{}
	Extends             map[string]struct{}
	Aggregations        map[string]struct{}
	PrivateAggregations map[string]struct{}
}

and the following function

func (st *Struct) ImplementsInterface(inter *Struct) bool {
...
}

notice I am not using (inter *parser.Struct) which is the case for you. I am not sure if that is the problem with the parsing of the relationship. Since the parser will assume the package and make the relationship with it. Maybe the interface needs to be defined as

Hello(ctx: context.Context, req: *Request, rsp: *Response): err: error

Instead, since Request and Response both belong to that package. I'd like to try what you are doing to see what the parser returns. If you could share the code it will help me see what is going on. I understand sometimes it is no possible, so something that compiles and produces a similar outcome will help me reproduce it.

jfeliu007 avatar Jan 06 '21 19:01 jfeliu007

@jfeliu007 Thanks for your sharing, I'll check and test it later.

hitzhangjie avatar Jan 07 '21 05:01 hitzhangjie

Hi @hitzhangjie , is this still an issue?

jfeliu007 avatar Mar 01 '21 19:03 jfeliu007

Yes, I think the problem still exists.

hello.zip

I uploaded an attachment. This contains a complete project based on some microservice framework, and a file.puml generated by the latest gouml.

hitzhangjie avatar Mar 12 '21 12:03 hitzhangjie