Shuffle some things around

This commit is contained in:
Lukas Wirth 2023-05-26 15:09:19 +02:00
parent e963846656
commit 79fe11ced3
2 changed files with 91 additions and 74 deletions

View file

@ -52,24 +52,31 @@ pub(crate) type ReqQueue = lsp_server::ReqQueue<(String, Instant), ReqHandler>;
pub(crate) struct GlobalState { pub(crate) struct GlobalState {
sender: Sender<lsp_server::Message>, sender: Sender<lsp_server::Message>,
req_queue: ReqQueue, req_queue: ReqQueue,
pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>, pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>,
pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>,
pub(crate) config: Arc<Config>, pub(crate) config: Arc<Config>,
pub(crate) analysis_host: AnalysisHost, pub(crate) analysis_host: AnalysisHost,
pub(crate) diagnostics: DiagnosticCollection, pub(crate) diagnostics: DiagnosticCollection,
pub(crate) mem_docs: MemDocs, pub(crate) mem_docs: MemDocs,
pub(crate) source_root_config: SourceRootConfig,
pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>,
// status
pub(crate) shutdown_requested: bool, pub(crate) shutdown_requested: bool,
pub(crate) last_reported_status: Option<lsp_ext::ServerStatusParams>, pub(crate) last_reported_status: Option<lsp_ext::ServerStatusParams>,
pub(crate) source_root_config: SourceRootConfig,
// proc macros
pub(crate) proc_macro_changed: bool, pub(crate) proc_macro_changed: bool,
pub(crate) proc_macro_clients: Arc<[anyhow::Result<ProcMacroServer>]>, pub(crate) proc_macro_clients: Arc<[anyhow::Result<ProcMacroServer>]>,
// Flycheck
pub(crate) flycheck: Arc<[FlycheckHandle]>, pub(crate) flycheck: Arc<[FlycheckHandle]>,
pub(crate) flycheck_sender: Sender<flycheck::Message>, pub(crate) flycheck_sender: Sender<flycheck::Message>,
pub(crate) flycheck_receiver: Receiver<flycheck::Message>, pub(crate) flycheck_receiver: Receiver<flycheck::Message>,
// VFS
pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>,
pub(crate) vfs: Arc<RwLock<(vfs::Vfs, IntMap<FileId, LineEndings>)>>, pub(crate) vfs: Arc<RwLock<(vfs::Vfs, IntMap<FileId, LineEndings>)>>,
pub(crate) vfs_config_version: u32, pub(crate) vfs_config_version: u32,
pub(crate) vfs_progress_config_version: u32, pub(crate) vfs_progress_config_version: u32,
@ -102,11 +109,12 @@ pub(crate) struct GlobalState {
/// the user just adds comments or whitespace to Cargo.toml, we do not want /// the user just adds comments or whitespace to Cargo.toml, we do not want
/// to invalidate any salsa caches. /// to invalidate any salsa caches.
pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
// op queues
pub(crate) fetch_workspaces_queue: OpQueue<(), Option<Vec<anyhow::Result<ProjectWorkspace>>>>, pub(crate) fetch_workspaces_queue: OpQueue<(), Option<Vec<anyhow::Result<ProjectWorkspace>>>>,
pub(crate) fetch_build_data_queue: pub(crate) fetch_build_data_queue:
OpQueue<(), (Arc<Vec<ProjectWorkspace>>, Vec<anyhow::Result<WorkspaceBuildScripts>>)>, OpQueue<(), (Arc<Vec<ProjectWorkspace>>, Vec<anyhow::Result<WorkspaceBuildScripts>>)>,
pub(crate) fetch_proc_macros_queue: OpQueue<Vec<ProcMacroPaths>, bool>, pub(crate) fetch_proc_macros_queue: OpQueue<Vec<ProcMacroPaths>, bool>,
pub(crate) prime_caches_queue: OpQueue, pub(crate) prime_caches_queue: OpQueue,
} }

View file

@ -77,7 +77,7 @@ pub(crate) enum PrimeCachesProgress {
impl fmt::Debug for Event { impl fmt::Debug for Event {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let debug_verbose_not = |not: &Notification, f: &mut fmt::Formatter<'_>| { let debug_non_verbose = |not: &Notification, f: &mut fmt::Formatter<'_>| {
f.debug_struct("Notification").field("method", &not.method).finish() f.debug_struct("Notification").field("method", &not.method).finish()
}; };
@ -86,7 +86,7 @@ impl fmt::Debug for Event {
if notification_is::<lsp_types::notification::DidOpenTextDocument>(not) if notification_is::<lsp_types::notification::DidOpenTextDocument>(not)
|| notification_is::<lsp_types::notification::DidChangeTextDocument>(not) || notification_is::<lsp_types::notification::DidChangeTextDocument>(not)
{ {
return debug_verbose_not(not, f); return debug_non_verbose(not, f);
} }
} }
Event::Task(Task::Response(resp)) => { Event::Task(Task::Response(resp)) => {
@ -112,6 +112,29 @@ impl GlobalState {
self.update_status_or_notify(); self.update_status_or_notify();
if self.config.did_save_text_document_dynamic_registration() { if self.config.did_save_text_document_dynamic_registration() {
self.register_did_save_capability();
}
self.fetch_workspaces_queue.request_op("startup".to_string(), ());
if let Some((cause, ())) = self.fetch_workspaces_queue.should_start_op() {
self.fetch_workspaces(cause);
}
while let Some(event) = self.next_event(&inbox) {
if matches!(
&event,
Event::Lsp(lsp_server::Message::Notification(Notification { method, .. }))
if method == lsp_types::notification::Exit::METHOD
) {
return Ok(());
}
self.handle_event(event)?;
}
Err("client exited without proper shutdown sequence".into())
}
fn register_did_save_capability(&mut self) {
let save_registration_options = lsp_types::TextDocumentSaveRegistrationOptions { let save_registration_options = lsp_types::TextDocumentSaveRegistrationOptions {
include_text: Some(false), include_text: Some(false),
text_document_registration_options: lsp_types::TextDocumentRegistrationOptions { text_document_registration_options: lsp_types::TextDocumentRegistrationOptions {
@ -146,23 +169,6 @@ impl GlobalState {
); );
} }
self.fetch_workspaces_queue.request_op("startup".to_string(), ());
if let Some((cause, ())) = self.fetch_workspaces_queue.should_start_op() {
self.fetch_workspaces(cause);
}
while let Some(event) = self.next_event(&inbox) {
if let Event::Lsp(lsp_server::Message::Notification(not)) = &event {
if not.method == lsp_types::notification::Exit::METHOD {
return Ok(());
}
}
self.handle_event(event)?
}
Err("client exited without proper shutdown sequence".into())
}
fn next_event(&self, inbox: &Receiver<lsp_server::Message>) -> Option<Event> { fn next_event(&self, inbox: &Receiver<lsp_server::Message>) -> Option<Event> {
select! { select! {
recv(inbox) -> msg => recv(inbox) -> msg =>
@ -184,20 +190,20 @@ impl GlobalState {
// NOTE: don't count blocking select! call as a loop-turn time // NOTE: don't count blocking select! call as a loop-turn time
let _p = profile::span("GlobalState::handle_event"); let _p = profile::span("GlobalState::handle_event");
let event_dbg = format!("{event:?}"); let event_dbg_msg = format!("{event:?}");
tracing::debug!("{:?} handle_event({:?})", loop_start, event); tracing::debug!("{:?} handle_event({})", loop_start, event_dbg_msg);
if tracing::enabled!(tracing::Level::INFO) {
let task_queue_len = self.task_pool.handle.len(); let task_queue_len = self.task_pool.handle.len();
if task_queue_len > 0 { if task_queue_len > 0 {
tracing::info!("task queue len: {}", task_queue_len); tracing::info!("task queue len: {}", task_queue_len);
} }
}
let was_quiescent = self.is_quiescent(); let was_quiescent = self.is_quiescent();
match event { match event {
Event::Lsp(msg) => match msg { Event::Lsp(msg) => match msg {
lsp_server::Message::Request(req) => self.on_new_request(loop_start, req), lsp_server::Message::Request(req) => self.on_new_request(loop_start, req),
lsp_server::Message::Notification(not) => { lsp_server::Message::Notification(not) => self.on_notification(not)?,
self.on_notification(not)?;
}
lsp_server::Message::Response(resp) => self.complete_request(resp), lsp_server::Message::Response(resp) => self.complete_request(resp),
}, },
Event::Task(task) => { Event::Task(task) => {
@ -291,7 +297,8 @@ impl GlobalState {
} }
} }
if !was_quiescent || state_changed { let client_refresh = !was_quiescent || state_changed;
if client_refresh {
// Refresh semantic tokens if the client supports it. // Refresh semantic tokens if the client supports it.
if self.config.semantic_tokens_refresh() { if self.config.semantic_tokens_refresh() {
self.semantic_tokens_cache.lock().clear(); self.semantic_tokens_cache.lock().clear();
@ -309,9 +316,9 @@ impl GlobalState {
} }
} }
if (!was_quiescent || state_changed || memdocs_added_or_removed) let update_diagnostics = (!was_quiescent || state_changed || memdocs_added_or_removed)
&& self.config.publish_diagnostics() && self.config.publish_diagnostics();
{ if update_diagnostics {
self.update_diagnostics() self.update_diagnostics()
} }
} }
@ -371,6 +378,22 @@ impl GlobalState {
} }
if let Some((cause, ())) = self.prime_caches_queue.should_start_op() { if let Some((cause, ())) = self.prime_caches_queue.should_start_op() {
self.prime_caches(cause);
}
self.update_status_or_notify();
let loop_duration = loop_start.elapsed();
if loop_duration > Duration::from_millis(100) && was_quiescent {
tracing::warn!("overly long loop turn took {loop_duration:?}: {event_dbg_msg}");
self.poke_rust_analyzer_developer(format!(
"overly long loop turn took {loop_duration:?}: {event_dbg_msg}"
));
}
Ok(())
}
fn prime_caches(&mut self, cause: String) {
tracing::debug!(%cause, "will prime caches"); tracing::debug!(%cause, "will prime caches");
let num_worker_threads = self.config.prime_caches_num_threads(); let num_worker_threads = self.config.prime_caches_num_threads();
@ -383,26 +406,12 @@ impl GlobalState {
sender.send(Task::PrimeCaches(report)).unwrap(); sender.send(Task::PrimeCaches(report)).unwrap();
}); });
sender sender
.send(Task::PrimeCaches(PrimeCachesProgress::End { .send(Task::PrimeCaches(PrimeCachesProgress::End { cancelled: res.is_err() }))
cancelled: res.is_err(),
}))
.unwrap(); .unwrap();
} }
}); });
} }
self.update_status_or_notify();
let loop_duration = loop_start.elapsed();
if loop_duration > Duration::from_millis(100) && was_quiescent {
tracing::warn!("overly long loop turn took {loop_duration:?}: {event_dbg}");
self.poke_rust_analyzer_developer(format!(
"overly long loop turn took {loop_duration:?}: {event_dbg}"
));
}
Ok(())
}
fn update_status_or_notify(&mut self) { fn update_status_or_notify(&mut self) {
let status = self.current_status(); let status = self.current_status();
if self.last_reported_status.as_ref() != Some(&status) { if self.last_reported_status.as_ref() != Some(&status) {