-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[ty] Initial support for workspace diagnostics #18939
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
Conversation
|
crates/ty_project/src/db.rs
Outdated
| /// Checks all files in the workspace, ignoring open files setting. | ||
| /// | ||
| /// This is used to power the workspace diagnostics capability in the language server. | ||
| pub fn check_all_files(&self) -> Vec<Diagnostic> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd prefer not to introduce this new method and instead:
a) Remove the behavior that open files has today and make check always check all files (the LSP can call check_file if it only wants diagnostics for open files). The downside of this is that we may need another way to surface setting diagnostics
b) Add a CheckMode field
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually thought of changing the current logic something like (b). I don't think we should do (a) as the playground checks only the files that are marked open. The LSP already uses check_file for pull diagnostic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also realised that it's a bit more complicated because of virtual files... we can never discover them by walking the file try. That means we'll need to check the open files when calling check or we'll miss those files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh good point. I think that'll require astral-sh/ty#619 because currently the server uses the check_file method directly but to include the virtual files in the workspace diagnostics, we need to know the set of virtual files that are available. After #619, we can get the open_files set and filter based on virtual path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or, we could just ask the server index to get all the open virtual files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or, we could just ask the server index to get all the open virtual files.
I think that would work for workspace diagnostics but not necessarily how we use open_files in check_file_impl to determine if the file is open.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something else we would have to be careful about when moving it to System is that we can't use it in any salsa query because the result can change from the outside.
CodSpeed WallTime Performance ReportMerging #18939 will not alter performanceComparing Summary
|
c8e8013 to
788f426
Compare
788f426 to
2f806da
Compare
|
4900d71 to
c109086
Compare
BurntSushi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! This looks sensible to me.
| // The server needs to clear the diagnostics regardless of whether the client supports | ||
| // pull diagnostics or not. This is because the client only has the capability to fetch | ||
| // the diagnostics but does not automatically clear them when a document is closed. | ||
| clear_diagnostics(&key, client); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come this doesn't need to be done when in workspace diagnostic mode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because in workspace mode all diagnostics should be visible regardless of whether a document is open or close in an editor. So, we shouldn't clear the diagnostics when a user closes a file in the editor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhhh makes sense of course.
0e72155 to
1252436
Compare
7e52e98 to
5cc62b0
Compare
## Summary This PR adds support for `ty.diagnosticMode` for astral-sh/ruff#18939. ## Test Plan Refer to the test plain in the above PR.
|
This is great. We may want to iterate on how we handle the different check modes in |
Summary
This PR adds initial support for workspace diagnostics in the ty server.
Reference spec: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_diagnostic
This is currently implemented via the pull diagnostics method which was added in the current version (3.17) and the server advertises it via the
diagnosticProvider.workspaceDiagnosticsserver capability.Note: This might be a bit confusing but a workspace diagnostics is not for a single workspace but for all the workspaces that the server handles. These are the ones that the server received during initialization. Currently, the ty server doesn't support multiple workspaces so this capability is also limited to provide diagnostics only for a single workspace (the first one if the client provided multiple).
A new
ty.diagnosticModeserver setting is added which can be eitherworkspace(for workspace diagnostics) oropenFilesOnly(for checking only open files) (default). This is same aspython.analysis.diagnosticModethat Pyright / Pylance utilizes. In the future, we could use the value underpython.*namespace as fallback to improve the experience on user side to avoid setting the value multiple times.Part of: astral-sh/ty#81
Test Plan
This capability was introduced in the current LSP version (~3 years) and the way it's implemented by various clients are a bit different. I've provided notes on what I've noticed and what would need to be done on our side to further improve the experience.
VS Code
VS Code sends the
workspace/diagnosticrequests every ~2 second:I couldn't really find any resource that explains this behavior. But, this does mean that we'd need to implement the caching layer via the previous result ids sooner. This will allow the server to avoid sending all the diagnostics on every request and instead just send a response stating that the diagnostics hasn't changed yet. This could possibly be achieved by using the salsa ID.
If we switch from workspace diagnostics to open-files diagnostics, the server would send the diagnostics only via the
textDocument/diagnosticendpoint. Here, when a document containing the diagnostic is closed, the server would send a publish diagnostics notification with an empty list of diagnostics to clear the diagnostics from that document. The issue is the VS Code doesn't seem to be clearing the diagnostics in this case even though it receives the notification. (I'm going to open an issue on VS Code side for this today.)Screen.Recording.2025-06-27.at.19.50.33.mov
Zed
Zed's implementation works by refreshing the workspace diagnostics whenever the content of the documents are changed. This seems like a very reasonable behavior and I was a bit surprised that VS Code didn't use this heuristic.
Screen.Recording.2025-06-27.at.19.53.27.mov
Neovim
Neovim only recently added support for workspace diagnostics (neovim/neovim#34262, merged ~3 weeks ago) so it's only available on nightly versions.
The initial support is limited and requires fetching the workspace diagnostics manually as demonstrated in the video. It doesn't support refreshing the workspace diagnostics either, so that would need to be done manually as well. I'm assuming that these are just a temporary limitation and will be implemented before the stable release.
Screen.Recording.2025-06-30.at.12.07.38.mov