Support LSP document links - #56011
Conversation
9d2ae70 to
a50b793
Compare
e660f37 to
96ce1de
Compare
# Conflicts: # crates/editor/src/editor.rs
96ce1de to
9e5a33a
Compare
|
Dynamic registration seems to need to be fixed. Opened a follow up PR: #57749 |
`register_server_capabilities` / `unregister_server_capabilities` had no arm for `textDocument/documentLink`, so when a server saw our `documentLink.dynamicRegistration` capability and chose to register the provider dynamically, the registration silently fell into the `unhandled capability registration` warning. `document_link_provider` stayed `None`, `GetDocumentLinks::check_capabilities` returned false, and no `textDocument/documentLink` request was ever sent. Fixes up zed-industries#56011. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…dustries#57749) `register_server_capabilities` / `unregister_server_capabilities` had no arm for `textDocument/documentLink`, so when a server saw our `documentLink.dynamicRegistration` capability and chose to register the provider dynamically, the registration silently fell into the `unhandled capability registration` warning. `document_link_provider` stayed `None`, `GetDocumentLinks::check_capabilities` returned false, and no `textDocument/documentLink` request was ever sent. Follow-up to zed-industries#56011 Release Notes: - N/A Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
|
One more follow-up I wonder about: should we render document link ranges as underlined by default, similar to how VS Code does? Right now, Would you be open to that as a follow-up? |
|
I'd ask a designer for that, myself is not very open to that as it adds more visual noise than needed. |
|
Understood. I think the noise argument has a validity. Since I only mentioned it as a tentative suggestion, I will hold off on upstreaming this idea for now. |
`register_server_capabilities` / `unregister_server_capabilities` had no arm for `textDocument/documentLink`, so when a server saw our `documentLink.dynamicRegistration` capability and chose to register the provider dynamically, the registration silently fell into the `unhandled capability registration` warning. `document_link_provider` stayed `None`, `GetDocumentLinks::check_capabilities` returned false, and no `textDocument/documentLink` request was ever sent. Follow-up to zed-industries/zed#56011 Release Notes: - N/A Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Closes zed-industries#33587 https://github.com/user-attachments/assets/bbaea8a9-402e-485b-800e-2f4486142956 Release Notes: - Supported LSP document links (enabled by default, use `"lsp_document_links": false` to turn it off)
…dustries#57749) `register_server_capabilities` / `unregister_server_capabilities` had no arm for `textDocument/documentLink`, so when a server saw our `documentLink.dynamicRegistration` capability and chose to register the provider dynamically, the registration silently fell into the `unhandled capability registration` warning. `document_link_provider` stayed `None`, `GetDocumentLinks::check_capabilities` returned false, and no `textDocument/documentLink` request was ever sent. Follow-up to zed-industries#56011 Release Notes: - N/A Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Closes zed-industries#33587 https://github.com/user-attachments/assets/bbaea8a9-402e-485b-800e-2f4486142956 Release Notes: - Supported LSP document links (enabled by default, use `"lsp_document_links": false` to turn it off)
…dustries#57749) `register_server_capabilities` / `unregister_server_capabilities` had no arm for `textDocument/documentLink`, so when a server saw our `documentLink.dynamicRegistration` capability and chose to register the provider dynamically, the registration silently fell into the `unhandled capability registration` warning. `document_link_provider` stayed `None`, `GetDocumentLinks::check_capabilities` returned false, and no `textDocument/documentLink` request was ever sent. Follow-up to zed-industries#56011 Release Notes: - N/A Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Closes zed-industries#33587 https://github.com/user-attachments/assets/bbaea8a9-402e-485b-800e-2f4486142956 Release Notes: - Supported LSP document links (enabled by default, use `"lsp_document_links": false` to turn it off)
# Summary Adds **Hyperlinks**, an extension that turns text matching user-defined regex patterns into clickable links in the editor — e.g. `ISSUE-123` → your issue tracker, `#42` → a GitHub issue. It's a port of the VS Code extension [`dlevs/vscode-pattern-links`](https://github.com/dlevs/vscode-pattern-links) to Zed. - Extension repo: https://github.com/krawitzzZ/zed-hyperlinks - Language server repo: https://github.com/krawitzzZ/zed-hyperlinks-server - Extension ID: `hyperlinks-lsp` ## How it works Zed renders links returned by language servers through the LSP `textDocument/documentLink` request (added in [zed#56011](zed-industries/zed#56011), enabled by default). The extension provides a tiny language server that scans open documents for the configured regex rules and returns a `DocumentLink` for each match, with the target URL built from a template (`$0` = whole match, `$1`, `$2`, … = capture groups; `\$` for a literal `$`). Matching semantics mirror the upstream VS Code extension (JS `RegExp`). The server additionally reports a custom `hyperlink` LSP semantic token for every match, so matched text can be visually highlighted (see [Highlighting](#highlighting)). ## Why the language server is downloaded, not bundled Per the publishing guidelines, the extension does not ship the language server. Instead, the WASM extension downloads it at runtime from a pinned GitHub release of the separate [`zed-hyperlinks-server`](https://github.com/krawitzzZ/zed-hyperlinks-server) repo (`main.js` asset, version pinned in `src/lib.rs`), caches it under the extension's work dir, cleans up older cached versions, and runs it with Zed's bundled Node (`node_binary_path`). Download failures surface via `set_language_server_installation_status(Failed)`. ## Configuration There is no per-extension settings UI, so rules live under the language server's settings: ```json { "lsp": { "hyperlinks": { "settings": { "hyperlinkRules": [ { "linkPattern": "ISSUE-\\d+", "linkTarget": "https://myorg.atlassian.net/browse/$0" }, { "linkPattern": "#(\\d+)", "linkTarget": "https://github.com/my-org/my-repo/issues/$1", "languages": ["markdown", "plaintext"] } ] } } } } ``` Per-rule fields: - `linkPattern` (required) - `linkTarget` (required) - `linkPatternFlags` (optional JS regex flags; `g` always applied) - `languages` (optional list of LSP `languageId`s to scope the rule; empty = all) ## Highlighting Zed doesn't style document links on its own, so matches are clickable but look like ordinary text by default. The server therefore emits a custom `hyperlink` semantic token per match (multi-line matches are split into one token per line, as LSP requires). Users opt in via `settings.json` by enabling semantic tokens (off by default) and adding a rule for the `hyperlink` token type: ```json { "semantic_tokens": "combined", "global_lsp_settings": { "semantic_token_rules": [ { "token_type": "hyperlink", "underline": true, "foreground_color": "#4c9df3" } ] } } ``` The extension intentionally does not ship default semantic token rules: it provides a language server (not a language), and per Zed's docs shipping rules that way can override/break other language servers' configuration. Styling is left to the user's `semantic_token_rules`. ## Note on supported languages Zed has no "all languages" wildcard for extension-provided language servers, so the server is attached to an explicit list of common languages in `extension.toml` (Plain Text, Markdown, and popular programming languages). This is the closest equivalent to the VS Code extension's "all languages" default; more can be added on request. ## Testing - Installed and tested locally as a dev extension (links appear and open on Cmd/Ctrl-click; matches highlight once `semantic_tokens` + a `hyperlink` rule are set). - Language server (`node --test`, 31 tests): substitution, rule normalization, offset/position math, link computation, semantic-token encoding (single-line, delta-encoded multi-match, multi-line splitting, language filtering), plus end-to-end stdio LSP sessions covering `documentLink` and `semanticTokens/full`. - Extension: `cargo test` for the version/path helpers; `cargo build --target wasm32-wasip1` passes. - [x] I've read [CONTRIBUTING.md](../CONTRIBUTING.md) and followed the relevant guidance for adding or updating my extension.
Closes #33587
LSP.document.links.mov
Release Notes:
"lsp_document_links": falseto turn it off)