For a long time I’ve been annoyed at looking at a binding’s type but not having a convenient way to navigate to that type’s definition.
For example:
es <- fetchEntitiesFromDb
Hovering reveals es :: [Entity], but there’s no quick way to jump to the definition of Entity.
Sure, you can use typed holes, but the process is clunky:
Add a typed hole (es :: _)
Maybe add ScopedTypeVariables
Wait for GHC to infer the type
Realize Entity isn’t in scope
Wait for the import suggestion
Import it
Then go to its definition
Most often I will just resort to searching for Entity = throughout the code base because it’s faster.
That’s why I drafted the hls-underlying-type-plugin.
For the example above, the plugin will generate a Go to definition of Entity (inferred from es's type) action which will take you straight to Entity’s definition. It works on nested types too - if you have a ContainerType Entity you will see two code actions - Go to definition of ContainerType and Go to definition of Entity.
Here it is in action:
The PR has just been put up and it probably has a lot of quirks to iron out but it was very fun implementing it and I encourage everyone to go mess around with the HLS code base.
Doesn’t “Go to Type Definition” basically do what you are describing? This also works for multiple types under the cursor
Lol, I’ve never seen “Go to Type Definition”. Funnily, I discussed this plugin with colleagues before implementing it and none of them were aware of it too. People’s feedback on reddit seems to suggest that this is the case for many more.
I still find the code actions more convenient because the VS Code UI is clunkier than just selecting “Go to X"/Y”. Maybe this plugin should simply sit on top and generate those?
I still find the code actions more convenient because the VS Code UI is clunkier than just selecting “Go to X"/Y”. Maybe this plugin should simply sit on top and generate those?
That’s exactly what your plugin does right now, as it uses the AtPoint.pointCommand and getTypeDefinition, which both power the go to Type Definition request.
I suppose we could add the CodeAction , but I personally would not use CodeActions for code navigation.
If users would like this kind of CodeAction, I think adding this to ghcide is preferable to a separate plugin.
However, Go to Type Definition is a standard LSP feature, thus likely the most discoverable way to navigate the code.
Also, well done with the plugin, it looks like it is mostly doing the right thing, which is pretty impressive on a first attempt!
I didn’t know HLS already had this functionality either, and it’s actually pretty awesome. It even properly presents choices when the expression has a compound type, showing each type that one can go to (i.e. those defined in local units). I didn’t expect the LSP spec to be flexible enough for that.
So I don’t think any new feature is needed.
For what it’s worth, in VSCode one can easily add a keybinding to “Go to type definition”. Most desktops also have some universal right-click keybinding, e.g. Shift-F10 in Windows and Gnome, at least. EDIT: Whoops, not actually true, but Shift-F10 is supported by most applications in practice one way or another.