1 use crate::recursive::{deserialize_line, serialize_line, DriverInfo};
2
3 use std::io::{self, BufReader, Write};
4 use std::net::TcpStream;
5 use std::process::{self, Command, Stdio};
6 use std::{env, mem};
7
8 /// 1. Sends [`DriverInfo`] to the [`crate::recursive::LintcheckServer`] running on `addr`
9 /// 2. Receives [bool] from the server, if `false` returns `None`
10 /// 3. Otherwise sends the stderr of running `clippy-driver` to the server
run_clippy(addr: &str) -> Option<i32>11 fn run_clippy(addr: &str) -> Option<i32> {
12 let driver_info = DriverInfo {
13 package_name: env::var("CARGO_PKG_NAME").ok()?,
14 crate_name: env::var("CARGO_CRATE_NAME").ok()?,
15 version: env::var("CARGO_PKG_VERSION").ok()?,
16 };
17
18 let mut stream = BufReader::new(TcpStream::connect(addr).unwrap());
19
20 serialize_line(&driver_info, stream.get_mut());
21
22 let should_run = deserialize_line::<bool, _>(&mut stream);
23 if !should_run {
24 return None;
25 }
26
27 // Remove --cap-lints allow so that clippy runs and lints are emitted
28 let mut include_next = true;
29 let args = env::args().skip(1).filter(|arg| match arg.as_str() {
30 "--cap-lints=allow" => false,
31 "--cap-lints" => {
32 include_next = false;
33 false
34 },
35 _ => mem::replace(&mut include_next, true),
36 });
37
38 let output = Command::new(env::var("CLIPPY_DRIVER").expect("missing env CLIPPY_DRIVER"))
39 .args(args)
40 .stdout(Stdio::inherit())
41 .output()
42 .expect("failed to run clippy-driver");
43
44 stream
45 .get_mut()
46 .write_all(&output.stderr)
47 .unwrap_or_else(|e| panic!("{e:?} in {driver_info:?}"));
48
49 match output.status.code() {
50 Some(0) => Some(0),
51 code => {
52 io::stderr().write_all(&output.stderr).unwrap();
53 Some(code.expect("killed by signal"))
54 },
55 }
56 }
57
drive(addr: &str)58 pub fn drive(addr: &str) {
59 process::exit(run_clippy(addr).unwrap_or_else(|| {
60 Command::new("rustc")
61 .args(env::args_os().skip(2))
62 .status()
63 .unwrap()
64 .code()
65 .unwrap()
66 }))
67 }
68