diff options
author | Aleksey Kladov <[email protected]> | 2021-04-06 16:08:05 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-04-06 16:08:05 +0100 |
commit | de3370278468e5135e4990fc14562e5ce523ef37 (patch) | |
tree | bd433d92a1a44b9b5bc7a6603b7862ed47c3937b | |
parent | 9ec5e6e4fdbe893f38d10dbdc609284368efdb64 (diff) |
feat: show errors from `cargo metadata` and initial `cargo check` in the status bar
closes #3155
-rw-r--r-- | crates/project_model/src/build_data.rs | 27 | ||||
-rw-r--r-- | crates/rust-analyzer/src/reload.rs | 41 | ||||
-rw-r--r-- | crates/stdx/src/lib.rs | 8 |
3 files changed, 63 insertions, 13 deletions
diff --git a/crates/project_model/src/build_data.rs b/crates/project_model/src/build_data.rs index fdf4b2d55..0d4d39fef 100644 --- a/crates/project_model/src/build_data.rs +++ b/crates/project_model/src/build_data.rs | |||
@@ -13,7 +13,7 @@ use cargo_metadata::{BuildScript, Message}; | |||
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
14 | use paths::{AbsPath, AbsPathBuf}; | 14 | use paths::{AbsPath, AbsPathBuf}; |
15 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::FxHashMap; |
16 | use stdx::JodChild; | 16 | use stdx::{format_to, JodChild}; |
17 | 17 | ||
18 | use crate::{cfg_flag::CfgFlag, CargoConfig}; | 18 | use crate::{cfg_flag::CfgFlag, CargoConfig}; |
19 | 19 | ||
@@ -35,6 +35,7 @@ pub(crate) struct PackageBuildData { | |||
35 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | 35 | #[derive(Debug, Default, PartialEq, Eq, Clone)] |
36 | pub(crate) struct WorkspaceBuildData { | 36 | pub(crate) struct WorkspaceBuildData { |
37 | per_package: FxHashMap<String, PackageBuildData>, | 37 | per_package: FxHashMap<String, PackageBuildData>, |
38 | error: Option<String>, | ||
38 | } | 39 | } |
39 | 40 | ||
40 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | 41 | #[derive(Debug, Default, PartialEq, Eq, Clone)] |
@@ -94,6 +95,19 @@ impl BuildDataResult { | |||
94 | pub(crate) fn get(&self, workspace_root: &AbsPath) -> Option<&WorkspaceBuildData> { | 95 | pub(crate) fn get(&self, workspace_root: &AbsPath) -> Option<&WorkspaceBuildData> { |
95 | self.per_workspace.get(workspace_root) | 96 | self.per_workspace.get(workspace_root) |
96 | } | 97 | } |
98 | pub fn error(&self) -> Option<String> { | ||
99 | let mut buf = String::new(); | ||
100 | for (_workspace_root, build_data) in &self.per_workspace { | ||
101 | if let Some(err) = &build_data.error { | ||
102 | format_to!(buf, "cargo check failed:\n{}", err); | ||
103 | } | ||
104 | } | ||
105 | if buf.is_empty() { | ||
106 | return None; | ||
107 | } | ||
108 | |||
109 | Some(buf) | ||
110 | } | ||
97 | } | 111 | } |
98 | 112 | ||
99 | impl BuildDataConfig { | 113 | impl BuildDataConfig { |
@@ -139,7 +153,7 @@ fn collect_from_workspace( | |||
139 | } | 153 | } |
140 | } | 154 | } |
141 | 155 | ||
142 | cmd.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()); | 156 | cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null()); |
143 | 157 | ||
144 | let mut child = cmd.spawn().map(JodChild)?; | 158 | let mut child = cmd.spawn().map(JodChild)?; |
145 | let child_stdout = child.stdout.take().unwrap(); | 159 | let child_stdout = child.stdout.take().unwrap(); |
@@ -209,6 +223,15 @@ fn collect_from_workspace( | |||
209 | } | 223 | } |
210 | } | 224 | } |
211 | 225 | ||
226 | let output = child.into_inner().wait_with_output()?; | ||
227 | if !output.status.success() { | ||
228 | let mut stderr = String::from_utf8(output.stderr).unwrap_or_default(); | ||
229 | if stderr.is_empty() { | ||
230 | stderr = "cargo check failed".to_string(); | ||
231 | } | ||
232 | res.error = Some(stderr) | ||
233 | } | ||
234 | |||
212 | Ok(res) | 235 | Ok(res) |
213 | } | 236 | } |
214 | 237 | ||
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 301c7003b..d0cc1b61a 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs | |||
@@ -109,6 +109,11 @@ impl GlobalState { | |||
109 | quiescent: self.is_quiescent(), | 109 | quiescent: self.is_quiescent(), |
110 | message: None, | 110 | message: None, |
111 | }; | 111 | }; |
112 | |||
113 | if let Some(error) = self.build_data_error() { | ||
114 | status.health = lsp_ext::Health::Warning; | ||
115 | status.message = Some(error) | ||
116 | } | ||
112 | if !self.config.cargo_autoreload() | 117 | if !self.config.cargo_autoreload() |
113 | && self.is_quiescent() | 118 | && self.is_quiescent() |
114 | && self.fetch_workspaces_queue.op_requested() | 119 | && self.fetch_workspaces_queue.op_requested() |
@@ -116,9 +121,10 @@ impl GlobalState { | |||
116 | status.health = lsp_ext::Health::Warning; | 121 | status.health = lsp_ext::Health::Warning; |
117 | status.message = Some("Workspace reload required".to_string()) | 122 | status.message = Some("Workspace reload required".to_string()) |
118 | } | 123 | } |
119 | if let Some(error) = self.loading_error() { | 124 | |
125 | if let Some(error) = self.fetch_workspace_error() { | ||
120 | status.health = lsp_ext::Health::Error; | 126 | status.health = lsp_ext::Health::Error; |
121 | status.message = Some(format!("Workspace reload failed: {}", error)) | 127 | status.message = Some(error) |
122 | } | 128 | } |
123 | 129 | ||
124 | if self.last_reported_status.as_ref() != Some(&status) { | 130 | if self.last_reported_status.as_ref() != Some(&status) { |
@@ -217,7 +223,7 @@ impl GlobalState { | |||
217 | let _p = profile::span("GlobalState::switch_workspaces"); | 223 | let _p = profile::span("GlobalState::switch_workspaces"); |
218 | log::info!("will switch workspaces"); | 224 | log::info!("will switch workspaces"); |
219 | 225 | ||
220 | if let Some(error_message) = self.loading_error() { | 226 | if let Some(error_message) = self.fetch_workspace_error() { |
221 | log::error!("failed to switch workspaces: {}", error_message); | 227 | log::error!("failed to switch workspaces: {}", error_message); |
222 | self.show_message(lsp_types::MessageType::Error, error_message); | 228 | self.show_message(lsp_types::MessageType::Error, error_message); |
223 | if !self.workspaces.is_empty() { | 229 | if !self.workspaces.is_empty() { |
@@ -225,6 +231,11 @@ impl GlobalState { | |||
225 | } | 231 | } |
226 | } | 232 | } |
227 | 233 | ||
234 | if let Some(error_message) = self.build_data_error() { | ||
235 | log::error!("failed to switch build data: {}", error_message); | ||
236 | self.show_message(lsp_types::MessageType::Error, error_message); | ||
237 | } | ||
238 | |||
228 | let workspaces = self | 239 | let workspaces = self |
229 | .fetch_workspaces_queue | 240 | .fetch_workspaces_queue |
230 | .last_op_result() | 241 | .last_op_result() |
@@ -343,22 +354,30 @@ impl GlobalState { | |||
343 | log::info!("did switch workspaces"); | 354 | log::info!("did switch workspaces"); |
344 | } | 355 | } |
345 | 356 | ||
346 | fn loading_error(&self) -> Option<String> { | 357 | fn fetch_workspace_error(&self) -> Option<String> { |
347 | let mut message = None; | 358 | let mut buf = String::new(); |
348 | 359 | ||
349 | for ws in self.fetch_workspaces_queue.last_op_result() { | 360 | for ws in self.fetch_workspaces_queue.last_op_result() { |
350 | if let Err(err) = ws { | 361 | if let Err(err) = ws { |
351 | let message = message.get_or_insert_with(String::new); | 362 | stdx::format_to!(buf, "rust-analyzer failed to load workspace: {:#}\n", err); |
352 | stdx::format_to!(message, "rust-analyzer failed to load workspace: {:#}\n", err); | ||
353 | } | 363 | } |
354 | } | 364 | } |
355 | 365 | ||
356 | if let Some(Err(err)) = self.fetch_build_data_queue.last_op_result() { | 366 | if buf.is_empty() { |
357 | let message = message.get_or_insert_with(String::new); | 367 | return None; |
358 | stdx::format_to!(message, "rust-analyzer failed to fetch build data: {:#}\n", err); | ||
359 | } | 368 | } |
360 | 369 | ||
361 | message | 370 | Some(buf) |
371 | } | ||
372 | |||
373 | fn build_data_error(&self) -> Option<String> { | ||
374 | match self.fetch_build_data_queue.last_op_result() { | ||
375 | Some(Err(err)) => { | ||
376 | Some(format!("rust-analyzer failed to fetch build data: {:#}\n", err)) | ||
377 | } | ||
378 | Some(Ok(data)) => data.error(), | ||
379 | None => None, | ||
380 | } | ||
362 | } | 381 | } |
363 | 382 | ||
364 | fn reload_flycheck(&mut self) { | 383 | fn reload_flycheck(&mut self) { |
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index d26be4853..b0a18d58d 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs | |||
@@ -178,6 +178,7 @@ where | |||
178 | start..start + len | 178 | start..start + len |
179 | } | 179 | } |
180 | 180 | ||
181 | #[repr(transparent)] | ||
181 | pub struct JodChild(pub process::Child); | 182 | pub struct JodChild(pub process::Child); |
182 | 183 | ||
183 | impl ops::Deref for JodChild { | 184 | impl ops::Deref for JodChild { |
@@ -200,6 +201,13 @@ impl Drop for JodChild { | |||
200 | } | 201 | } |
201 | } | 202 | } |
202 | 203 | ||
204 | impl JodChild { | ||
205 | pub fn into_inner(self) -> process::Child { | ||
206 | // SAFETY: repr transparent | ||
207 | unsafe { std::mem::transmute::<JodChild, process::Child>(self) } | ||
208 | } | ||
209 | } | ||
210 | |||
203 | #[cfg(test)] | 211 | #[cfg(test)] |
204 | mod tests { | 212 | mod tests { |
205 | use super::*; | 213 | use super::*; |