//! We setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself during the //! initial `cargo check`. That way, we avoid checking the actual project, and //! only build proc macros and build.rs. //! //! Code taken from IntelliJ :0) //! https://github.com/intellij-rust/intellij-rust/blob/master/native-helper/src/main.rs use std::{ ffi::OsString, io, process::{Command, Stdio}, }; /// ExitCode/ExitStatus are impossible to create :(. pub(crate) struct ExitCode(pub(crate) Option); pub(crate) fn run_rustc_skipping_cargo_checking( rustc_executable: OsString, args: Vec, ) -> io::Result { let is_cargo_check = args.iter().any(|arg| { let arg = arg.to_string_lossy(); // `cargo check` invokes `rustc` with `--emit=metadata` argument. // // https://doc.rust-lang.org/rustc/command-line-arguments.html#--emit-specifies-the-types-of-output-files-to-generate // link — Generates the crates specified by --crate-type. The default // output filenames depend on the crate type and platform. This // is the default if --emit is not specified. // metadata — Generates a file containing metadata about the crate. // The default output filename is CRATE_NAME.rmeta. arg.starts_with("--emit=") && arg.contains("metadata") && !arg.contains("link") }); if is_cargo_check { return Ok(ExitCode(Some(0))); } run_rustc(rustc_executable, args) } fn run_rustc(rustc_executable: OsString, args: Vec) -> io::Result { let mut child = Command::new(rustc_executable) .args(args) .stdin(Stdio::inherit()) .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) .spawn()?; Ok(ExitCode(child.wait()?.code())) }