Implement the rest of the worktree pulls (#32269)
Follow-up of https://github.com/zed-industries/zed/pull/19230 Implements the workspace diagnostics pulling, and replaces "pull diagnostics every open editors' buffer" strategy with "pull changed buffer's diagnostics" + "schedule workspace diagnostics pull" for the rest of the diagnostics. This means that if the server does not support the workspace diagnostics and does not return more in linked files, only the currently edited buffer has its diagnostics updated. This is better than the existing implementation that causes a lot of diagnostics pulls to be done instead, and we can add more heuristics on top later for querying more diagnostics. Release Notes: - N/A
This commit is contained in:
parent
9e5f89dc26
commit
77ead25f8c
8 changed files with 429 additions and 85 deletions
|
@ -1699,10 +1699,7 @@ impl Editor {
|
|||
editor.tasks_update_task =
|
||||
Some(editor.refresh_runnables(window, cx));
|
||||
}
|
||||
editor.pull_diagnostics(window, cx);
|
||||
}
|
||||
project::Event::PullWorkspaceDiagnostics => {
|
||||
editor.pull_diagnostics(window, cx);
|
||||
editor.pull_diagnostics(None, window, cx);
|
||||
}
|
||||
project::Event::SnippetEdit(id, snippet_edits) => {
|
||||
if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
|
||||
|
@ -2105,7 +2102,7 @@ impl Editor {
|
|||
|
||||
editor.minimap =
|
||||
editor.create_minimap(EditorSettings::get_global(cx).minimap, window, cx);
|
||||
editor.pull_diagnostics(window, cx);
|
||||
editor.pull_diagnostics(None, window, cx);
|
||||
}
|
||||
|
||||
editor.report_editor_event("Editor Opened", None, cx);
|
||||
|
@ -15974,7 +15971,12 @@ impl Editor {
|
|||
});
|
||||
}
|
||||
|
||||
fn pull_diagnostics(&mut self, window: &Window, cx: &mut Context<Self>) -> Option<()> {
|
||||
fn pull_diagnostics(
|
||||
&mut self,
|
||||
buffer_id: Option<BufferId>,
|
||||
window: &Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<()> {
|
||||
let project = self.project.as_ref()?.downgrade();
|
||||
let pull_diagnostics_settings = ProjectSettings::get_global(cx)
|
||||
.diagnostics
|
||||
|
@ -15983,7 +15985,10 @@ impl Editor {
|
|||
return None;
|
||||
}
|
||||
let debounce = Duration::from_millis(pull_diagnostics_settings.debounce_ms);
|
||||
let buffers = self.buffer.read(cx).all_buffers();
|
||||
let mut buffers = self.buffer.read(cx).all_buffers();
|
||||
if let Some(buffer_id) = buffer_id {
|
||||
buffers.retain(|buffer| buffer.read(cx).remote_id() == buffer_id);
|
||||
}
|
||||
|
||||
self.pull_diagnostics_task = cx.spawn_in(window, async move |editor, cx| {
|
||||
cx.background_executor().timer(debounce).await;
|
||||
|
@ -18744,27 +18749,23 @@ impl Editor {
|
|||
self.update_visible_inline_completion(window, cx);
|
||||
}
|
||||
if let Some(project) = self.project.as_ref() {
|
||||
project.update(cx, |project, cx| {
|
||||
if edited_buffer
|
||||
.as_ref()
|
||||
.is_some_and(|buffer| buffer.read(cx).file().is_some())
|
||||
{
|
||||
// Diagnostics are not local: an edit within one file (`pub mod foo()` -> `pub mod bar()`), may cause errors in another files with `foo()`.
|
||||
// Hence, emit a project-wide event to pull for every buffer's diagnostics that has an open editor.
|
||||
// TODO: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnostic_refresh explains the flow how
|
||||
// diagnostics should be pulled: instead of pulling every open editor's buffer's diagnostics (which happens effectively due to emitting this event),
|
||||
// we should only pull for the current buffer's diagnostics and get the rest via the workspace diagnostics LSP request — this is not implemented yet.
|
||||
cx.emit(project::Event::PullWorkspaceDiagnostics);
|
||||
}
|
||||
|
||||
if let Some(buffer) = edited_buffer {
|
||||
if let Some(edited_buffer) = edited_buffer {
|
||||
project.update(cx, |project, cx| {
|
||||
self.registered_buffers
|
||||
.entry(buffer.read(cx).remote_id())
|
||||
.entry(edited_buffer.read(cx).remote_id())
|
||||
.or_insert_with(|| {
|
||||
project.register_buffer_with_language_servers(&buffer, cx)
|
||||
project
|
||||
.register_buffer_with_language_servers(&edited_buffer, cx)
|
||||
});
|
||||
});
|
||||
if edited_buffer.read(cx).file().is_some() {
|
||||
self.pull_diagnostics(
|
||||
Some(edited_buffer.read(cx).remote_id()),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
cx.emit(EditorEvent::BufferEdited);
|
||||
cx.emit(SearchEvent::MatchesInvalidated);
|
||||
|
|
|
@ -21933,14 +21933,16 @@ async fn test_pulling_diagnostics(cx: &mut TestAppContext) {
|
|||
});
|
||||
|
||||
let ensure_result_id = |expected: Option<String>, cx: &mut TestAppContext| {
|
||||
editor.update(cx, |editor, cx| {
|
||||
let buffer_result_id = editor
|
||||
project.update(cx, |project, cx| {
|
||||
let buffer_id = editor
|
||||
.read(cx)
|
||||
.buffer()
|
||||
.read(cx)
|
||||
.as_singleton()
|
||||
.expect("created a singleton buffer")
|
||||
.read(cx)
|
||||
.result_id();
|
||||
.remote_id();
|
||||
let buffer_result_id = project.lsp_store().read(cx).result_id(buffer_id);
|
||||
assert_eq!(expected, buffer_result_id);
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue