aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-04-06 16:08:05 +0100
committerAleksey Kladov <[email protected]>2021-04-06 16:08:05 +0100
commitde3370278468e5135e4990fc14562e5ce523ef37 (patch)
treebd433d92a1a44b9b5bc7a6603b7862ed47c3937b
parent9ec5e6e4fdbe893f38d10dbdc609284368efdb64 (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.rs27
-rw-r--r--crates/rust-analyzer/src/reload.rs41
-rw-r--r--crates/stdx/src/lib.rs8
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};
13use itertools::Itertools; 13use itertools::Itertools;
14use paths::{AbsPath, AbsPathBuf}; 14use paths::{AbsPath, AbsPathBuf};
15use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
16use stdx::JodChild; 16use stdx::{format_to, JodChild};
17 17
18use crate::{cfg_flag::CfgFlag, CargoConfig}; 18use 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)]
36pub(crate) struct WorkspaceBuildData { 36pub(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
99impl BuildDataConfig { 113impl 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)]
181pub struct JodChild(pub process::Child); 182pub struct JodChild(pub process::Child);
182 183
183impl ops::Deref for JodChild { 184impl ops::Deref for JodChild {
@@ -200,6 +201,13 @@ impl Drop for JodChild {
200 } 201 }
201} 202}
202 203
204impl 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)]
204mod tests { 212mod tests {
205 use super::*; 213 use super::*;