aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/project_model/src/build_data.rs2
-rw-r--r--crates/rust-analyzer/src/global_state.rs13
-rw-r--r--crates/rust-analyzer/src/main_loop.rs20
-rw-r--r--crates/rust-analyzer/src/reload.rs76
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 {
52 configs: FxHashMap<AbsPathBuf, BuildDataConfig>, 52 configs: FxHashMap<AbsPathBuf, BuildDataConfig>,
53} 53}
54 54
55#[derive(Debug, Default, PartialEq, Eq)] 55#[derive(Debug, Default, PartialEq, Eq, Clone)]
56pub struct BuildDataResult { 56pub struct BuildDataResult {
57 data: FxHashMap<AbsPathBuf, BuildDataMap>, 57 data: FxHashMap<AbsPathBuf, BuildDataMap>,
58} 58}
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 {
82 pub(crate) source_root_config: SourceRootConfig, 82 pub(crate) source_root_config: SourceRootConfig,
83 pub(crate) proc_macro_client: Option<ProcMacroClient>, 83 pub(crate) proc_macro_client: Option<ProcMacroClient>,
84 84
85 /// For both `workspaces` and `workspace_build_data`, the field stores the
86 /// data we actually use, while the `OpQueue` stores the result of the last
87 /// fetch.
88 ///
89 /// If the fetch (partially) fails, we do not update the values.
85 pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, 90 pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
86 pub(crate) fetch_workspaces_queue: OpQueue<(), ()>, 91 pub(crate) fetch_workspaces_queue: OpQueue<(), Vec<anyhow::Result<ProjectWorkspace>>>,
87
88 pub(crate) workspace_build_data: Option<BuildDataResult>, 92 pub(crate) workspace_build_data: Option<BuildDataResult>,
89 pub(crate) fetch_build_data_queue: OpQueue<BuildDataCollector, ()>, 93 pub(crate) fetch_build_data_queue:
94 OpQueue<BuildDataCollector, Option<anyhow::Result<BuildDataResult>>>,
90 95
91 latest_requests: Arc<RwLock<LatestRequests>>, 96 latest_requests: Arc<RwLock<LatestRequests>>,
92} 97}
@@ -140,10 +145,12 @@ impl GlobalState {
140 status: Status::default(), 145 status: Status::default(),
141 source_root_config: SourceRootConfig::default(), 146 source_root_config: SourceRootConfig::default(),
142 proc_macro_client: None, 147 proc_macro_client: None,
148
143 workspaces: Arc::new(Vec::new()), 149 workspaces: Arc::new(Vec::new()),
144 fetch_workspaces_queue: OpQueue::default(), 150 fetch_workspaces_queue: OpQueue::default(),
145 workspace_build_data: None, 151 workspace_build_data: None,
146 fetch_build_data_queue: OpQueue::default(), 152 fetch_build_data_queue: OpQueue::default(),
153
147 latest_requests: Default::default(), 154 latest_requests: Default::default(),
148 } 155 }
149 } 156 }
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};
12use ide_db::base_db::VfsPath; 12use ide_db::base_db::VfsPath;
13use lsp_server::{Connection, Notification, Request, Response}; 13use lsp_server::{Connection, Notification, Request, Response};
14use lsp_types::notification::Notification as _; 14use lsp_types::notification::Notification as _;
15use project_model::BuildDataCollector;
15use vfs::ChangeKind; 16use vfs::ChangeKind;
16 17
17use crate::{ 18use crate::{
@@ -227,8 +228,15 @@ impl GlobalState {
227 (Progress::Report, Some(msg)) 228 (Progress::Report, Some(msg))
228 } 229 }
229 ProjectWorkspaceProgress::End(workspaces) => { 230 ProjectWorkspaceProgress::End(workspaces) => {
230 self.fetch_workspaces_completed(); 231 self.fetch_workspaces_completed(workspaces);
231 self.switch_workspaces(workspaces, None); 232 self.switch_workspaces();
233 if self.config.run_build_scripts() {
234 let mut collector = BuildDataCollector::default();
235 for ws in self.workspaces.iter() {
236 ws.collect_build_data_configs(&mut collector);
237 }
238 self.fetch_build_data_request(collector)
239 }
232 (Progress::End, None) 240 (Progress::End, None)
233 } 241 }
234 }; 242 };
@@ -240,11 +248,9 @@ impl GlobalState {
240 BuildDataProgress::Report(msg) => { 248 BuildDataProgress::Report(msg) => {
241 (Some(Progress::Report), Some(msg)) 249 (Some(Progress::Report), Some(msg))
242 } 250 }
243 BuildDataProgress::End(collector) => { 251 BuildDataProgress::End(build_data_result) => {
244 self.fetch_build_data_completed(); 252 self.fetch_build_data_completed(build_data_result);
245 let workspaces = 253 self.switch_workspaces();
246 (*self.workspaces).clone().into_iter().map(Ok).collect();
247 self.switch_workspaces(workspaces, Some(collector));
248 (Some(Progress::End), None) 254 (Some(Progress::End), None)
249 } 255 }
250 }; 256 };
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 {
139 sender.send(Task::FetchBuildData(BuildDataProgress::End(res))).unwrap(); 139 sender.send(Task::FetchBuildData(BuildDataProgress::End(res))).unwrap();
140 }); 140 });
141 } 141 }
142 pub(crate) fn fetch_build_data_completed(&mut self) { 142 pub(crate) fn fetch_build_data_completed(
143 self.fetch_build_data_queue.op_completed(()) 143 &mut self,
144 build_data: anyhow::Result<BuildDataResult>,
145 ) {
146 self.fetch_build_data_queue.op_completed(Some(build_data))
144 } 147 }
145 148
146 pub(crate) fn fetch_workspaces_request(&mut self) { 149 pub(crate) fn fetch_workspaces_request(&mut self) {
@@ -194,54 +197,55 @@ impl GlobalState {
194 } 197 }
195 }); 198 });
196 } 199 }
197 pub(crate) fn fetch_workspaces_completed(&mut self) { 200 pub(crate) fn fetch_workspaces_completed(
198 self.fetch_workspaces_queue.op_completed(())
199 }
200
201 pub(crate) fn switch_workspaces(
202 &mut self, 201 &mut self,
203 workspaces: Vec<anyhow::Result<ProjectWorkspace>>, 202 workspaces: Vec<anyhow::Result<ProjectWorkspace>>,
204 workspace_build_data: Option<anyhow::Result<BuildDataResult>>,
205 ) { 203 ) {
204 self.fetch_workspaces_queue.op_completed(workspaces)
205 }
206
207 pub(crate) fn switch_workspaces(&mut self) {
206 let _p = profile::span("GlobalState::switch_workspaces"); 208 let _p = profile::span("GlobalState::switch_workspaces");
209 let workspaces = self.fetch_workspaces_queue.last_op_result();
207 log::info!("will switch workspaces: {:?}", workspaces); 210 log::info!("will switch workspaces: {:?}", workspaces);
208 211
209 let mut has_errors = false; 212 let mut error_message = None;
210 let workspaces = workspaces 213 let workspaces = workspaces
211 .into_iter() 214 .iter()
212 .filter_map(|res| { 215 .filter_map(|res| match res {
213 res.map_err(|err| { 216 Ok(it) => Some(it.clone()),
214 has_errors = true; 217 Err(err) => {
215 log::error!("failed to load workspace: {:#}", err); 218 log::error!("failed to load workspace: {:#}", err);
216 if self.workspaces.is_empty() { 219 let message = error_message.get_or_insert_with(String::new);
217 self.show_message( 220 stdx::format_to!(
218 lsp_types::MessageType::Error, 221 message,
219 format!("rust-analyzer failed to load workspace: {:#}", err), 222 "rust-analyzer failed to load workspace: {:#}\n",
220 ); 223 err
221 } 224 );
222 }) 225 None
223 .ok() 226 }
224 }) 227 })
225 .collect::<Vec<_>>(); 228 .collect::<Vec<_>>();
226 229
227 let workspace_build_data = match workspace_build_data { 230 let workspace_build_data = match self.fetch_build_data_queue.last_op_result() {
228 Some(Ok(it)) => Some(it), 231 Some(Ok(it)) => Some(it.clone()),
232 None => None,
229 Some(Err(err)) => { 233 Some(Err(err)) => {
230 log::error!("failed to fetch build data: {:#}", err); 234 log::error!("failed to fetch build data: {:#}", err);
231 self.show_message( 235 let message = error_message.get_or_insert_with(String::new);
232 lsp_types::MessageType::Error, 236 stdx::format_to!(message, "rust-analyzer failed to fetch build data: {:#}\n", err);
233 format!("rust-analyzer failed to fetch build data: {:#}", err), 237 None
234 );
235 return;
236 } 238 }
237 None => None,
238 }; 239 };
239 240
240 if *self.workspaces == workspaces && self.workspace_build_data == workspace_build_data { 241 if let Some(error_message) = error_message {
241 return; 242 self.show_message(lsp_types::MessageType::Error, error_message);
243 if !self.workspaces.is_empty() {
244 return;
245 }
242 } 246 }
243 247
244 if !self.workspaces.is_empty() && has_errors { 248 if *self.workspaces == workspaces && self.workspace_build_data == workspace_build_data {
245 return; 249 return;
246 } 250 }
247 251
@@ -337,14 +341,6 @@ impl GlobalState {
337 }; 341 };
338 change.set_crate_graph(crate_graph); 342 change.set_crate_graph(crate_graph);
339 343
340 if self.config.run_build_scripts() && workspace_build_data.is_none() {
341 let mut collector = BuildDataCollector::default();
342 for ws in &workspaces {
343 ws.collect_build_data_configs(&mut collector);
344 }
345 self.fetch_build_data_request(collector)
346 }
347
348 self.source_root_config = project_folders.source_root_config; 344 self.source_root_config = project_folders.source_root_config;
349 self.workspaces = Arc::new(workspaces); 345 self.workspaces = Arc::new(workspaces);
350 self.workspace_build_data = workspace_build_data; 346 self.workspace_build_data = workspace_build_data;