Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Show links to full ty diagnostics - #462

#462
Merged
AlexWaygood merged 2 commits into
mainastral-sh/ty-vscode:mainfrom
alex/full-compiler-diagnosticastral-sh/ty-vscode:alex/full-compiler-diagnosticCopy head branch name to clipboard
Jun 25, 2026
Merged

Show links to full ty diagnostics#462
AlexWaygood merged 2 commits into
mainastral-sh/ty-vscode:mainfrom
alex/full-compiler-diagnosticastral-sh/ty-vscode:alex/full-compiler-diagnosticCopy head branch name to clipboard

Conversation

@AlexWaygood

Copy link
Copy Markdown
Member

Summary

This is the ty-vscode companion PR to astral-sh/ruff#26269. See the description on that PR for a full breakdown of the feature and a demo video of it in action.

This was all written and checked by codex. I'm unfamiliar with both TypeScript and writing VSCode extensions, so I didn't even try to review it :-)

Implementation details (Codex-authored)

Advertise the experimental fullDiagnosticOutput capability and replace the code of each diagnostic for which the server provides full output with a “Click for full diagnostic” link. Back each link with a virtual text document containing the server-rendered plain text. Append any existing rule-documentation URL to that virtual document so replacing the diagnostic code with a link does not hide access to the rule documentation.

Support push, document-pull, and workspace-pull diagnostics. Store rendered contents in the virtual-document provider instead of reading the current diagnostic array by index because pull reports can be rejected by vscode-languageclient result-ID precedence logic. Tag each converted pull report with an extension-local ID, and commit its rendered contents to the cache only after transformed diagnostics for that same ID appear in the VS Code diagnostic collection. This prevents discarded pull results from overwriting current content while retaining the simple index-based virtual URI scheme.

Handle workspace pulls directly in middleware because vscode-languageclient 9 captures its original reporter in a closure; replacing the reporter therefore cannot decorate reports before the library applies its result-ID precedence check. Serialize conversion of workspace-pull partial results, discard results from superseded or cancelled requests, and feed converted reports through the original reporter to preserve the built-in precedence behavior.

Clear cached virtual documents on server restart and extension disposal. Add a link from the extension contributor documentation to the server protocol documentation.

Test Plan

See astral-sh/ruff#26269

Advertise the experimental fullDiagnosticOutput capability and replace the code of each diagnostic for which the server provides full output with a “Click for full diagnostic” link. Back each link with a virtual text document containing the server-rendered plain text. Append any existing rule-documentation URL to that virtual document so replacing the diagnostic code with a link does not hide access to the rule documentation.

Support push, document-pull, and workspace-pull diagnostics. Store rendered contents in the virtual-document provider instead of reading the current diagnostic array by index because pull reports can be rejected by vscode-languageclient result-ID precedence logic. Tag each converted pull report with an extension-local ID, and commit its rendered contents to the cache only after transformed diagnostics for that same ID appear in the VS Code diagnostic collection. This prevents discarded pull results from overwriting current content while retaining the simple index-based virtual URI scheme.

Handle workspace pulls directly in middleware because vscode-languageclient 9 captures its original reporter in a closure; replacing the reporter therefore cannot decorate reports before the library applies its result-ID precedence check. Serialize conversion of workspace-pull partial results, discard results from superseded or cancelled requests, and feed converted reports through the original reporter to preserve the built-in precedence behavior.

Clear cached virtual documents on server restart and extension disposal. Add a link from the extension contributor documentation to the server protocol documentation.
Comment thread CONTRIBUTING.md Outdated
@dhruvmanila

Copy link
Copy Markdown
Member

