diff options
-rw-r--r-- | crates/project_model/src/build_data.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 13 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 20 | ||||
-rw-r--r-- | 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 { | |||
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)] |
56 | pub struct BuildDataResult { | 56 | pub 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}; | |||
12 | use ide_db::base_db::VfsPath; | 12 | use ide_db::base_db::VfsPath; |
13 | use lsp_server::{Connection, Notification, Request, Response}; | 13 | use lsp_server::{Connection, Notification, Request, Response}; |
14 | use lsp_types::notification::Notification as _; | 14 | use lsp_types::notification::Notification as _; |
15 | use project_model::BuildDataCollector; | ||
15 | use vfs::ChangeKind; | 16 | use vfs::ChangeKind; |
16 | 17 | ||
17 | use crate::{ | 18 | use 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; |