Refresh all possibly stale diagnostics pat
This commit is contained in:
parent
ac9efaebb7
commit
660c3371e4
1 changed files with 81 additions and 53 deletions
|
@ -3,7 +3,7 @@ mod project_diagnostics_settings;
|
||||||
mod toolbar_controls;
|
mod toolbar_controls;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use collections::{BTreeSet, HashSet};
|
use collections::{BTreeSet, HashMap, HashSet};
|
||||||
use editor::{
|
use editor::{
|
||||||
diagnostic_block_renderer,
|
diagnostic_block_renderer,
|
||||||
display_map::{BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock},
|
display_map::{BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock},
|
||||||
|
@ -13,7 +13,7 @@ use editor::{
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, elements::*, fonts::TextStyle, serde_json, AnyViewHandle, AppContext, Entity,
|
actions, elements::*, fonts::TextStyle, serde_json, AnyViewHandle, AppContext, Entity,
|
||||||
ModelHandle, Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use language::{
|
use language::{
|
||||||
Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection,
|
Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection,
|
||||||
|
@ -28,6 +28,7 @@ use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
|
mem,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
@ -61,7 +62,9 @@ struct ProjectDiagnosticsEditor {
|
||||||
excerpts: ModelHandle<MultiBuffer>,
|
excerpts: ModelHandle<MultiBuffer>,
|
||||||
path_states: Vec<PathState>,
|
path_states: Vec<PathState>,
|
||||||
paths_to_update: BTreeSet<(ProjectPath, LanguageServerId)>,
|
paths_to_update: BTreeSet<(ProjectPath, LanguageServerId)>,
|
||||||
|
current_diagnostics: HashMap<LanguageServerId, HashSet<ProjectPath>>,
|
||||||
include_warnings: bool,
|
include_warnings: bool,
|
||||||
|
_subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PathState {
|
struct PathState {
|
||||||
|
@ -149,11 +152,11 @@ impl ProjectDiagnosticsEditor {
|
||||||
workspace: WeakViewHandle<Workspace>,
|
workspace: WeakViewHandle<Workspace>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let project_event_subscription =
|
||||||
cx.subscribe(&project_handle, |this, _, event, cx| match event {
|
cx.subscribe(&project_handle, |this, _, event, cx| match event {
|
||||||
project::Event::DiskBasedDiagnosticsFinished { language_server_id } => {
|
project::Event::DiskBasedDiagnosticsFinished { language_server_id } => {
|
||||||
log::debug!("Disk based diagnostics finished for server {language_server_id}");
|
log::debug!("Disk based diagnostics finished for server {language_server_id}");
|
||||||
this.update_excerpts(Some(*language_server_id), cx);
|
this.update_excerpts(Some(*language_server_id), cx);
|
||||||
this.update_title(cx);
|
|
||||||
}
|
}
|
||||||
project::Event::DiagnosticsUpdated {
|
project::Event::DiagnosticsUpdated {
|
||||||
language_server_id,
|
language_server_id,
|
||||||
|
@ -162,12 +165,9 @@ impl ProjectDiagnosticsEditor {
|
||||||
log::debug!("Adding path {path:?} to update for server {language_server_id}");
|
log::debug!("Adding path {path:?} to update for server {language_server_id}");
|
||||||
this.paths_to_update
|
this.paths_to_update
|
||||||
.insert((path.clone(), *language_server_id));
|
.insert((path.clone(), *language_server_id));
|
||||||
this.update_excerpts(Some(*language_server_id), cx);
|
|
||||||
this.update_title(cx);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
})
|
});
|
||||||
.detach();
|
|
||||||
|
|
||||||
let excerpts = cx.add_model(|cx| MultiBuffer::new(project_handle.read(cx).replica_id()));
|
let excerpts = cx.add_model(|cx| MultiBuffer::new(project_handle.read(cx).replica_id()));
|
||||||
let editor = cx.add_view(|cx| {
|
let editor = cx.add_view(|cx| {
|
||||||
|
@ -176,19 +176,14 @@ impl ProjectDiagnosticsEditor {
|
||||||
editor.set_vertical_scroll_margin(5, cx);
|
editor.set_vertical_scroll_margin(5, cx);
|
||||||
editor
|
editor
|
||||||
});
|
});
|
||||||
cx.subscribe(&editor, |this, _, event, cx| {
|
let editor_event_subscription = cx.subscribe(&editor, |this, _, event, cx| {
|
||||||
cx.emit(event.clone());
|
cx.emit(event.clone());
|
||||||
if event == &editor::Event::Focused && this.path_states.is_empty() {
|
if event == &editor::Event::Focused && this.path_states.is_empty() {
|
||||||
cx.focus_self()
|
cx.focus_self()
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.detach();
|
|
||||||
|
|
||||||
let project = project_handle.read(cx);
|
let project = project_handle.read(cx);
|
||||||
let paths_to_update = project
|
|
||||||
.diagnostic_summaries(cx)
|
|
||||||
.map(|(path, server_id, _)| (path, server_id))
|
|
||||||
.collect();
|
|
||||||
let summary = project.diagnostic_summary(cx);
|
let summary = project.diagnostic_summary(cx);
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
project: project_handle,
|
project: project_handle,
|
||||||
|
@ -197,8 +192,10 @@ impl ProjectDiagnosticsEditor {
|
||||||
excerpts,
|
excerpts,
|
||||||
editor,
|
editor,
|
||||||
path_states: Default::default(),
|
path_states: Default::default(),
|
||||||
paths_to_update,
|
paths_to_update: BTreeSet::new(),
|
||||||
include_warnings: settings::get::<ProjectDiagnosticsSettings>(cx).include_warnings,
|
include_warnings: settings::get::<ProjectDiagnosticsSettings>(cx).include_warnings,
|
||||||
|
current_diagnostics: HashMap::default(),
|
||||||
|
_subscriptions: vec![project_event_subscription, editor_event_subscription],
|
||||||
};
|
};
|
||||||
this.update_excerpts(None, cx);
|
this.update_excerpts(None, cx);
|
||||||
this
|
this
|
||||||
|
@ -218,12 +215,6 @@ impl ProjectDiagnosticsEditor {
|
||||||
|
|
||||||
fn toggle_warnings(&mut self, _: &ToggleWarnings, cx: &mut ViewContext<Self>) {
|
fn toggle_warnings(&mut self, _: &ToggleWarnings, cx: &mut ViewContext<Self>) {
|
||||||
self.include_warnings = !self.include_warnings;
|
self.include_warnings = !self.include_warnings;
|
||||||
self.paths_to_update = self
|
|
||||||
.project
|
|
||||||
.read(cx)
|
|
||||||
.diagnostic_summaries(cx)
|
|
||||||
.map(|(path, server_id, _)| (path, server_id))
|
|
||||||
.collect();
|
|
||||||
self.update_excerpts(None, cx);
|
self.update_excerpts(None, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
@ -234,29 +225,71 @@ impl ProjectDiagnosticsEditor {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
log::debug!("Updating excerpts for server {language_server_id:?}");
|
log::debug!("Updating excerpts for server {language_server_id:?}");
|
||||||
let mut paths = Vec::new();
|
let mut paths_to_recheck = HashSet::default();
|
||||||
|
let mut new_summaries: HashMap<LanguageServerId, HashSet<ProjectPath>> = self
|
||||||
|
.project
|
||||||
|
.read(cx)
|
||||||
|
.diagnostic_summaries(cx)
|
||||||
|
.fold(HashMap::default(), |mut summaries, (path, server_id, _)| {
|
||||||
|
summaries.entry(server_id).or_default().insert(path);
|
||||||
|
summaries
|
||||||
|
});
|
||||||
|
let mut old_diagnostics =
|
||||||
|
mem::replace(&mut self.current_diagnostics, new_summaries.clone());
|
||||||
|
if let Some(language_server_id) = language_server_id {
|
||||||
|
new_summaries.retain(|server_id, _| server_id == &language_server_id);
|
||||||
|
old_diagnostics.retain(|server_id, _| server_id == &language_server_id);
|
||||||
self.paths_to_update.retain(|(path, server_id)| {
|
self.paths_to_update.retain(|(path, server_id)| {
|
||||||
if language_server_id
|
if server_id == &language_server_id {
|
||||||
.map_or(true, |language_server_id| language_server_id == *server_id)
|
paths_to_recheck.insert(path.clone());
|
||||||
{
|
|
||||||
paths.push(path.clone());
|
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
paths_to_recheck.extend(
|
||||||
|
mem::replace(&mut self.paths_to_update, BTreeSet::new())
|
||||||
|
.into_iter()
|
||||||
|
.map(|(path, _)| path),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (server_id, new_paths) in new_summaries {
|
||||||
|
match old_diagnostics.remove(&server_id) {
|
||||||
|
Some(mut old_paths) => {
|
||||||
|
paths_to_recheck.extend(
|
||||||
|
new_paths
|
||||||
|
.into_iter()
|
||||||
|
.filter(|new_path| !old_paths.remove(new_path)),
|
||||||
|
);
|
||||||
|
paths_to_recheck.extend(old_paths);
|
||||||
|
}
|
||||||
|
None => paths_to_recheck.extend(new_paths),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paths_to_recheck.extend(old_diagnostics.into_iter().flat_map(|(_, paths)| paths));
|
||||||
|
|
||||||
let project = self.project.clone();
|
let project = self.project.clone();
|
||||||
cx.spawn(|this, mut cx| {
|
cx.spawn(|this, mut cx| {
|
||||||
async move {
|
async move {
|
||||||
for path in paths {
|
let mut changed = false;
|
||||||
|
for path in paths_to_recheck {
|
||||||
let buffer = project
|
let buffer = project
|
||||||
.update(&mut cx, |project, cx| project.open_buffer(path.clone(), cx))
|
.update(&mut cx, |project, cx| project.open_buffer(path.clone(), cx))
|
||||||
.await?;
|
.await?;
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
this.populate_excerpts(path, language_server_id, buffer, cx)
|
this.populate_excerpts(path, language_server_id, buffer, cx);
|
||||||
|
changed = true;
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
Result::<_, anyhow::Error>::Ok(())
|
if changed {
|
||||||
|
this.update(&mut cx, |this, cx| {
|
||||||
|
this.summary = this.project.read(cx).diagnostic_summary(cx);
|
||||||
|
cx.emit(Event::TitleChanged);
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
anyhow::Ok(())
|
||||||
}
|
}
|
||||||
.log_err()
|
.log_err()
|
||||||
})
|
})
|
||||||
|
@ -559,11 +592,6 @@ impl ProjectDiagnosticsEditor {
|
||||||
}
|
}
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_title(&mut self, cx: &mut ViewContext<Self>) {
|
|
||||||
self.summary = self.project.read(cx).diagnostic_summary(cx);
|
|
||||||
cx.emit(Event::TitleChanged);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Item for ProjectDiagnosticsEditor {
|
impl Item for ProjectDiagnosticsEditor {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue