Since go does not have an explicit declaration of which interfaces one implements, it is hard to follow someone's code. I know that there is a command to show all the interfaces, but it is not very intuitive nor efficient.

Goland has the feature of showing a gutter when a function implements an interface. It would be nice to show maybe a codelens over the implementation and the type, or a similar solution as Goland.

Codelens: pasted

Goland: Golang x/tools/gopls: codelens to show implementations of interfaces

I found an extension that does kinda the opposite which is not very helpful in most scenario: galkowskit/go-interface-annotations Golang x/tools/gopls: codelens to show implementations of interfaces

Comment From: 2opremio

That's exactly how rust-analyzer handles traits

Comment From: icearith

this feature seems exactly what I want.

Comment From: Shawn-Huang-Tron

This feature is very useful and we use it frequently. A lot of my friends doesn't like vscode-go just because of the leak of this feature.So they change to goland.Hope to add such a feature.

Comment From: tony-sol

+1 this would be an extremely usefull

Comment From: hyangah

cc @golang/tools-team This can be expensive depending on the size of the search space, but given that there are already similar functionalities (Find All Implementations, or LSP textDocument/implementation), I guess gopls has sufficient information to package this info as a codelens. Is there any concern?

Comment From: findleyr

We have this in our long-term roadmap for gopls (along with a references codelens), most likely once we build out indexes that can satisfy these queries cheaply. Moving to the gopls issue tracker.

Comment From: tkgalk

I found an extension that does kinda the opposite which is not very helpful in most scenario: galkowskit/go-interface-annotations

It actually had bidirectional code lens, but only for structs. I released a 0.1.0 version that makes it work on non-struct types as well. Underneath, it's using the "Find Implementations" and "Find References" VS Code feature, so the gopls version would still be miles better. But it should tide people over until then, if they really need this feature. :)

Comment From: adonovan

We are in the process of rewriting gopls' implementations feature so that it uses a global persistent index. Currently gopls must type-check every package in the workspace (since any package might define a type that satsifies an arbitrary interface), but in the next month or so we expect that gopls will be able to make cache hits in the persistent index without type-checking, so it should dramatically reduce the cost of an implementations query in a large workspace on all but the very first run after installing a new gopls executable.

At that point it might become feasible to implement something like this feature request as a code lens.

Comment From: tooltitude-support

@BIKA-C Our team is working on a golang extension which augments the standard go language server with convenience and productivity features which are out of scope for gopls either due to infeasibility in larger repositories or lack of resources. We have more than 20 code actions now. Is there any way to contact you to discuss features you might want?

@adonovan Hope you don't mind us commenting in this repository.

P.S. The extension link is: https://marketplace.visualstudio.com/items?itemName=tooltitudeteam.tooltitude

Comment From: adonovan

@adonovan Hope you don't mind us commenting in this repository.

No, of course, that's fine.

Where can I find the source code for Tooltitude? The download page took me to an (obfuscated) executable, and of course there's no way I'm going to run that on my machine. Alternatively, is there any documentation about how it relates to gopls?

Comment From: marlongerson

Would be nice to have a gutter icon as well like in Goland.

Comment From: tkgalk

Any updates on this one? I tried to implement something for neovim, but I can't seem to get gopls to return what I what, so I guess this is still not implemented. Is that correct?

Comment From: Tesohh

I found an extension that does kinda the opposite which is not very helpful in most scenario: galkowskit/go-interface-annotations

It actually had bidirectional code lens, but only for structs. I released a 0.1.0 version that makes it work on non-struct types as well. Underneath, it's using the "Find Implementations" and "Find References" VS Code feature, so the gopls version would still be miles better. But it should tide people over until then, if they really need this feature. :)

i think they added this in the extension, but still, it would be nice to have these types of features in the go extension by default

Comment From: tkgalk

i think they added this in the extension, but still, it would be nice to have these types of features in the go extension by default

https://github.com/tkg-codes/go-interface-annotations <- I have a hacked solution in my VSCode extension. But it might start to chug on large codebases, I haven't tested it thoroughly.

I would still like to have this be supported by gopls instead of just VSCode, as otherwise I don't think support for Vim/Neovim, Sublime, Zed et cetera is possible. If this feature would be supported by gopls directly then it would be much more performant.

Comment From: adonovan

gopls now has an index of implementations, so it can compute the corresponding types for a single type efficiently, but this feature needs the ability to query the correspondences for every type in the file. There's still substantial work to do to make an efficient batch-parallel implementations query. Until then, the client side code lens implementation is as good as one can expect, although of course it works only in VS Code.

Comment From: tkgalk

Unrelated, but in case someone gets here by googling and sees your last post about VSCode.

I'm working on a neovim version as well, and for anyone interested there is already lsp-lens.nvim, too. :)

So while gopls version would be better, there are client-side solutions out there.

Comment From: adonovan

Someone kindly offered (via email) to contribute this feature. For posterity and transparency, I've shared part of my response to them below.

--

I think this particular feature may be quite challenging to implement efficiently, even now that we've completed the changes we were planning to the architecture of gopls. (In fact, our changes may actually have made this problem more difficult because it is more expensive to join type information from an arbitrary pair of packages.) You may find this blog post and this talk a useful introduction to some of the recent design changes.

Each of the proposed annotations on a type requires a global query to compute the set of interfaces that it implements, or is implemented by. (Yes, the "find implementations" algorithm works both ways.) When I say global, I mean every package, not just the forward or reverse dependencies, because interfaces can be implemented by types that aren't dependencies in either direction. And any change to any file can in principle invalidate the information previously computed, so it's far from clear to me what the invalidation story is for this feature.

This is unlike most other features, which are either a property of forward dependencies, e.g. diagnostics, type information, static analysis, etc, which are served by the index; or of reverse information, e.g. references, also served from an index; or both, e.g. rename, which requires type checking the entire reverse closure (which is expensive, but the feature is infrequently used).

A more achievable goal might be to report only the relationships between each declared type and some other type mentioned in the same package, so for example, os.File would say "implements io.Reader, io.Writer, ... and perhaps others", and the "perhaps others" part could be a link that activates the expensive global query to compute the definitive answer for that particular type at that moment. In order to implement that, you would just need to gather the set of "interesting" types after type checking, compute the pairwise implements relation, and record the set of matches in the source.Package.

--

Comment From: findleyr

@adonovan I'm not sure this is so infeasible. We already keep a global index of package data live in memory: the set of type checking diagnostics. We also have a serializable format for method sets. Suppose that, as part of analyzing a package, we kept the method set index in memory (IIRC, the serialized method set data is quite small). How expensive would it be to, for all types declared in a single file (i.e. within the context of a codelens request), cross reference this method set index? Suppose also that a small false positive rate were acceptable, as I think may be the case here (or we could detect potential false positives and re-type check a small number of packages to eliminate them).

Comment From: JulianGuSM

Any updates on this one?

Comment From: gopherbot

Change https://go.dev/cl/619115 mentions this issue: src/goCodeLens: show codelens for implementations of symbols

Comment From: caozhuozi

!

Comment From: gowtham-swiggy

@gopherbot any update on this. This will be a helpful feature

Comment From: adonovan

No direct progress on this issue, sorry. However, we just (moments ago) merged a new feature, support for Type Hierarchy, which allows you to browse named types by their subtype/supertype relationship. To try it out, build gopls from master and use the "Show type hierarchy" item on the context menu. Also, we just changed the behavior of "Go to implementations" so that it reports interface/subinterface relationships. Both of these changes should make it easier to navigate type relationships.

Comment From: hedongyouxia

@adonovan When will this feature be adapted?

Comment From: adonovan

When will this feature be adapted?

As soon as we have a design, and implementing becomes a priority. Less flippantly: it is unclear how to implement this feature so that it is both correct and efficient, which is our usual bar; we really don't want to present incorrect or stale data in the UI. If we had a design, there would be more enthusiasm for implementing it; this feature certainly garners lots of interest.

Comment From: ufukty

I noticed that since the first time I visit this feature request and left an upvote, my opinion has changed. Thinking about fake conformances caused by interfaces from different dependencies happen to fully or partially share same method list; developers are already better be leaving conformance assertions like below to notify future maintainers on what interfaces the type needs to keep conforming in future. Isn't the need for this feature narrows down enough to make it a niche after adopting such behavior?

type h string
func (h) ServeHTTP(w http.ResponseWriter, r *http.Request)
var _ http.Handler = h("") // conformance assertion

Comment From: hedongyouxia

@adonovan

As soon as we have a design, and implementing becomes a priority. Less flippantly: it is unclear how to implement this feature so that it is both correct and efficient, which is our usual bar; we really don't want to present incorrect or stale data in the UI. If we had a design, there would be more enthusiasm for implementing it; this feature certainly garners lots of interest.

Thanks for the reply, but I think there are already plugins that implement this feature, why not consider their implementation? such as tooltitude.

Comment From: ocean2811

For VS Code, I recommend using the GoGo CodeLens extension to achieve these Code Lens features. It provides similar functionality to Tooltitude while being ​completely free.

Note:​​ GoGo CodeLens is a third-party extension. You should ​conduct your own security review​ and determine if it's suitable for your use.

Comment From: anirudhagarwal365

I have tried to create something very similar to what GoLand provides - Go Implementation Lens

Do give it a try out. Have also implemented caching for faster lookups. Do give it a try and will be very actively resolving any issues reported.

Comment From: hedongyouxia

For VS Code, I recommend using the GoGo CodeLens extension to achieve these Code Lens features. It provides similar functionality to Tooltitude while being ​completely free.

Note:​​ GoGo CodeLens is a third-party extension. You should ​conduct your own security review​ and determine if it's suitable for your use.

