Extract a LanguageServerStatus struct

This commit is contained in:
Antonio Scandurra 2022-03-10 17:04:36 +01:00
parent 45fb470f4d
commit 5157b42896
2 changed files with 106 additions and 50 deletions

View file

@ -51,8 +51,7 @@ pub struct Project {
languages: Arc<LanguageRegistry>, languages: Arc<LanguageRegistry>,
language_servers: HashMap<(WorktreeId, Arc<str>), Arc<LanguageServer>>, language_servers: HashMap<(WorktreeId, Arc<str>), Arc<LanguageServer>>,
started_language_servers: HashMap<(WorktreeId, Arc<str>), Task<Option<Arc<LanguageServer>>>>, started_language_servers: HashMap<(WorktreeId, Arc<str>), Task<Option<Arc<LanguageServer>>>>,
pending_language_server_work: BTreeMap<(usize, String), LanguageServerProgress>, language_server_statuses: BTreeMap<usize, LanguageServerStatus>,
language_server_names: HashMap<usize, String>,
next_language_server_id: usize, next_language_server_id: usize,
client: Arc<client::Client>, client: Arc<client::Client>,
user_store: ModelHandle<UserStore>, user_store: ModelHandle<UserStore>,
@ -131,6 +130,12 @@ enum LanguageServerEvent {
DiagnosticsUpdate(lsp::PublishDiagnosticsParams), DiagnosticsUpdate(lsp::PublishDiagnosticsParams),
} }
pub struct LanguageServerStatus {
pub name: String,
pub pending_work: BTreeMap<String, LanguageServerProgress>,
pending_diagnostic_updates: isize,
}
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct LanguageServerProgress { pub struct LanguageServerProgress {
pub message: Option<String>, pub message: Option<String>,
@ -326,8 +331,7 @@ impl Project {
language_servers_with_diagnostics_running: 0, language_servers_with_diagnostics_running: 0,
language_servers: Default::default(), language_servers: Default::default(),
started_language_servers: Default::default(), started_language_servers: Default::default(),
pending_language_server_work: Default::default(), language_server_statuses: Default::default(),
language_server_names: Default::default(),
next_language_server_id: 0, next_language_server_id: 0,
nonce: StdRng::from_entropy().gen(), nonce: StdRng::from_entropy().gen(),
} }
@ -398,11 +402,19 @@ impl Project {
language_servers_with_diagnostics_running: 0, language_servers_with_diagnostics_running: 0,
language_servers: Default::default(), language_servers: Default::default(),
started_language_servers: Default::default(), started_language_servers: Default::default(),
pending_language_server_work: Default::default(), language_server_statuses: response
language_server_names: response
.language_servers .language_servers
.into_iter() .into_iter()
.map(|s| (s.id as usize, s.name)) .map(|server| {
(
server.id as usize,
LanguageServerStatus {
name: server.name,
pending_work: Default::default(),
pending_diagnostic_updates: 0,
},
)
})
.collect(), .collect(),
next_language_server_id: 0, next_language_server_id: 0,
opened_buffers: Default::default(), opened_buffers: Default::default(),
@ -1274,8 +1286,14 @@ impl Project {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.language_servers this.language_servers
.insert(key.clone(), language_server.clone()); .insert(key.clone(), language_server.clone());
this.language_server_names this.language_server_statuses.insert(
.insert(server_id, language_server.name().to_string()); server_id,
LanguageServerStatus {
name: language_server.name().to_string(),
pending_work: Default::default(),
pending_diagnostic_updates: 0,
},
);
if let Some(project_id) = this.remote_id() { if let Some(project_id) = this.remote_id() {
this.client this.client
@ -1359,16 +1377,26 @@ impl Project {
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) { ) {
let disk_diagnostics_token = language.disk_based_diagnostics_progress_token(); let disk_diagnostics_token = language.disk_based_diagnostics_progress_token();
let language_server_status =
if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
status
} else {
return;
};
match event { match event {
LanguageServerEvent::WorkStart { token } => { LanguageServerEvent::WorkStart { token } => {
if Some(&token) == disk_diagnostics_token { if Some(&token) == disk_diagnostics_token {
self.disk_based_diagnostics_started(cx); language_server_status.pending_diagnostic_updates += 1;
self.broadcast_language_server_update( if language_server_status.pending_diagnostic_updates == 1 {
language_server_id, self.disk_based_diagnostics_started(cx);
proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating( self.broadcast_language_server_update(
proto::LspDiskBasedDiagnosticsUpdating {}, language_server_id,
), proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(
); proto::LspDiskBasedDiagnosticsUpdating {},
),
);
}
} else { } else {
self.on_lsp_work_start(language_server_id, token.clone(), cx); self.on_lsp_work_start(language_server_id, token.clone(), cx);
self.broadcast_language_server_update( self.broadcast_language_server_update(
@ -1401,13 +1429,16 @@ impl Project {
} }
LanguageServerEvent::WorkEnd { token } => { LanguageServerEvent::WorkEnd { token } => {
if Some(&token) == disk_diagnostics_token { if Some(&token) == disk_diagnostics_token {
self.disk_based_diagnostics_finished(cx); language_server_status.pending_diagnostic_updates -= 1;
self.broadcast_language_server_update( if language_server_status.pending_diagnostic_updates == 0 {
language_server_id, self.disk_based_diagnostics_finished(cx);
proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( self.broadcast_language_server_update(
proto::LspDiskBasedDiagnosticsUpdated {}, language_server_id,
), proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
); proto::LspDiskBasedDiagnosticsUpdated {},
),
);
}
} else { } else {
self.on_lsp_work_end(language_server_id, token.clone(), cx); self.on_lsp_work_end(language_server_id, token.clone(), cx);
self.broadcast_language_server_update( self.broadcast_language_server_update(
@ -1457,14 +1488,16 @@ impl Project {
token: String, token: String,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) { ) {
self.pending_language_server_work.insert( if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
(language_server_id, token), status.pending_work.insert(
LanguageServerProgress { token,
message: None, LanguageServerProgress {
percentage: None, message: None,
}, percentage: None,
); },
cx.notify(); );
cx.notify();
}
} }
fn on_lsp_work_progress( fn on_lsp_work_progress(
@ -1474,9 +1507,10 @@ impl Project {
progress: LanguageServerProgress, progress: LanguageServerProgress,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) { ) {
self.pending_language_server_work if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
.insert((language_server_id, token), progress); status.pending_work.insert(token, progress);
cx.notify(); cx.notify();
}
} }
fn on_lsp_work_end( fn on_lsp_work_end(
@ -1485,9 +1519,10 @@ impl Project {
token: String, token: String,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) { ) {
self.pending_language_server_work if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
.remove(&(language_server_id, token)); status.pending_work.remove(&token);
cx.notify(); cx.notify();
}
} }
fn broadcast_language_server_update( fn broadcast_language_server_update(
@ -1506,15 +1541,8 @@ impl Project {
} }
} }
pub fn pending_language_server_work( pub fn language_server_statuses(&self) -> impl Iterator<Item = &LanguageServerStatus> {
&self, self.language_server_statuses.values()
) -> impl Iterator<Item = (&str, &str, &LanguageServerProgress)> {
self.pending_language_server_work.iter().filter_map(
|((language_server_id, token), progress)| {
let name = self.language_server_names.get(language_server_id)?;
Some((name.as_str(), token.as_str(), progress))
},
)
} }
pub fn update_diagnostics( pub fn update_diagnostics(
@ -3266,8 +3294,14 @@ impl Project {
.server .server
.ok_or_else(|| anyhow!("invalid server"))?; .ok_or_else(|| anyhow!("invalid server"))?;
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.language_server_names this.language_server_statuses.insert(
.insert(server.id as usize, server.name); server.id as usize,
LanguageServerStatus {
name: server.name,
pending_work: Default::default(),
pending_diagnostic_updates: 0,
},
);
cx.notify(); cx.notify();
}); });
Ok(()) Ok(())

View file

@ -1,12 +1,13 @@
use crate::{ItemViewHandle, Settings, StatusItemView}; use crate::{ItemViewHandle, Settings, StatusItemView};
use futures::StreamExt; use futures::StreamExt;
use gpui::AppContext;
use gpui::{ use gpui::{
action, elements::*, platform::CursorStyle, Entity, ModelHandle, MutableAppContext, action, elements::*, platform::CursorStyle, Entity, ModelHandle, MutableAppContext,
RenderContext, View, ViewContext, RenderContext, View, ViewContext,
}; };
use language::{LanguageRegistry, LanguageServerBinaryStatus}; use language::{LanguageRegistry, LanguageServerBinaryStatus};
use postage::watch; use postage::watch;
use project::Project; use project::{LanguageServerProgress, Project};
use std::fmt::Write; use std::fmt::Write;
use std::sync::Arc; use std::sync::Arc;
@ -81,6 +82,27 @@ impl LspStatus {
self.failed.clear(); self.failed.clear();
cx.notify(); cx.notify();
} }
fn pending_language_server_work<'a>(
&self,
cx: &'a AppContext,
) -> impl Iterator<Item = (&'a str, &'a str, &'a LanguageServerProgress)> {
self.project
.read(cx)
.language_server_statuses()
.filter_map(|status| {
if status.pending_work.is_empty() {
None
} else {
Some(
status.pending_work.iter().map(|(token, progress)| {
(status.name.as_str(), token.as_str(), progress)
}),
)
}
})
.flatten()
}
} }
impl Entity for LspStatus { impl Entity for LspStatus {
@ -95,7 +117,7 @@ impl View for LspStatus {
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
let theme = &self.settings_rx.borrow().theme; let theme = &self.settings_rx.borrow().theme;
let mut pending_work = self.project.read(cx).pending_language_server_work(); let mut pending_work = self.pending_language_server_work(cx);
if let Some((lang_server_name, progress_token, progress)) = pending_work.next() { if let Some((lang_server_name, progress_token, progress)) = pending_work.next() {
let mut message = lang_server_name.to_string(); let mut message = lang_server_name.to_string();