Skip to content

Commit de33702

Browse files
committed
feat: show errors from cargo metadata and initial cargo check in the status bar
closes #3155
1 parent 9ec5e6e commit de33702

File tree

3 files changed

+63
-13
lines changed

3 files changed

+63
-13
lines changed

crates/project_model/src/build_data.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use cargo_metadata::{BuildScript, Message};
1313
use itertools::Itertools;
1414
use paths::{AbsPath, AbsPathBuf};
1515
use rustc_hash::FxHashMap;
16-
use stdx::JodChild;
16+
use stdx::{format_to, JodChild};
1717

1818
use crate::{cfg_flag::CfgFlag, CargoConfig};
1919

@@ -35,6 +35,7 @@ pub(crate) struct PackageBuildData {
3535
#[derive(Debug, Default, PartialEq, Eq, Clone)]
3636
pub(crate) struct WorkspaceBuildData {
3737
per_package: FxHashMap<String, PackageBuildData>,
38+
error: Option<String>,
3839
}
3940

4041
#[derive(Debug, Default, PartialEq, Eq, Clone)]
@@ -94,6 +95,19 @@ impl BuildDataResult {
9495
pub(crate) fn get(&self, workspace_root: &AbsPath) -> Option<&WorkspaceBuildData> {
9596
self.per_workspace.get(workspace_root)
9697
}
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+
}
97111
}
98112

99113
impl BuildDataConfig {
@@ -139,7 +153,7 @@ fn collect_from_workspace(
139153
}
140154
}
141155

142-
cmd.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null());
156+
cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());
143157

144158
let mut child = cmd.spawn().map(JodChild)?;
145159
let child_stdout = child.stdout.take().unwrap();
@@ -209,6 +223,15 @@ fn collect_from_workspace(
209223
}
210224
}
211225

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+
212235
Ok(res)
213236
}
214237

crates/rust-analyzer/src/reload.rs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,22 @@ impl GlobalState {
109109
quiescent: self.is_quiescent(),
110110
message: None,
111111
};
112+
113+
if let Some(error) = self.build_data_error() {
114+
status.health = lsp_ext::Health::Warning;
115+
status.message = Some(error)
116+
}
112117
if !self.config.cargo_autoreload()
113118
&& self.is_quiescent()
114119
&& self.fetch_workspaces_queue.op_requested()
115120
{
116121
status.health = lsp_ext::Health::Warning;
117122
status.message = Some("Workspace reload required".to_string())
118123
}
119-
if let Some(error) = self.loading_error() {
124+
125+
if let Some(error) = self.fetch_workspace_error() {
120126
status.health = lsp_ext::Health::Error;
121-
status.message = Some(format!("Workspace reload failed: {}", error))
127+
status.message = Some(error)
122128
}
123129

124130
if self.last_reported_status.as_ref() != Some(&status) {
@@ -217,14 +223,19 @@ impl GlobalState {
217223
let _p = profile::span("GlobalState::switch_workspaces");
218224
log::info!("will switch workspaces");
219225

220-
if let Some(error_message) = self.loading_error() {
226+
if let Some(error_message) = self.fetch_workspace_error() {
221227
log::error!("failed to switch workspaces: {}", error_message);
222228
self.show_message(lsp_types::MessageType::Error, error_message);
223229
if !self.workspaces.is_empty() {
224230
return;
225231
}
226232
}
227233

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+
228239
let workspaces = self
229240
.fetch_workspaces_queue
230241
.last_op_result()
@@ -343,22 +354,30 @@ impl GlobalState {
343354
log::info!("did switch workspaces");
344355
}
345356

346-
fn loading_error(&self) -> Option<String> {
347-
let mut message = None;
357+
fn fetch_workspace_error(&self) -> Option<String> {
358+
let mut buf = String::new();
348359

349360
for ws in self.fetch_workspaces_queue.last_op_result() {
350361
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);
362+
stdx::format_to!(buf, "rust-analyzer failed to load workspace: {:#}\n", err);
353363
}
354364
}
355365

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);
366+
if buf.is_empty() {
367+
return None;
359368
}
360369

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+
}
362381
}
363382

364383
fn reload_flycheck(&mut self) {

crates/stdx/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ where
178178
start..start + len
179179
}
180180

181+
#[repr(transparent)]
181182
pub struct JodChild(pub process::Child);
182183

183184
impl ops::Deref for JodChild {
@@ -200,6 +201,13 @@ impl Drop for JodChild {
200201
}
201202
}
202203

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+
203211
#[cfg(test)]
204212
mod tests {
205213
use super::*;

0 commit comments

Comments
 (0)