Skip to content

feat: add hls-document-link-plugin to support LSP document links#4898

Open
jetjinser wants to merge 9 commits into
haskell:masterfrom
jetjinser:documentLink
Open

feat: add hls-document-link-plugin to support LSP document links#4898
jetjinser wants to merge 9 commits into
haskell:masterfrom
jetjinser:documentLink

Conversation

@jetjinser

Copy link
Copy Markdown
Contributor

This PR introduces a new plugin hls-document-link-plugin that adds LSP documentLink support to Haskell Language Server.

This plugin automatically extracts documentation links for symbols in source code. These links are the same ones that power the [Documentation] link in the hover information.

Changes

  • New plugin: hls-document-link-plugin – extracts clickable links and provides them as document links. Editors can then open these links directly from the source code.
  • Configuration: Added documentLinkOn option to enable/disable the feature (default: True).

Usage

In Neovim 0.12 or later, you can place the cursor on the link and press gx to open it directly in your default browser.

The feature can be turned off by setting documentLinkOn: false in the HLS configuration.


Note. The getDocumentLinks helper for lsp-test is implemented manually here, but a same change is also pending in haskell/lsp#638. After that PR is merged and the dependency is updated, this part can be simplified.

@jetjinser jetjinser changed the title feat: ddd hls-document-link-plugin to support LSP document links feat: add hls-document-link-plugin to support LSP document links Apr 18, 2026

@fendor fendor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Welcome back and happy to see you tackle this issue!

This looks pretty good to my cursory review. I have mostly nitpicks and a couple of clarification questions.
Other than that, LGTM :)

Comment thread plugins/hls-document-link-plugin/test/Main.hs Outdated
Comment thread plugins/hls-document-link-plugin/test/Main.hs Outdated
Comment on lines +98 to +99
-- custom Eq to ignore some details, such as specific URI
-- not symmetry

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
-- custom Eq to ignore some details, such as specific URI
-- not symmetry
-- Custom Eq to ignore some details, such as specific URI.
-- This is not a lawful instance as it doesn't obey the `symmetry` law. Use at your own risk and only in tests.

Comment thread plugins/hls-document-link-plugin/test/testdata/ImportModule.hs Outdated
Comment thread plugins/hls-document-link-plugin/src/Ide/Plugin/DocumentLink.hs Outdated
Comment thread plugins/hls-document-link-plugin/src/Ide/Plugin/DocumentLink.hs Outdated
Comment thread plugins/hls-document-link-plugin/src/Ide/Plugin/DocumentLink.hs Outdated
Comment thread plugins/hls-document-link-plugin/src/Ide/Plugin/DocumentLink.hs Outdated
@fendor

fendor commented Apr 18, 2026

Copy link
Copy Markdown
Collaborator

Also, I am wondering whether this has any overlap with #4746 and the Documentation and Source links in the hover message?

@fendor

fendor commented Apr 18, 2026

Copy link
Copy Markdown
Collaborator
Screencast_20260418_150352.webm

This is the behaviour on vscode... I suppose that's not the expected behaviour?

@fendor fendor added the status: needs review This PR is ready for review label Apr 18, 2026
@jetjinser

jetjinser commented Apr 22, 2026

Copy link
Copy Markdown
Contributor Author

Also, I am wondering whether this has any overlap with #4746 and the Documentation and Source links in the hover message?

Yes. The links provided in this PR share the same source as the 'Documentation' links in the hover messages. The goal here is to expose that information through a more native and convenient LSP feature (DocumentLink).

Therefore, documentLink provides a local hackage link, not the online link provided in #4746.

@jetjinser

jetjinser commented Apr 22, 2026

Copy link
Copy Markdown
Contributor Author

Screencast_20260418_150352.webm

This is the behaviour on vscode... I suppose that's not the expected behaviour?

I’ve done some local testing and noticed the same behavior in VSCodium.

  1. If I manually run xdg-open on the generated URI (e.g., file:///nix/store/.../docs/index.html#v:nodeChildren), it opens correctly in the external browser. This is also why gx works as expected in Neovim. It seems VSCodium's default behavior is to capture file:// URIs and render them in an internal webview/tab instead of passing them to the system handler?

  2. Additionally, I found a minor UX conflict: when a DocumentLink is present, VSCodium's Ctrl+Click defaults to following the link, which "shadows" the Go to Definition action. This might cause some confusion?


EDIT:
For the first question,

    "workbench.externalUriOpeners": {
        "file:///*": "simpleBrowser.open"
    },

Ideally, this might work? However, I still couldn't get it to open in either an internal or external browser.

@crtschin

Copy link
Copy Markdown
Collaborator

However, I still couldn't get it to open in either an internal or external browser.

I think this might be a lsp consumer problem. I'm using Helix and by default all file:// links get opened by the editor as well, and only other links get the xdg-open treatment. I guess from an editor's pov, there is a legitimate usecase for opening html files in the editor.

I wonder, what's the hueristic nvim uses to determine whether to open files with xdg-open or locally in the editor?

@jetjinser

jetjinser commented Apr 22, 2026

Copy link
Copy Markdown
Contributor Author

I wonder, what's the hueristic nvim uses to determine whether to open files with xdg-open or locally in the editor?

Nvim doesn't attempt any heuristics.

It simply uses vim.ui.open, which always uses xdg-open (the equivalent command on other platforms).

https://github.com/neovim/neovim/blob/2ca31eddae0748de5d54207c2d34f7405fed4f29/runtime/lua/vim/_core/defaults.lua#L147-L181

It's possible that Neovim doesn't have a particular reason to open HTML, while a GUI editor does, and the former distinguishes between gx (opens ... using the system default handler) and gf (Edit the file ...). XX

@vidit-od

Copy link
Copy Markdown
Collaborator

Additionally, I found a minor UX conflict:

We also should take into consideration how to disable the underlines.
The by default view makes everything look too cluttered due to lots of underlines.

example :
image

@fendor

fendor commented Apr 30, 2026

Copy link
Copy Markdown
Collaborator

We also should take into consideration how to disable the underlines.

Disabling should work, otherwise this is a VSCode / theme setting, so not in the scope of this PR

@fendor

fendor commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

I think disabling the plugin by default is most likely not a great idea, having a couple of disabled-by-default plugins increases maintenance burden at no benefit for the user.
@wz1000 and I talked, and perhaps it might be a good middle ground if the document links were only shown in haddock comments. Otherwise, the documentation and source links currenlty have this feature already covered.
What do you think about this @jetjinser?

@jetjinser

Copy link
Copy Markdown
Contributor Author

I think disabling the plugin by default is most likely not a great idea, having a couple of disabled-by-default plugins increases maintenance burden at no benefit for the user.
@wz1000 and I talked, and perhaps it might be a good middle ground if the document links were only shown in haddock comments. Otherwise, the documentation and source links currenlty have this feature already covered.
What do you think about this @jetjinser?

Fair point! But I’m not entirely sure what “shown only in haddock comments” would actually look like -- what kind of content would get a documentLink attached?

As a side note, I later wired up documentLink myself in Neovim through config, and indeed the current hover info is already enough for my needs. (Also, considering it doesn’t seem very practical in VSCode, I (offensively) suspect it’s an interaction that wasn’t really thought through... XD)

@fendor

fendor commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

-- what kind of content would get a documentLink attached?

I imagined everything that Haddock was able to link, but thinking about it, if haddock was able to link it... then source and documentation link would presumably work already?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: needs review This PR is ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants