diff options
author | Aleksey Kladov <[email protected]> | 2021-04-06 12:16:35 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-04-06 13:45:31 +0100 |
commit | 8fe20b19d4702fc6d6933c31abddc8539d2581f0 (patch) | |
tree | 8aca2a3aa2b059bb47cc235b1b557d4b4de93a24 /crates/rust-analyzer/src/reload.rs | |
parent | 9143e3925cd95d30af72745f25e185f65a686d32 (diff) |
More robust status notifications
Diffstat (limited to 'crates/rust-analyzer/src/reload.rs')
-rw-r--r-- | crates/rust-analyzer/src/reload.rs | 119 |
1 files changed, 67 insertions, 52 deletions
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 5ff60c22a..301c7003b 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs | |||
@@ -9,11 +9,10 @@ use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind}; | |||
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | config::{Config, FilesWatcher, LinkedProject}, | 11 | config::{Config, FilesWatcher, LinkedProject}, |
12 | global_state::{GlobalState, Status}, | 12 | global_state::GlobalState, |
13 | lsp_ext, | 13 | lsp_ext, |
14 | main_loop::Task, | 14 | main_loop::Task, |
15 | }; | 15 | }; |
16 | use lsp_ext::StatusParams; | ||
17 | 16 | ||
18 | #[derive(Debug)] | 17 | #[derive(Debug)] |
19 | pub(crate) enum ProjectWorkspaceProgress { | 18 | pub(crate) enum ProjectWorkspaceProgress { |
@@ -30,6 +29,13 @@ pub(crate) enum BuildDataProgress { | |||
30 | } | 29 | } |
31 | 30 | ||
32 | impl GlobalState { | 31 | impl GlobalState { |
32 | pub(crate) fn is_quiescent(&self) -> bool { | ||
33 | !(self.fetch_workspaces_queue.op_in_progress() | ||
34 | || self.fetch_build_data_queue.op_in_progress() | ||
35 | || self.vfs_progress_config_version < self.vfs_config_version | ||
36 | || self.vfs_progress_n_done < self.vfs_progress_n_total) | ||
37 | } | ||
38 | |||
33 | pub(crate) fn update_configuration(&mut self, config: Config) { | 39 | pub(crate) fn update_configuration(&mut self, config: Config) { |
34 | let _p = profile::span("GlobalState::update_configuration"); | 40 | let _p = profile::span("GlobalState::update_configuration"); |
35 | let old_config = mem::replace(&mut self.config, Arc::new(config)); | 41 | let old_config = mem::replace(&mut self.config, Arc::new(config)); |
@@ -46,17 +52,13 @@ impl GlobalState { | |||
46 | if !changes.iter().any(|(path, kind)| is_interesting(path, *kind)) { | 52 | if !changes.iter().any(|(path, kind)| is_interesting(path, *kind)) { |
47 | return; | 53 | return; |
48 | } | 54 | } |
49 | match self.status { | ||
50 | Status::Loading | Status::NeedsReload => return, | ||
51 | Status::Ready { .. } | Status::Invalid => (), | ||
52 | } | ||
53 | log::info!( | 55 | log::info!( |
54 | "Reloading workspace because of the following changes: {}", | 56 | "Requesting workspace reload because of the following changes: {}", |
55 | itertools::join( | 57 | itertools::join( |
56 | changes | 58 | changes |
57 | .iter() | 59 | .iter() |
58 | .filter(|(path, kind)| is_interesting(path, *kind)) | 60 | .filter(|(path, kind)| is_interesting(path, *kind)) |
59 | .map(|(path, kind)| format!("{}/{:?}", path.display(), kind)), | 61 | .map(|(path, kind)| format!("{}: {:?}", path.display(), kind)), |
60 | ", " | 62 | ", " |
61 | ) | 63 | ) |
62 | ); | 64 | ); |
@@ -97,19 +99,31 @@ impl GlobalState { | |||
97 | false | 99 | false |
98 | } | 100 | } |
99 | } | 101 | } |
100 | pub(crate) fn transition(&mut self, new_status: Status) { | 102 | pub(crate) fn report_new_status_if_needed(&mut self) { |
101 | self.status = new_status; | 103 | if !self.config.server_status_notification() { |
102 | if self.config.status_notification() { | 104 | return; |
103 | let lsp_status = match new_status { | 105 | } |
104 | Status::Loading => lsp_ext::Status::Loading, | 106 | |
105 | Status::Ready { partial: true } => lsp_ext::Status::ReadyPartial, | 107 | let mut status = lsp_ext::ServerStatusParams { |
106 | Status::Ready { partial: false } => lsp_ext::Status::Ready, | 108 | health: lsp_ext::Health::Ok, |
107 | Status::Invalid => lsp_ext::Status::Invalid, | 109 | quiescent: self.is_quiescent(), |
108 | Status::NeedsReload => lsp_ext::Status::NeedsReload, | 110 | message: None, |
109 | }; | 111 | }; |
110 | self.send_notification::<lsp_ext::StatusNotification>(StatusParams { | 112 | if !self.config.cargo_autoreload() |
111 | status: lsp_status, | 113 | && self.is_quiescent() |
112 | }); | 114 | && self.fetch_workspaces_queue.op_requested() |
115 | { | ||
116 | status.health = lsp_ext::Health::Warning; | ||
117 | status.message = Some("Workspace reload required".to_string()) | ||
118 | } | ||
119 | if let Some(error) = self.loading_error() { | ||
120 | status.health = lsp_ext::Health::Error; | ||
121 | status.message = Some(format!("Workspace reload failed: {}", error)) | ||
122 | } | ||
123 | |||
124 | if self.last_reported_status.as_ref() != Some(&status) { | ||
125 | self.last_reported_status = Some(status.clone()); | ||
126 | self.send_notification::<lsp_ext::ServerStatusNotification>(status); | ||
113 | } | 127 | } |
114 | } | 128 | } |
115 | 129 | ||
@@ -201,45 +215,28 @@ impl GlobalState { | |||
201 | 215 | ||
202 | pub(crate) fn switch_workspaces(&mut self) { | 216 | pub(crate) fn switch_workspaces(&mut self) { |
203 | let _p = profile::span("GlobalState::switch_workspaces"); | 217 | let _p = profile::span("GlobalState::switch_workspaces"); |
204 | let workspaces = self.fetch_workspaces_queue.last_op_result(); | 218 | log::info!("will switch workspaces"); |
205 | log::info!("will switch workspaces: {:?}", workspaces); | 219 | |
220 | if let Some(error_message) = self.loading_error() { | ||
221 | log::error!("failed to switch workspaces: {}", error_message); | ||
222 | self.show_message(lsp_types::MessageType::Error, error_message); | ||
223 | if !self.workspaces.is_empty() { | ||
224 | return; | ||
225 | } | ||
226 | } | ||
206 | 227 | ||
207 | let mut error_message = None; | 228 | let workspaces = self |
208 | let workspaces = workspaces | 229 | .fetch_workspaces_queue |
230 | .last_op_result() | ||
209 | .iter() | 231 | .iter() |
210 | .filter_map(|res| match res { | 232 | .filter_map(|res| res.as_ref().ok().cloned()) |
211 | Ok(it) => Some(it.clone()), | ||
212 | Err(err) => { | ||
213 | log::error!("failed to load workspace: {:#}", err); | ||
214 | let message = error_message.get_or_insert_with(String::new); | ||
215 | stdx::format_to!( | ||
216 | message, | ||
217 | "rust-analyzer failed to load workspace: {:#}\n", | ||
218 | err | ||
219 | ); | ||
220 | None | ||
221 | } | ||
222 | }) | ||
223 | .collect::<Vec<_>>(); | 233 | .collect::<Vec<_>>(); |
224 | 234 | ||
225 | let workspace_build_data = match self.fetch_build_data_queue.last_op_result() { | 235 | let workspace_build_data = match self.fetch_build_data_queue.last_op_result() { |
226 | Some(Ok(it)) => Some(it.clone()), | 236 | Some(Ok(it)) => Some(it.clone()), |
227 | None => None, | 237 | None | Some(Err(_)) => None, |
228 | Some(Err(err)) => { | ||
229 | log::error!("failed to fetch build data: {:#}", err); | ||
230 | let message = error_message.get_or_insert_with(String::new); | ||
231 | stdx::format_to!(message, "rust-analyzer failed to fetch build data: {:#}\n", err); | ||
232 | None | ||
233 | } | ||
234 | }; | 238 | }; |
235 | 239 | ||
236 | if let Some(error_message) = error_message { | ||
237 | self.show_message(lsp_types::MessageType::Error, error_message); | ||
238 | if !self.workspaces.is_empty() { | ||
239 | return; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | if *self.workspaces == workspaces && self.workspace_build_data == workspace_build_data { | 240 | if *self.workspaces == workspaces && self.workspace_build_data == workspace_build_data { |
244 | return; | 241 | return; |
245 | } | 242 | } |
@@ -346,6 +343,24 @@ impl GlobalState { | |||
346 | log::info!("did switch workspaces"); | 343 | log::info!("did switch workspaces"); |
347 | } | 344 | } |
348 | 345 | ||
346 | fn loading_error(&self) -> Option<String> { | ||
347 | let mut message = None; | ||
348 | |||
349 | for ws in self.fetch_workspaces_queue.last_op_result() { | ||
350 | if let Err(err) = ws { | ||
351 | let message = message.get_or_insert_with(String::new); | ||
352 | stdx::format_to!(message, "rust-analyzer failed to load workspace: {:#}\n", err); | ||
353 | } | ||
354 | } | ||
355 | |||
356 | if let Some(Err(err)) = self.fetch_build_data_queue.last_op_result() { | ||
357 | let message = message.get_or_insert_with(String::new); | ||
358 | stdx::format_to!(message, "rust-analyzer failed to fetch build data: {:#}\n", err); | ||
359 | } | ||
360 | |||
361 | message | ||
362 | } | ||
363 | |||
349 | fn reload_flycheck(&mut self) { | 364 | fn reload_flycheck(&mut self) { |
350 | let _p = profile::span("GlobalState::reload_flycheck"); | 365 | let _p = profile::span("GlobalState::reload_flycheck"); |
351 | let config = match self.config.flycheck() { | 366 | let config = match self.config.flycheck() { |