mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
Shuffle some things around
This commit is contained in:
parent
e963846656
commit
79fe11ced3
2 changed files with 91 additions and 74 deletions
|
@ -52,24 +52,31 @@ pub(crate) type ReqQueue = lsp_server::ReqQueue<(String, Instant), ReqHandler>;
|
|||
pub(crate) struct GlobalState {
|
||||
sender: Sender<lsp_server::Message>,
|
||||
req_queue: ReqQueue,
|
||||
|
||||
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) analysis_host: AnalysisHost,
|
||||
pub(crate) diagnostics: DiagnosticCollection,
|
||||
pub(crate) mem_docs: MemDocs,
|
||||
pub(crate) source_root_config: SourceRootConfig,
|
||||
pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>,
|
||||
|
||||
// status
|
||||
pub(crate) shutdown_requested: bool,
|
||||
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_clients: Arc<[anyhow::Result<ProcMacroServer>]>,
|
||||
|
||||
// Flycheck
|
||||
pub(crate) flycheck: Arc<[FlycheckHandle]>,
|
||||
pub(crate) flycheck_sender: Sender<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_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
|
||||
/// to invalidate any salsa caches.
|
||||
pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
|
||||
|
||||
// op queues
|
||||
pub(crate) fetch_workspaces_queue: OpQueue<(), Option<Vec<anyhow::Result<ProjectWorkspace>>>>,
|
||||
pub(crate) fetch_build_data_queue:
|
||||
OpQueue<(), (Arc<Vec<ProjectWorkspace>>, Vec<anyhow::Result<WorkspaceBuildScripts>>)>,
|
||||
pub(crate) fetch_proc_macros_queue: OpQueue<Vec<ProcMacroPaths>, bool>,
|
||||
|
||||
pub(crate) prime_caches_queue: OpQueue,
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ pub(crate) enum PrimeCachesProgress {
|
|||
|
||||
impl fmt::Debug for Event {
|
||||
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", ¬.method).finish()
|
||||
};
|
||||
|
||||
|
@ -86,7 +86,7 @@ impl fmt::Debug for Event {
|
|||
if notification_is::<lsp_types::notification::DidOpenTextDocument>(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)) => {
|
||||
|
@ -112,38 +112,7 @@ impl GlobalState {
|
|||
self.update_status_or_notify();
|
||||
|
||||
if self.config.did_save_text_document_dynamic_registration() {
|
||||
let save_registration_options = lsp_types::TextDocumentSaveRegistrationOptions {
|
||||
include_text: Some(false),
|
||||
text_document_registration_options: lsp_types::TextDocumentRegistrationOptions {
|
||||
document_selector: Some(vec![
|
||||
lsp_types::DocumentFilter {
|
||||
language: None,
|
||||
scheme: None,
|
||||
pattern: Some("**/*.rs".into()),
|
||||
},
|
||||
lsp_types::DocumentFilter {
|
||||
language: None,
|
||||
scheme: None,
|
||||
pattern: Some("**/Cargo.toml".into()),
|
||||
},
|
||||
lsp_types::DocumentFilter {
|
||||
language: None,
|
||||
scheme: None,
|
||||
pattern: Some("**/Cargo.lock".into()),
|
||||
},
|
||||
]),
|
||||
},
|
||||
};
|
||||
|
||||
let registration = lsp_types::Registration {
|
||||
id: "textDocument/didSave".to_string(),
|
||||
method: "textDocument/didSave".to_string(),
|
||||
register_options: Some(serde_json::to_value(save_registration_options).unwrap()),
|
||||
};
|
||||
self.send_request::<lsp_types::request::RegisterCapability>(
|
||||
lsp_types::RegistrationParams { registrations: vec![registration] },
|
||||
|_, _| (),
|
||||
);
|
||||
self.register_did_save_capability();
|
||||
}
|
||||
|
||||
self.fetch_workspaces_queue.request_op("startup".to_string(), ());
|
||||
|
@ -152,17 +121,54 @@ impl GlobalState {
|
|||
}
|
||||
|
||||
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(());
|
||||
}
|
||||
if matches!(
|
||||
&event,
|
||||
Event::Lsp(lsp_server::Message::Notification(Notification { method, .. }))
|
||||
if method == lsp_types::notification::Exit::METHOD
|
||||
) {
|
||||
return Ok(());
|
||||
}
|
||||
self.handle_event(event)?
|
||||
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 {
|
||||
include_text: Some(false),
|
||||
text_document_registration_options: lsp_types::TextDocumentRegistrationOptions {
|
||||
document_selector: Some(vec![
|
||||
lsp_types::DocumentFilter {
|
||||
language: None,
|
||||
scheme: None,
|
||||
pattern: Some("**/*.rs".into()),
|
||||
},
|
||||
lsp_types::DocumentFilter {
|
||||
language: None,
|
||||
scheme: None,
|
||||
pattern: Some("**/Cargo.toml".into()),
|
||||
},
|
||||
lsp_types::DocumentFilter {
|
||||
language: None,
|
||||
scheme: None,
|
||||
pattern: Some("**/Cargo.lock".into()),
|
||||
},
|
||||
]),
|
||||
},
|
||||
};
|
||||
|
||||
let registration = lsp_types::Registration {
|
||||
id: "textDocument/didSave".to_string(),
|
||||
method: "textDocument/didSave".to_string(),
|
||||
register_options: Some(serde_json::to_value(save_registration_options).unwrap()),
|
||||
};
|
||||
self.send_request::<lsp_types::request::RegisterCapability>(
|
||||
lsp_types::RegistrationParams { registrations: vec![registration] },
|
||||
|_, _| (),
|
||||
);
|
||||
}
|
||||
|
||||
fn next_event(&self, inbox: &Receiver<lsp_server::Message>) -> Option<Event> {
|
||||
select! {
|
||||
recv(inbox) -> msg =>
|
||||
|
@ -184,20 +190,20 @@ impl GlobalState {
|
|||
// NOTE: don't count blocking select! call as a loop-turn time
|
||||
let _p = profile::span("GlobalState::handle_event");
|
||||
|
||||
let event_dbg = format!("{event:?}");
|
||||
tracing::debug!("{:?} handle_event({:?})", loop_start, event);
|
||||
let task_queue_len = self.task_pool.handle.len();
|
||||
if task_queue_len > 0 {
|
||||
tracing::info!("task queue len: {}", task_queue_len);
|
||||
let event_dbg_msg = format!("{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();
|
||||
if task_queue_len > 0 {
|
||||
tracing::info!("task queue len: {}", task_queue_len);
|
||||
}
|
||||
}
|
||||
|
||||
let was_quiescent = self.is_quiescent();
|
||||
match event {
|
||||
Event::Lsp(msg) => match msg {
|
||||
lsp_server::Message::Request(req) => self.on_new_request(loop_start, req),
|
||||
lsp_server::Message::Notification(not) => {
|
||||
self.on_notification(not)?;
|
||||
}
|
||||
lsp_server::Message::Notification(not) => self.on_notification(not)?,
|
||||
lsp_server::Message::Response(resp) => self.complete_request(resp),
|
||||
},
|
||||
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.
|
||||
if self.config.semantic_tokens_refresh() {
|
||||
self.semantic_tokens_cache.lock().clear();
|
||||
|
@ -309,9 +316,9 @@ impl GlobalState {
|
|||
}
|
||||
}
|
||||
|
||||
if (!was_quiescent || state_changed || memdocs_added_or_removed)
|
||||
&& self.config.publish_diagnostics()
|
||||
{
|
||||
let update_diagnostics = (!was_quiescent || state_changed || memdocs_added_or_removed)
|
||||
&& self.config.publish_diagnostics();
|
||||
if update_diagnostics {
|
||||
self.update_diagnostics()
|
||||
}
|
||||
}
|
||||
|
@ -371,38 +378,40 @@ impl GlobalState {
|
|||
}
|
||||
|
||||
if let Some((cause, ())) = self.prime_caches_queue.should_start_op() {
|
||||
tracing::debug!(%cause, "will prime caches");
|
||||
let num_worker_threads = self.config.prime_caches_num_threads();
|
||||
|
||||
self.task_pool.handle.spawn_with_sender({
|
||||
let analysis = self.snapshot().analysis;
|
||||
move |sender| {
|
||||
sender.send(Task::PrimeCaches(PrimeCachesProgress::Begin)).unwrap();
|
||||
let res = analysis.parallel_prime_caches(num_worker_threads, |progress| {
|
||||
let report = PrimeCachesProgress::Report(progress);
|
||||
sender.send(Task::PrimeCaches(report)).unwrap();
|
||||
});
|
||||
sender
|
||||
.send(Task::PrimeCaches(PrimeCachesProgress::End {
|
||||
cancelled: res.is_err(),
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
});
|
||||
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}");
|
||||
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}"
|
||||
"overly long loop turn took {loop_duration:?}: {event_dbg_msg}"
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prime_caches(&mut self, cause: String) {
|
||||
tracing::debug!(%cause, "will prime caches");
|
||||
let num_worker_threads = self.config.prime_caches_num_threads();
|
||||
|
||||
self.task_pool.handle.spawn_with_sender({
|
||||
let analysis = self.snapshot().analysis;
|
||||
move |sender| {
|
||||
sender.send(Task::PrimeCaches(PrimeCachesProgress::Begin)).unwrap();
|
||||
let res = analysis.parallel_prime_caches(num_worker_threads, |progress| {
|
||||
let report = PrimeCachesProgress::Report(progress);
|
||||
sender.send(Task::PrimeCaches(report)).unwrap();
|
||||
});
|
||||
sender
|
||||
.send(Task::PrimeCaches(PrimeCachesProgress::End { cancelled: res.is_err() }))
|
||||
.unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn update_status_or_notify(&mut self) {
|
||||
let status = self.current_status();
|
||||
if self.last_reported_status.as_ref() != Some(&status) {
|
||||
|
|
Loading…
Reference in a new issue