aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_flycheck/src/lib.rs89
-rw-r--r--crates/rust-analyzer/src/main_loop.rs2
2 files changed, 38 insertions, 53 deletions
diff --git a/crates/ra_flycheck/src/lib.rs b/crates/ra_flycheck/src/lib.rs
index ee09d8de3..13494a731 100644
--- a/crates/ra_flycheck/src/lib.rs
+++ b/crates/ra_flycheck/src/lib.rs
@@ -4,8 +4,8 @@
4mod conv; 4mod conv;
5 5
6use std::{ 6use std::{
7 env, error, fmt, 7 env,
8 io::{BufRead, BufReader}, 8 io::{self, BufRead, BufReader},
9 path::PathBuf, 9 path::PathBuf,
10 process::{Command, Stdio}, 10 process::{Command, Stdio},
11 time::Instant, 11 time::Instant,
@@ -23,10 +23,9 @@ use crate::conv::{map_rust_diagnostic_to_lsp, MappedRustDiagnostic};
23pub use crate::conv::url_from_path_with_drive_lowercasing; 23pub use crate::conv::url_from_path_with_drive_lowercasing;
24 24
25#[derive(Clone, Debug)] 25#[derive(Clone, Debug)]
26pub struct FlycheckConfig { 26pub enum FlycheckConfig {
27 pub command: String, 27 CargoCommand { command: String, all_targets: bool, extra_args: Vec<String> },
28 pub all_targets: bool, 28 CustomCommand { command: String, args: Vec<String> },
29 pub extra_args: Vec<String>,
30} 29}
31 30
32/// Flycheck wraps the shared state and communication machinery used for 31/// Flycheck wraps the shared state and communication machinery used for
@@ -215,18 +214,25 @@ impl FlycheckThread {
215 self.message_recv = never(); 214 self.message_recv = never();
216 self.check_process = None; 215 self.check_process = None;
217 216
218 let cmd = { 217 let mut cmd = match &self.config {
219 let mut cmd = Command::new(cargo_binary()); 218 FlycheckConfig::CargoCommand { command, all_targets, extra_args } => {
220 cmd.arg(&self.config.command); 219 let mut cmd = Command::new(cargo_binary());
221 cmd.args(&["--workspace", "--message-format=json", "--manifest-path"]); 220 cmd.arg(command);
222 cmd.arg(self.workspace_root.join("Cargo.toml")); 221 cmd.args(&["--workspace", "--message-format=json", "--manifest-path"]);
223 if self.config.all_targets { 222 cmd.arg(self.workspace_root.join("Cargo.toml"));
224 cmd.arg("--all-targets"); 223 if *all_targets {
224 cmd.arg("--all-targets");
225 }
226 cmd.args(extra_args);
227 cmd
228 }
229 FlycheckConfig::CustomCommand { command, args } => {
230 let mut cmd = Command::new(command);
231 cmd.args(args);
232 cmd
225 } 233 }
226 cmd.args(self.config.extra_args.iter());
227 cmd.current_dir(&self.workspace_root);
228 cmd
229 }; 234 };
235 cmd.current_dir(&self.workspace_root);
230 236
231 let (message_send, message_recv) = unbounded(); 237 let (message_send, message_recv) = unbounded();
232 self.message_recv = message_recv; 238 self.message_recv = message_recv;
@@ -273,27 +279,12 @@ enum CheckEvent {
273 End, 279 End,
274} 280}
275 281
276#[derive(Debug)]
277pub struct CargoError(String);
278
279impl fmt::Display for CargoError {
280 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
281 write!(f, "Cargo failed: {}", self.0)
282 }
283}
284impl error::Error for CargoError {}
285
286fn run_cargo( 282fn run_cargo(
287 mut command: Command, 283 mut command: Command,
288 on_message: &mut dyn FnMut(cargo_metadata::Message) -> bool, 284 on_message: &mut dyn FnMut(cargo_metadata::Message) -> bool,
289) -> Result<(), CargoError> { 285) -> io::Result<()> {
290 dbg!(&command); 286 let mut child =
291 let mut child = command 287 command.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null()).spawn()?;
292 .stdout(Stdio::piped())
293 .stderr(Stdio::null())
294 .stdin(Stdio::null())
295 .spawn()
296 .expect("couldn't launch cargo");
297 288
298 // We manually read a line at a time, instead of using serde's 289 // We manually read a line at a time, instead of using serde's
299 // stream deserializers, because the deserializer cannot recover 290 // stream deserializers, because the deserializer cannot recover
@@ -307,13 +298,7 @@ fn run_cargo(
307 let mut read_at_least_one_message = false; 298 let mut read_at_least_one_message = false;
308 299
309 for line in stdout.lines() { 300 for line in stdout.lines() {
310 let line = match line { 301 let line = line?;
311 Ok(line) => line,
312 Err(err) => {
313 log::error!("Couldn't read line from cargo: {}", err);
314 continue;
315 }
316 };
317 302
318 let message = serde_json::from_str::<cargo_metadata::Message>(&line); 303 let message = serde_json::from_str::<cargo_metadata::Message>(&line);
319 let message = match message { 304 let message = match message {
@@ -334,20 +319,20 @@ fn run_cargo(
334 // It is okay to ignore the result, as it only errors if the process is already dead 319 // It is okay to ignore the result, as it only errors if the process is already dead
335 let _ = child.kill(); 320 let _ = child.kill();
336 321
337 let err_msg = match child.wait() { 322 let exit_status = child.wait()?;
338 Ok(exit_code) if !exit_code.success() && !read_at_least_one_message => { 323 if !exit_status.success() && !read_at_least_one_message {
339 // FIXME: Read the stderr to display the reason, see `read2()` reference in PR comment: 324 // FIXME: Read the stderr to display the reason, see `read2()` reference in PR comment:
340 // https://github.com/rust-analyzer/rust-analyzer/pull/3632#discussion_r395605298 325 // https://github.com/rust-analyzer/rust-analyzer/pull/3632#discussion_r395605298
326 return Err(io::Error::new(
327 io::ErrorKind::Other,
341 format!( 328 format!(
342 "the command produced no valid metadata (exit code: {:?}): {:?}", 329 "the command produced no valid metadata (exit code: {:?}): {:?}",
343 exit_code, command 330 exit_status, command
344 ) 331 ),
345 } 332 ));
346 Err(err) => format!("io error: {:?}", err), 333 }
347 Ok(_) => return Ok(()),
348 };
349 334
350 Err(CargoError(err_msg)) 335 Ok(())
351} 336}
352 337
353fn cargo_binary() -> String { 338fn cargo_binary() -> String {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 06122ed95..a89ea86ea 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -102,7 +102,7 @@ fn get_config(
102 max_length: config.inlay_hints_max_length, 102 max_length: config.inlay_hints_max_length,
103 }, 103 },
104 check: if config.cargo_watch_enable { 104 check: if config.cargo_watch_enable {
105 Some(FlycheckConfig { 105 Some(FlycheckConfig::CargoCommand {
106 command: config.cargo_watch_command.clone(), 106 command: config.cargo_watch_command.clone(),
107 all_targets: config.cargo_watch_all_targets, 107 all_targets: config.cargo_watch_all_targets,
108 extra_args: config.cargo_watch_args.clone(), 108 extra_args: config.cargo_watch_args.clone(),