Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lsp: Implement support for the textDocument/diagnostic command #19230

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

vitallium
Copy link
Contributor

@vitallium vitallium commented Oct 15, 2024

Closes #13107

Release Notes:

  • Added support for the LSP textDocument/diagnostic command.

Brief

This is draft PR that implements the LSP textDocument/diagnostic command. The goal is to receive your feedback and establish further steps towards fully implementing this command. I tried to re-use existing method and structures to ensure:

  1. The existing functionality works as before
  2. There is no interference between the diagnostics sent by a server and the diagnostics requested by a client.

The current implementation is done via a new LSP command GetDocumentDiagnostics that is sent when a buffer is saved and when a buffer is edited. There is a new method called pull_diagnostic that is called for such events. It has debounce to ensure we don't spam a server with commands every time the buffer is edited. Probably, we don't need the debounce when the buffer is saved.

All in all, the goal is basically to get your feedback and ensure I am on the right track. Thanks!

TODO

  • Support for related documents diagnostics.
  • Support for re-using previous results. The spec describes that as storing and sending a token between LSP commands.

References

  1. https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics

In action

You can clone any Ruby repo since the ruby-lsp supports the pull diagnostics only.

Steps to reproduce:

  1. Clone this repo https://github.com/vitallium/stimulus-lsp-error-zed
  2. Install Ruby (via asdf or `mise).
  3. Install Ruby gems via bundle install
  4. Install Ruby LSP with gem install ruby-lsp
  5. Check out this PR and build Zed
  6. Open any file and start editing to see diagnostics in realtime.
CleanShot.2024-10-13.at.13.27.22.mp4

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Oct 15, 2024
@@ -201,6 +201,7 @@ pub struct CachedLspAdapter {
pub name: LanguageServerName,
pub disk_based_diagnostic_sources: Vec<String>,
pub disk_based_diagnostics_progress_token: Option<String>,
pub previous_document_diagnostic_result_id: Option<String>,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Still not sure about the place to store this token that Zed should store and use between sending/receiving textDocument/diagnostic commands.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved the previous_document_diagnostic_result_id to LanguageServerState enum. Let me know if that's ok.

@vitallium
Copy link
Contributor Author

Whoops, conflicts. I will resolve them in a bit.

@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch from 2180cc7 to 04e102e Compare October 15, 2024 16:21
@vitallium
Copy link
Contributor Author

Whoops, conflicts. I will resolve them in a bit.

Done.

@zed-industries-bot
Copy link

zed-industries-bot commented Oct 15, 2024

Messages
📖

This PR includes links to the following GitHub Issues: #13107
If this PR aims to close an issue, please include a Closes #ISSUE line at the top of the PR body.

Generated by 🚫 dangerJS against 9e79ecd

@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch 2 times, most recently from 5f35960 to 2e2e437 Compare October 15, 2024 21:12
@vitallium vitallium marked this pull request as ready for review October 15, 2024 21:12
@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch 3 times, most recently from 0e98542 to 3ab5b2c Compare October 17, 2024 19:26
@vitallium
Copy link
Contributor Author

Ok, this is ready for the first round of review. Thanks!

@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch from 5c1e305 to 2d3d38c Compare October 18, 2024 18:40
osiewicz pushed a commit that referenced this pull request Oct 18, 2024
Hi. While working on #19230 I
noticed that some servers send a request to unregistered the
`textDocument/rename` capability. I thought it would be good to handle
that message in Zed:

```plaintext
[2024-10-18T21:25:07+02:00 WARN  project::lsp_store] unhandled capability unregistration: Unregistration { id: "biome_rename", method: "textDocument/rename" }
```

So this pull request implements that. Thanks.

Release Notes:

- N/A
noaccOS pushed a commit to noaccOS/zed that referenced this pull request Oct 19, 2024
…ndustries#19427)

Hi. While working on zed-industries#19230 I
noticed that some servers send a request to unregistered the
`textDocument/rename` capability. I thought it would be good to handle
that message in Zed:

```plaintext
[2024-10-18T21:25:07+02:00 WARN  project::lsp_store] unhandled capability unregistration: Unregistration { id: "biome_rename", method: "textDocument/rename" }
```

So this pull request implements that. Thanks.

Release Notes:

- N/A
@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch from 2d3d38c to 4e6c9fd Compare October 21, 2024 17:28
@vitallium
Copy link
Contributor Author

Resolved merge conflicts.

@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch from 4e6c9fd to b7b3be1 Compare October 23, 2024 04:41
Copy link
Contributor

@SomeoneToIgnore SomeoneToIgnore left a comment

Choose a reason for hiding this comment

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

One thing I do not understand is how both diagnostics pull and diagnostics push models are supposed to live together.

  • For instance, rust-analyzer has its own diagnostics, fast to update, and the cargo check-based ones, which may take seconds to update on large projects.
    If we start to wait for all diagnostics or nothing, it might get slower — right now it's ok, as r-a pushes slow and fast ones separately.
    How does this feature work on Zed?

  • How should the LSP server and the client agree what to use?
    It seems, that the push method is the default, and pull is an opt-in one, that will be used right after we declare this new capability?

  • Is it ok to handle both push and pull at the same time, as we do now?
    We have to include potential refresh requests that we either have to support (as declared currently in the capabilities) or declare incapable.

crates/lsp/src/lsp.rs Show resolved Hide resolved
crates/lsp/src/lsp.rs Show resolved Hide resolved
crates/lsp/src/lsp.rs Outdated Show resolved Hide resolved
crates/project/src/lsp_command.rs Show resolved Hide resolved
crates/project/src/lsp_command.rs Outdated Show resolved Hide resolved
crates/project/src/lsp_store.rs Outdated Show resolved Hide resolved
crates/project/src/lsp_store.rs Outdated Show resolved Hide resolved
crates/project/src/lsp_store.rs Outdated Show resolved Hide resolved
crates/project/src/lsp_store.rs Outdated Show resolved Hide resolved
crates/project/src/lsp_store.rs Outdated Show resolved Hide resolved
@SomeoneToIgnore SomeoneToIgnore self-assigned this Oct 23, 2024
@vitallium
Copy link
Contributor Author

@SomeoneToIgnore Thanks for this amazing review! This is what I've been waiting for. I will start working on your comments and answering your questions about handling both push and pull models for diagnostics. Do you want me to convert this PR to draft to mark it as non-ready?

@SomeoneToIgnore SomeoneToIgnore marked this pull request as draft October 23, 2024 11:07
@vitallium
Copy link
Contributor Author

Small update: I am still working on it. I was OOO last week.

@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch 2 times, most recently from 5b9ee27 to 9de1d98 Compare December 4, 2024 16:52
@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch from 9de1d98 to 9ddc70c Compare December 7, 2024 20:51
@vitallium
Copy link
Contributor Author

There have been a lot of changes recently in the related crates. I will double-check all the changes here. Also, I may need to review the implementation approach in this commit

The reason why I went this way is that the LspStore::update_diagnostics function accepts lsp::PublishDiagnosticsParams as one of its parameters. Diagnostics pulled via textDocument/diagnostic are not fully compatible with PublishDiagnosticsParams; for instance, there is no uri: Url field. So, I have had to introduce separate structs for pulled diagnostics.

@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch 4 times, most recently from e7fe69e to fa673d1 Compare December 15, 2024 10:55
@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch 4 times, most recently from 93c99eb to 7bfaf2d Compare December 25, 2024 20:22
Comment on lines +1163 to +1168
} else if let project::Event::LanguageServerAdded(_, _, _) = event {
editor.tasks_pull_diagnostics_task = Some(editor.refresh_diagnostics(cx));
} else if let project::Event::LanguageServerRemoved(_) = event {
editor.tasks_pull_diagnostics_task = Some(editor.refresh_diagnostics(cx));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Question: Not sure if triggering the task for pulling diagnostics here is the correct approach. My thinking is with the MultiLspQuery we want to pull new diagnostics sostics every time new LSP is added or removed.

@vitallium
Copy link
Contributor Author

vitallium commented Dec 26, 2024

@SomeoneToIgnore Hi! Can you please do a smoke check of this PR? Just to guide me if I am moving towards the right direction with the task-based approach and additional protobuf messages. The latter is the major question to me since I have had to do it to properly pass LSP diagnostics between Zed and LSPs. The main difference is the structure of push-based and pull-based diagnostics is different. Thanks for the suggestion about using MultiLspQuery, the implementation looks way better than before. I use Ruby LSP for testing because this is the only server with pull-based diagnostics that I can use currently. I know that rust-analyzer also supports it but I wasn't able to enable them.

For instance, rust-analyzer has its own diagnostics, fast to update, and the cargo check-based ones, which may take seconds to update on large projects.
If we start to wait for all diagnostics or nothing, it might get slower — right now it's ok, as r-a pushes slow and fast ones separately.
How does this feature work on Zed?
How should the LSP server and the client agree what to use?
It seems, that the push method is the default, and pull is an opt-in one, that will be used right after we declare this new capability?

AFAIU, it depends on the LSP. I wonder if it makes sense to provide a configuration option in Zed to switch between push and pull-based models?

Is it ok to handle both push and pull at the same time, as we do now?
We have to include potential refresh requests that we either have to support (as declared currently in the capabilities) or declare incapable.

I think it is, but I am not sure. In my tests, I used Ruby LSP with pull-based diagnostics and rubocop with push-based diagnostics and I didn't notice problems with mixing two modes. I will double-check that.

Thanks again!

@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch from 7bfaf2d to 26f6751 Compare December 26, 2024 10:25
@SomeoneToIgnore
Copy link
Contributor

Thank you for working on this.
I'll be able to look at this somewhere after 9th of Jan.

@vitallium vitallium force-pushed the vs/lsp-pull-diagnostic-support-with-lsp-command branch from 26f6751 to 9e79ecd Compare December 31, 2024 06:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla-signed The user has signed the Contributor License Agreement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support textDocument/diagnostic
3 participants