@ocean2811 Thanks, I used the plugin you mentioned, but it consumes too many resources. When I open large projects (like the Kubernetes source code), it uses a lot of CPU, causing my computer to freeze.

Comment From: hedongyouxia

I have tried to create something very similar to what GoLand provides - Go Implementation Lens

Do give it a try out. Have also implemented caching for faster lookups. Do give it a try and will be very actively resolving any issues reported.

@anirudhagarwal365 Thanks, I used the plugin you mentioned, but it provides some simple functions. I hope it can provide methods to view struct instance implementations, the number of implemented interfaces, and when clicking on code lens, these results can be opened in a new page, similar to how gopls in VSCode shows all implementations. This way, after viewing a specific implementation, you can close the already viewed results. Note: You can refer to the implementation results of tooltitude below

Comment From: anirudhagarwal365

I have tried to create something very similar to what GoLand provides - Go Implementation Lens

Do give it a try out. Have also implemented caching for faster lookups. Do give it a try and will be very actively resolving any issues reported.

@anirudhagarwal365 Thanks, I used the plugin you mentioned, but it provides some simple functions. I hope it can provide methods to view struct instance implementations, the number of implemented interfaces, and when clicking on code lens, these results can be opened in a new page, similar to how gopls in VSCode shows all implementations. This way, after viewing a specific implementation, you can close the already viewed results. Note: You can refer to the implementation results of tooltitude below

@hedongyouxia Clicking on the code lens already does open up in a new tab. If there are multiple implementations, it shows up the list.

Looks like you were trying to attach something for reference - that is not showing up in your comment.

Would love to work on something to make it simpler for everyone.

Comment From: hedongyouxia

@anirudhagarwal365 What I mean is that if an interface has multiple implementations, clicking the code lens should display results similar to those of gopls querying all implementations (in a new tab, allowing operations like closing), and also whether it's possible to add a code lens for references and interface methods, which would be very useful.

Comment From: hedongyouxia

@anirudhagarwal365 Sorry,my network have some problem for upload a picture.

Image

Comment From: anirudhagarwal365

Oh wow. This makes it very clear. This looks like a pretty neat setup. Lemme see what all I can pick up. Thanks for the feedback though.

Also, looks like this is an extension that you are using. If you don't mind - can you share the name of this? What do you expect my extension to provide that the one that you have shared a screenshot of, does not have?

Comment From: hedongyouxia

@anirudhagarwal365 I use the plugin is Tooltitude for Go (GoLang),it not support the interface code lens in vendor or mod pkg and it not free.

Comment From: anirudhagarwal365

Hi @hedongyouxia I have updated the extension with the changes that you proposed. Please go through the readme file to see a list of changes made. Also, more feedback is always welcome.

Comment From: anirudhagarwal365

@adonovan Would you also mind giving this extension a try - Go Implementation Lens

Would love to hear your feedback on the product and see if this is what you had in mind?

I had been missing this feature since I moved from GoLand to VSC. I am willing to put in the effort to solving this problem for everyone in the best possible way.

Comment From: adonovan

@adonovan Would you also mind giving this extension a try - Go Implementation Lens Would love to hear your feedback on the product and see if this is what you had in mind?

I haven't run the code, but it appears to loop over all the symbols in the document and make implementations and references queries to gopls for each one. That won't scale well for large documents and large workspaces.

Comment From: anirudhagarwal365

I haven't run the code, but it appears to loop over all the symbols in the document and make implementations and references queries to gopls for each one. That won't scale well for large documents and large workspaces.

Thanks for taking a look. I have been testing it with my internal codebase which is moderately sized (not super large) and seems to work fine. There's a delay the first time a time is opened and after that I cache the results but I see your point as well. If possible - could you point me in the right direction to solve this? Are you thinking about generating a dependency tree on top of what is present in the language server and power these indicators or something completely different?

Comment From: adonovan

If possible - could you point me in the right direction to solve this? Are you thinking about generating a dependency tree on top of what is present in the language server and power these indicators or something completely different?

As I mentioned in https://github.com/golang/go/issues/56695#issuecomment-3024009745, we don't have a design in mind, but we do have a requirement that it must be scalable. This means the implementation must either return stale and/or heuristic results (allowing it to avoid type checking), or will require building new invalidation mechanisms into gopls.

Comment From: findleyr

@anirudhagarwal365 you mentioned that you miss this feature from Goland. Can you say more about what you use it for? VS Code provides a way to find implementations, references, and implementors. Furthermore, it highlights unused (unexported) symbols with a diagnostic. What is it about seeing the number of references or implementations as a code lens that is useful?

(This is not meant to be snarky: there are clearly a large number of users who agree; I am just genuinely curious because I've never wanted this feature myself).

I can see the use case for a code lens that highlights the primary interface implemented by a concrete type, though I think an inlay hint or explicit Go comment may be a better UI for this. However, I don't understand the use case for listing "9 refs" or "3 interfaces" -- it just seems distracting to me; the information is available if I want it...