I saw the test plan in the ty PR but I think it only showcases what the diagnostic look like and the flow with the default extension settings. Can you try using workspace diagnostics as well just to make sure it's working well? Also, can you open multiple full diagnostic windows either of the same diagnostic or multiple diagnostics? Does this re-use the same window for displaying diagnostics or opens another window? If it's the latter, can you make sure those windows are not rendering the same diagnostics and the contents are actually different (just to make sure there's no sync between these diagnostic windows). I can try to think of other scenarios but this is what comes to my mind right now.

@MichaReiser

Copy link
Copy Markdown
Member

For workspace diagnostics. What's very important is that we only send new diagnostics or clients will start to lag. That's maybe something worth testing

@AlexWaygood

Copy link
Copy Markdown
Member Author

Here's what it looks like with multiple diagnostics open at once:

Screen.Recording.2026-06-25.at.14.56.44.mov

@AlexWaygood

Copy link
Copy Markdown
Member Author

Here's what happens if you try to open the same diagnostic multiple times or if the diagnostic goes stale:

Screen.Recording.2026-06-25.at.15.01.51.mov

@dhruvmanila dhruvmanila left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you!

I've glanced through it but haven't looked into much detail here.

And, thanks for testing it more and sharing the videos!

@AlexWaygood

Copy link
Copy Markdown
Member Author

Here's a video using the feature in homeassistant with workspace diagnostics enabled. It doesn't feel laggy at all to me and it seems to be working great:

Screen.Recording.2026-06-25.at.17.01.16.mov

I also did some testing to see if it started to lag when I added some new diagnostics and it also seemed fine to me. The "problems" count at the bottom of the screen stayed the same at 63,000 thorughout

AlexWaygood added a commit to astral-sh/ruff that referenced this pull request Jun 25, 2026
…eature (#26269)

## Summary

Fixes astral-sh/ty#1731. See
astral-sh/ty-vscode#462 for the companion
ty-vscode PR.

This PR implements a parallel to rust-analyzer's "Click for full
compiler diagnostic feature" in its VSCode extension. Here's a video of
rust-analyzer's feature in action in VSCode:


https://github.com/user-attachments/assets/7c14c7d6-46ea-4716-9f05-4df032cdc913

The feature is implemented by allowing LSP clients to advertise an
experimental `fullDiagnosticOutput` capability. For clients that
advertise this capability, we include both a plain-text rendering and
the original diagnostic identifier in `Diagnostic.data`; otherwise, we
retain the existing fix-only payload and avoid the rendering cost.

The one (significant) part of rust-analyzer's feature that is not
implemented in this PR is full color rendering of diagnostics. This is
left out of scope for this PR, as it would have led to a significant
increase in code, and can be done as a followup.

## Prior art in other LSPs

rust-analyzer is the best known LSP that provides this kind of feature.
Similar features are also found in
[Flow](https://github.com/facebook/flow/blob/main/packages/flow-for-vscode/src/FlowLanguageClient/DetailedDiagnostics.ts)
and
[wsgl-analyzer](https://github.com/wgsl-analyzer/wgsl-analyzer/blob/main/editors/code/src/client.ts).

Pyrefly has [experimental support for Markdown
rendering](https://github.com/facebook/pyrefly/blob/3ca46218e4d5b63f0d079449d93376d535682795/pyrefly/lib/lsp/non_wasm/server.rs#L681-L765)
in tooltips, but this is an orthogonal feature. Here's codex's summary
of the differences between the two features.

<details>
<summary>Codex comparison</summary>

## Full compiler diagnostics and Markdown diagnostic messages

ty’s full-diagnostic feature and Pyrefly’s Markdown diagnostic-message
support improve diagnostic presentation at different layers and are
largely complementary.

The ty feature follows the model established by rust-analyzer. The
language server preserves the ordinary concise `Diagnostic.message` but
attaches a second, substantially richer representation in
`Diagnostic.data.rendered`. This rendering can contain source snippets,
annotated spans, notes, and other multiline context that would be
unwieldy inside a normal diagnostic hover.

ty-vscode detects the additional data and replaces the displayed
diagnostic code with a **Click for full diagnostic** link. Following the
link opens the rendered report in a read-only virtual document. This
requires bespoke client middleware and a virtual-document provider, but
clients that do not understand the extension can safely ignore the
additional `data` and continue displaying the standard concise
diagnostic.

Repurposing `Diagnostic.code` as a link means that ty must preserve the
original diagnostic identifier elsewhere. It therefore includes
`data.diagnostic_id`, which allows the server to recover identifiers
such as `invalid-argument-type` when processing subsequent code-action
requests.

The protocol is documented in [ty’s language-server
documentation](https://github.com/astral-sh/ruff/blob/9f12f376467bd84e0aff651c09860e5bdbc8fc52/crates/ty_server/README.md#full-diagnostic-output),
while the client-side transformation can be seen in [ty-vscode’s
diagnostic
handling](https://github.com/astral-sh/ty-vscode/blob/48fa1b6567b2deaf923f5724a9d58a6bea2266eb/src/common/diagnostics.ts#L139-L172).

rust-analyzer uses essentially the same client-side design. Its VS Code
extension reads a compiler rendering from `Diagnostic.data.rendered`,
changes the diagnostic code into a link, and opens the report through a
custom URI. The implementation is in [rust-analyzer’s VS Code
client](https://github.com/rust-lang/rust-analyzer/blob/master/editors/code/src/client.ts),
and the protocol is described under [Colored Diagnostic
Output](https://rust-analyzer.github.io/book/contributing/lsp-extensions.html#colored-diagnostic-output).
One distinction is that rust-analyzer receives these reports from rustc
through check-on-save and can request ANSI styling, whereas ty renders
its own diagnostics and the current MVP emits plain text.

Pyrefly’s Markdown diagnostic-message support has a different purpose.
Rather than providing a second, expanded representation, it changes the
content type of the existing `Diagnostic.message`. When the client
advertises `textDocument.diagnostic.markupMessageSupport`, Pyrefly sends
the message as:

    {
        "kind": "markdown",
        "value": "..."
    }

This uses the proposed LSP 3.18 extension that permits
`Diagnostic.message` to contain `MarkupContent`. A compatible client can
render the Markdown directly in its ordinary diagnostic UI without any
Pyrefly-specific virtual-document provider. Clients that do not
advertise support continue receiving a standard string.

Pyrefly currently uses this mechanism primarily to render
backtick-delimited identifiers and types as inline

</details>

## Implementation details

We keep the identifier in `Diagnostic.data` because clients may replace
`Diagnostic.code` with a link to the rendered report. We teach code
actions to recover the identifier and optional fix from
`Diagnostic.data` so replacing the visible diagnostic code with a link
does not disable lazy or eager quick fixes.

Rendered reports embed source snippets whereas raw diagnostics do not.
We therefore include the source text of every file referenced by
diagnostic annotations in pull-diagnostic result IDs for opted-in
clients, deduplicating files before hashing. This conservatively
invalidates cached reports after source-only edits without rendering
every diagnostic merely to compute cache keys. To preserve existing
behavior, we continue to omit result IDs from empty workspace reports.

In [the same way that rust-analyzer
does](https://rust-analyzer.github.io/book/contributing/lsp-extensions.html#colored-diagnostic-output)
(source code
[here](https://github.com/rust-lang/rust-analyzer/blob/master/docs/book/src/contributing/lsp-extensions.md#colored-diagnostic-output)),
we document the experimental protocol explicitly, describing how clients
can declare support for it.

## Test Plan

Tests have been added covering push and pull output, source-sensitive
cache invalidation, and code actions after the visible diagnostic code
has been replaced with a link.

And here is a manual test:


https://github.com/user-attachments/assets/ed65ade1-a111-49be-b8a1-ce357286f33e

To reproduce the above manual test, clone
https://github.com/AlexWaygood/ty-full-diagnostic-demo and follow the
instructions in that repo's README.md.
@AlexWaygood
AlexWaygood merged commit 4c683ee into main Jun 25, 2026
3 checks passed
@AlexWaygood
AlexWaygood deleted the alex/full-compiler-diagnostic branch June 25, 2026 16:08
AlexWaygood added a commit to astral-sh/ty that referenced this pull request Jun 25, 2026
…Protocol (#3855)

## Summary

This documents the experimental LSP extension added in
astral-sh/ruff#26269 /
astral-sh/ty-vscode#462
AlexWaygood added a commit that referenced this pull request Jun 26, 2026
## Context

This builds on the original **Click for full diagnostic** feature
implemented in
[astral-sh/ruff#26269](astral-sh/ruff#26269) and
[#462](#462).
The colored rendering follows the approach established by
[rust-lang/rust-analyzer#13848](rust-lang/rust-analyzer#13848).

## Summary

- advertise support for colored full diagnostic output
- strip ANSI sequences from the virtual document and recreate their
styles with VS Code decorations
- support named terminal colors, 256-color palette entries, truecolor,
and text decorations

## Companion PRs

- [astral-sh/ruff#26384](astral-sh/ruff#26384)
- [astral-sh/ty#3858](astral-sh/ty#3858)

## Test plan



https://github.com/user-attachments/assets/36638263-fe48-4ba7-8abe-95db353f1257
AlexWaygood added a commit to astral-sh/ty that referenced this pull request Jun 26, 2026
## Context

This builds on the original **Click for full diagnostic** feature
implemented in
[astral-sh/ruff#26269](astral-sh/ruff#26269) and
[astral-sh/ty-vscode#462](astral-sh/ty-vscode#462).
The colored rendering follows the approach established by
[rust-lang/rust-analyzer#13848](rust-lang/rust-analyzer#13848).

## Summary

Explain that `fullDiagnosticOutput` can include ANSI colour codes and
clients are expected to be able to handle this

## Companion PRs

- [astral-sh/ruff#26384](astral-sh/ruff#26384)
-
[astral-sh/ty-vscode#463](astral-sh/ty-vscode#463)
AlexWaygood added a commit to astral-sh/ruff that referenced this pull request Jun 26, 2026
## Context

This builds on the original **Click for full diagnostic** feature
implemented in
[#26269](#26269) and
[astral-sh/ty-vscode#462](astral-sh/ty-vscode#462).
The colored rendering follows the approach established by
[rust-lang/rust-analyzer#13848](rust-lang/rust-analyzer#13848).

## Summary

- render full ty diagnostics with ANSI color and styling when the client
opts in
- negotiate color support separately from `fullDiagnosticOutput` for
rollout compatibility
- disable terminal hyperlinks in LSP output and cover the behavior under
forced hyperlink support

## Companion PRs

-
[astral-sh/ty-vscode#463](astral-sh/ty-vscode#463)
- [astral-sh/ty#3858](astral-sh/ty#3858)

## Test plan



https://github.com/user-attachments/assets/dc7e7538-ae2b-4870-9e9b-f59943ee804a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.