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

Support textDocument/diagnostic specification (Pull diagnostics) #11315

Open
wants to merge 31 commits into
base: master
Choose a base branch
from

Conversation

SofusA
Copy link

@SofusA SofusA commented Jul 25, 2024

Closes #7757, if workspace diagnostics is not a requirement. I have not yet found a language server which supports this capability.

Handling of response was originally done by @woojiq in #7900. I was not able to include their git history since their branch has been deleted.

Tested with language servers:

  • eslint version 4.10.0
  • roslyn language sever for C# version 4.12.0
  • ruby-lsp

Diagnostics are pulled when a document is changed for each language server with pull diagnostics feature with an async hook after a debounce period.

Diagnostics are also pulled when a document is opened, when changed to buffer and when a language server is successfully initiated. This is done without debounce.

@SofusA SofusA marked this pull request as ready for review August 3, 2024 20:49
rust-toolchain.toml Outdated Show resolved Hide resolved
helix-term/src/commands/lsp.rs Outdated Show resolved Hide resolved
helix-term/src/ui/editor.rs Outdated Show resolved Hide resolved
@the-mikedavis the-mikedavis added the A-language-server Area: Language server client label Aug 4, 2024
@SofusA SofusA force-pushed the pull-diagnostics branch 2 times, most recently from 85600d2 to 29c5318 Compare August 4, 2024 18:37
helix-term/src/handlers/diagnostics.rs Outdated Show resolved Hide resolved
helix-term/src/handlers/diagnostics.rs Outdated Show resolved Hide resolved
@SofusA
Copy link
Author

SofusA commented Aug 12, 2024

Thanks again for the reviews!
I added your comments and did some refactoring. I closed the conversations, i am sorry if it is usually the reviewer who does this.

The request is currently only being send on document changes, which makes a terrible user experience 😄

Is there a way to send this request when a document is opened, or should a workspace diagnostic event be send when the language server (which supports this feature) is started?

Edit: By the way, i am using this branch daily for C# development, since it allows me to use the same language server as the C# vscode extension. So i am keeping the branch up to date with master branch. Let me know if the merge commits is making too much noise.

@SofusA
Copy link
Author

SofusA commented Aug 13, 2024

I did some experiments with this on roslyn language server. It might be that this language server just behaves weird (which it does on other stuff), but sending workspace/diagnostic after the server is initiated always resulted in and empty diagnostic list. Also with some seconds delay.

I also noticed that responses can either be a full or an related unchanged document report. At the moment, since we only listening on changes, we only get the full reports. This means that when i eg. rename something, i will not see diagnostics on related documents until i make a change.

I am not sure if the specification suggest to pull diagnostics every time a document is viewed, or if we should pull diagnostics for all open documents on changes to a document.

Edit: Pulling diagnostics for all open documents seems to work fine actually.

@SofusA
Copy link
Author

SofusA commented Aug 17, 2024

Thanks for testing!

Firstly, if you open a file directly using the CLI args, then the diagnostics won't show, and instead you have to close the buffer and re-open via the file picker.

I see the same behaviour with roslyn language server. I think this is because we are requesting diagnostics before the language server is ready. I was hoping that this would be the language servers responsibility. I am not sure what to do about this.
Diagnostics will be requested if you make a change to the document

Secondly, and most noticable I think, if I then close this buffer and try to re-open it again then I get a crash

I fixed this by skipping the diagnostics request if the document id is not in the editor.
I am not sure if this is the best solution.

Edit:

