From aaa8c208b12e3ddb1b4a7fd3d843182ae12cdae5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 5 Apr 2021 22:30:19 +0300 Subject: internal: do not drop errors from cargo metadata/check Work towards #3155 --- crates/project_model/src/build_data.rs | 2 +- crates/rust-analyzer/src/global_state.rs | 13 ++++-- crates/rust-analyzer/src/main_loop.rs | 20 ++++++--- crates/rust-analyzer/src/reload.rs | 76 +++++++++++++++----------------- 4 files changed, 60 insertions(+), 51 deletions(-) diff --git a/crates/project_model/src/build_data.rs b/crates/project_model/src/build_data.rs index f7050be4e..c2c87b207 100644 --- a/crates/project_model/src/build_data.rs +++ b/crates/project_model/src/build_data.rs @@ -52,7 +52,7 @@ pub struct BuildDataCollector { configs: FxHashMap, } -#[derive(Debug, Default, PartialEq, Eq)] +#[derive(Debug, Default, PartialEq, Eq, Clone)] pub struct BuildDataResult { data: FxHashMap, } diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 8679c8599..b9be1e7b8 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -82,11 +82,16 @@ pub(crate) struct GlobalState { pub(crate) source_root_config: SourceRootConfig, pub(crate) proc_macro_client: Option, + /// For both `workspaces` and `workspace_build_data`, the field stores the + /// data we actually use, while the `OpQueue` stores the result of the last + /// fetch. + /// + /// If the fetch (partially) fails, we do not update the values. pub(crate) workspaces: Arc>, - pub(crate) fetch_workspaces_queue: OpQueue<(), ()>, - + pub(crate) fetch_workspaces_queue: OpQueue<(), Vec>>, pub(crate) workspace_build_data: Option, - pub(crate) fetch_build_data_queue: OpQueue, + pub(crate) fetch_build_data_queue: + OpQueue>>, latest_requests: Arc>, } @@ -140,10 +145,12 @@ impl GlobalState { status: Status::default(), source_root_config: SourceRootConfig::default(), proc_macro_client: None, + workspaces: Arc::new(Vec::new()), fetch_workspaces_queue: OpQueue::default(), workspace_build_data: None, fetch_build_data_queue: OpQueue::default(), + latest_requests: Default::default(), } } diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index e88f16cc1..eec6676e0 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -12,6 +12,7 @@ use ide::{Canceled, FileId}; use ide_db::base_db::VfsPath; use lsp_server::{Connection, Notification, Request, Response}; use lsp_types::notification::Notification as _; +use project_model::BuildDataCollector; use vfs::ChangeKind; use crate::{ @@ -227,8 +228,15 @@ impl GlobalState { (Progress::Report, Some(msg)) } ProjectWorkspaceProgress::End(workspaces) => { - self.fetch_workspaces_completed(); - self.switch_workspaces(workspaces, None); + self.fetch_workspaces_completed(workspaces); + self.switch_workspaces(); + if self.config.run_build_scripts() { + let mut collector = BuildDataCollector::default(); + for ws in self.workspaces.iter() { + ws.collect_build_data_configs(&mut collector); + } + self.fetch_build_data_request(collector) + } (Progress::End, None) } }; @@ -240,11 +248,9 @@ impl GlobalState { BuildDataProgress::Report(msg) => { (Some(Progress::Report), Some(msg)) } - BuildDataProgress::End(collector) => { - self.fetch_build_data_completed(); - let workspaces = - (*self.workspaces).clone().into_iter().map(Ok).collect(); - self.switch_workspaces(workspaces, Some(collector)); + BuildDataProgress::End(build_data_result) => { + self.fetch_build_data_completed(build_data_result); + self.switch_workspaces(); (Some(Progress::End), None) } }; diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index d12f891bb..cdd6eae69 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -139,8 +139,11 @@ impl GlobalState { sender.send(Task::FetchBuildData(BuildDataProgress::End(res))).unwrap(); }); } - pub(crate) fn fetch_build_data_completed(&mut self) { - self.fetch_build_data_queue.op_completed(()) + pub(crate) fn fetch_build_data_completed( + &mut self, + build_data: anyhow::Result, + ) { + self.fetch_build_data_queue.op_completed(Some(build_data)) } pub(crate) fn fetch_workspaces_request(&mut self) { @@ -194,54 +197,55 @@ impl GlobalState { } }); } - pub(crate) fn fetch_workspaces_completed(&mut self) { - self.fetch_workspaces_queue.op_completed(()) - } - - pub(crate) fn switch_workspaces( + pub(crate) fn fetch_workspaces_completed( &mut self, workspaces: Vec>, - workspace_build_data: Option>, ) { + self.fetch_workspaces_queue.op_completed(workspaces) + } + + pub(crate) fn switch_workspaces(&mut self) { let _p = profile::span("GlobalState::switch_workspaces"); + let workspaces = self.fetch_workspaces_queue.last_op_result(); log::info!("will switch workspaces: {:?}", workspaces); - let mut has_errors = false; + let mut error_message = None; let workspaces = workspaces - .into_iter() - .filter_map(|res| { - res.map_err(|err| { - has_errors = true; + .iter() + .filter_map(|res| match res { + Ok(it) => Some(it.clone()), + Err(err) => { log::error!("failed to load workspace: {:#}", err); - if self.workspaces.is_empty() { - self.show_message( - lsp_types::MessageType::Error, - format!("rust-analyzer failed to load workspace: {:#}", err), - ); - } - }) - .ok() + let message = error_message.get_or_insert_with(String::new); + stdx::format_to!( + message, + "rust-analyzer failed to load workspace: {:#}\n", + err + ); + None + } }) .collect::>(); - let workspace_build_data = match workspace_build_data { - Some(Ok(it)) => Some(it), + let workspace_build_data = match self.fetch_build_data_queue.last_op_result() { + Some(Ok(it)) => Some(it.clone()), + None => None, Some(Err(err)) => { log::error!("failed to fetch build data: {:#}", err); - self.show_message( - lsp_types::MessageType::Error, - format!("rust-analyzer failed to fetch build data: {:#}", err), - ); - return; + let message = error_message.get_or_insert_with(String::new); + stdx::format_to!(message, "rust-analyzer failed to fetch build data: {:#}\n", err); + None } - None => None, }; - if *self.workspaces == workspaces && self.workspace_build_data == workspace_build_data { - return; + if let Some(error_message) = error_message { + self.show_message(lsp_types::MessageType::Error, error_message); + if !self.workspaces.is_empty() { + return; + } } - if !self.workspaces.is_empty() && has_errors { + if *self.workspaces == workspaces && self.workspace_build_data == workspace_build_data { return; } @@ -337,14 +341,6 @@ impl GlobalState { }; change.set_crate_graph(crate_graph); - if self.config.run_build_scripts() && workspace_build_data.is_none() { - let mut collector = BuildDataCollector::default(); - for ws in &workspaces { - ws.collect_build_data_configs(&mut collector); - } - self.fetch_build_data_request(collector) - } - self.source_root_config = project_folders.source_root_config; self.workspaces = Arc::new(workspaces); self.workspace_build_data = workspace_build_data; -- cgit v1.2.3