diff --git a/crates/rust-analyzer/src/command.rs b/crates/rust-analyzer/src/command.rs index d6c80c399ba2..674e8623b2d0 100644 --- a/crates/rust-analyzer/src/command.rs +++ b/crates/rust-analyzer/src/command.rs @@ -3,13 +3,15 @@ use std::{ ffi::OsString, - fmt, io, + fmt, + io::{self, BufWriter, Write}, marker::PhantomData, path::PathBuf, process::{ChildStderr, ChildStdout, Command, Stdio}, }; use crossbeam_channel::Sender; +use paths::Utf8PathBuf; use process_wrap::std::{StdChildWrapper, StdCommandWrap}; use stdx::process::streaming_output; @@ -40,7 +42,7 @@ impl CargoActor { } impl CargoActor { - fn run(self) -> io::Result<(bool, String)> { + fn run(self, outfile: Option) -> io::Result<(bool, String)> { // We manually read a line at a time, instead of using serde's // stream deserializers, because the deserializer cannot recover // from an error, resulting in it getting stuck, because we try to @@ -50,6 +52,15 @@ impl CargoActor { // simply skip a line if it doesn't parse, which just ignores any // erroneous output. + let mut stdout = outfile.as_ref().and_then(|path| { + _ = std::fs::create_dir_all(path); + Some(BufWriter::new(std::fs::File::create(path.join("stdout")).ok()?)) + }); + let mut stderr = outfile.as_ref().and_then(|path| { + _ = std::fs::create_dir_all(path); + Some(BufWriter::new(std::fs::File::create(path.join("stderr")).ok()?)) + }); + let mut stdout_errors = String::new(); let mut stderr_errors = String::new(); let mut read_at_least_one_stdout_message = false; @@ -67,11 +78,19 @@ impl CargoActor { self.stdout, self.stderr, &mut |line| { + if let Some(stdout) = &mut stdout { + _ = stdout.write_all(line.as_bytes()); + _ = stdout.write_all(b"\n"); + } if process_line(line, &mut stdout_errors) { read_at_least_one_stdout_message = true; } }, &mut |line| { + if let Some(stderr) = &mut stderr { + _ = stderr.write_all(line.as_bytes()); + _ = stderr.write_all(b"\n"); + } if process_line(line, &mut stderr_errors) { read_at_least_one_stderr_message = true; } @@ -130,6 +149,7 @@ impl CommandHandle { mut command: Command, parser: impl CargoParser, sender: Sender, + out_file: Option, ) -> std::io::Result { command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null()); @@ -150,7 +170,7 @@ impl CommandHandle { let actor = CargoActor::::new(parser, sender, stdout, stderr); let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "CommandHandle") - .spawn(move || actor.run()) + .spawn(move || actor.run(out_file)) .expect("failed to spawn thread"); Ok(CommandHandle { program, arguments, current_dir, child, thread, _phantom: PhantomData }) } diff --git a/crates/rust-analyzer/src/discover.rs b/crates/rust-analyzer/src/discover.rs index 24c433610f1a..4ec0c075dd5b 100644 --- a/crates/rust-analyzer/src/discover.rs +++ b/crates/rust-analyzer/src/discover.rs @@ -67,7 +67,7 @@ impl DiscoverCommand { cmd.args(args); Ok(DiscoverHandle { - _handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone())?, + _handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone(), None)?, span: info_span!("discover_command").entered(), }) } diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs index cded34be14a2..b545106fe1cf 100644 --- a/crates/rust-analyzer/src/flycheck.rs +++ b/crates/rust-analyzer/src/flycheck.rs @@ -423,7 +423,21 @@ impl FlycheckActor { tracing::debug!(?command, "will restart flycheck"); let (sender, receiver) = unbounded(); - match CommandHandle::spawn(command, CargoCheckParser, sender) { + match CommandHandle::spawn( + command, + CargoCheckParser, + sender, + match &self.config { + FlycheckConfig::CargoCommand { options, .. } => Some( + options + .target_dir + .as_deref() + .unwrap_or("target".as_ref()) + .join(format!("rust-analyzer/flycheck{}", self.id)), + ), + _ => None, + }, + ) { Ok(command_handle) => { tracing::debug!(command = formatted_command, "did restart flycheck"); self.command_handle = Some(command_handle); @@ -622,6 +636,7 @@ impl FlycheckActor { { cmd.env("RUSTUP_TOOLCHAIN", AsRef::::as_ref(sysroot_root)); } + cmd.env("CARGO_LOG", "cargo::core::compiler::fingerprint=info"); cmd.arg(command); match scope { diff --git a/crates/rust-analyzer/src/test_runner.rs b/crates/rust-analyzer/src/test_runner.rs index e7528dbc9396..0c8658c75df0 100644 --- a/crates/rust-analyzer/src/test_runner.rs +++ b/crates/rust-analyzer/src/test_runner.rs @@ -136,7 +136,12 @@ impl CargoTestHandle { } Ok(Self { - _handle: CommandHandle::spawn(cmd, CargoTestOutputParser::new(&test_target), sender)?, + _handle: CommandHandle::spawn( + cmd, + CargoTestOutputParser::new(&test_target), + sender, + None, + )?, }) } }