Of note, you do have to be using vscode-langservers-extracted@>=4.9.0 (I'm testing on 4.10.0), as that's when they changed something to stop the LS working originally, and is why I'm trying this.

I am actually (without knowing) been using vscode-eslint-language-server version 4.10.0 on this branch. It is working for me with pull diagnostics. @lizclipse Can you check if it work with my latest changes?

@lizclipse
Copy link
Contributor

It looks like the crash is fixed now, thank you. I'd be curious on why the diagnostic request is trying to happen on a missing document ID (is there a memory leak somewhere?), but a little defensive programming didn't hurt anyone.

I've been testing this PR against v4.10.0 and so far it's been working (unlike the master branch, since eslint needs this now I think), although I am still getting the issue where it doesn't pick up the first open file. With my testing just now, it seems that it also doesn't pick up if you open helix blank and then open a file via the picker, you then have to re-open the file (or make an edit) before it starts showing anything. IMO I think functionally it's fine for this PR, but it may be worth opening an issue afterwards as a follow-up to at least document that this is known dodgey behaviour.

@SofusA
Copy link
Author

SofusA commented Aug 18, 2024

I looked into it, and i am not sending the pull diagnostics request, because of a race between the event, and the launching the language server (and registering capabilities). The event wins 😄
In sequent events (open or edit) the language server will be initiated and capabilities are registered.

I have not found a good solution for this, which i find very annoying.
I have found a somewhat hacky solution, where i dispatch the DocumentDidOpen again after a language sever is initialized.

It looks like the crash is fixed now, thank you. I'd be curious on why the diagnostic request is trying to happen on a missing document ID (is there a memory leak somewhere?), but a little defensive programming didn't hurt anyone.

I am not completely sure why. I think part of it was because i was doing this asynchronous, where i collected all document_ids in a hashset, and then send all notifications after a debounce. I changed this to a synchronous hook instead.

@SofusA SofusA marked this pull request as draft August 19, 2024 05:34
@SofusA SofusA marked this pull request as ready for review August 19, 2024 19:26
@SofusA
Copy link
Author

SofusA commented Aug 19, 2024

I did some experiments with diagnostics refresh, but it does not look like the language servers that I use send this notification. I was hoping this would be sent when the language server is ready to receive pull diagnostic requests.

@SofusA
Copy link
Author

SofusA commented Aug 22, 2024

I started to implement workspace diagnostics, but the language servers that i use don't responds to this request. Eslint returns an error and roslyn returns an empty array. So not much to work with here.

I also think that this will be difficult to get to work in helix, because we would need the diagnostics picker to await the async request before displaying, or we would need a way to refresh diagnostics in the picker when the request has finished.
So i am leaving this feature, at least unless someone can guide me in the right direction.

I got refresh diagnostics working though

jming422 added a commit to jming422/mac-config that referenced this pull request Aug 22, 2024
See helix-editor/helix#11506, until
helix-editor/helix#11315 lands I have to stay on
vscode-langservers-extracted 4.8.0 or older
@ssiltanen
Copy link
Contributor

eslint version 4.10.0
Eslint returns an error

Have you tried building a newer version of Microsoft/vscode-eslint? Since you referred to version 4.10.0, I imagine you are using the build from hrsh7th/vscode-langservers-extracted, which took a non-release commit from main at its build time.

@SofusA
Copy link
Author

SofusA commented Sep 1, 2024

eslint version 4.10.0
Eslint returns an error

Have you tried building a newer version of Microsoft/vscode-eslint? Since you referred to version 4.10.0, I imagine you are using the build from hrsh7th/vscode-langservers-extracted, which took a non-release commit from main at its build time.

No i have only tried vscode-langservers-extracted from nixpkgs.

But this would require some refactoring of the diagnostics picker, and i think it should be in a separate pull request

@the-mikedavis
Copy link
Member

See the symbol picker for an example of a picker that waits on an LSP request. The workspace symbol picker is maybe also a good example but it's a sort of "dynamic picker" that re-requests symbols as you type with follow-up requests to the language server.

helix-lsp/src/lib.rs Outdated Show resolved Hide resolved
helix-view/src/editor.rs Outdated Show resolved Hide resolved
@@ -735,9 +743,11 @@ impl Application {
doc.text(),
language_id,
));

helix_event::dispatch(helix_view::events::DocumentDidOpen { doc });
Copy link
Member

Choose a reason for hiding this comment

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

Ideally we should only be dispatching the internal DocumentDidOpen when we initially open a buffer. Here instead of using DocumentDidOpen we should be able to use pull_diagnostics_for_document

Copy link
Author

Choose a reason for hiding this comment

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

Changed to use pull_diagnostics_for_document directly

helix-term/src/handlers/diagnostics.rs Outdated Show resolved Hide resolved
@SofusA
Copy link
Author

SofusA commented Sep 1, 2024

See the symbol picker for an example of a picker that waits on an LSP request. The workspace symbol picker is maybe also a good example but it's a sort of "dynamic picker" that re-requests symbols as you type with follow-up requests to the language server.

Okay it does not look that difficult. I have however not been able to get response from roslyn language server. I will try again with a newer version of eslint language server next week.

Edit: Okay i gave it a very low effort shot using this fork which has a nix flake i could use.

I looked at the capability responses from the 3 language servers i know of that supports pull diagnostics: ruby-lsp, vscode-eslint´ and Microsoft.CodeAnalysis.LanguageServer(akaroslyn-ls`. Unfortunately only the roslyn language server supports this at the time of writing, and it does not give me a reliable response.

A workaround could be to request diagnostics for all open buffers, for all language servers which support pull diagnostics, before opening workspace diagnostics.
Edit again: I did give this a try and i am not sure if i will be able to get it working. There will be a double for looping which will gives me issues. That would be the case for workspace diagnostics since it is just one request to the server. A better rust developer might be able to pull it off 😄

I suggest to wait for language servers to support this capability, and maybe handle pulling diagnostics for all documents for workspace diagnostics picker in a separate pull request.

@kirawi kirawi added the S-waiting-on-review Status: Awaiting review from a maintainer. label Sep 3, 2024
@archseer archseer added this to the next milestone Sep 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-language-server Area: Language server client S-waiting-on-review Status: Awaiting review from a maintainer.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add pullDiagnostics lsp feature
7 participants