Skip to content

Commit 1765c5d

Browse files
committed
Auto merge of rust-lang#5363 - yaahc:clippy-fix, r=phansch,flip1995
add --fix support to `cargo-clippy` Prior to this we had started work on integrating clippy as a subcommand directly into cargo in the form of `cargo clippy-preview` and `cargo fix --clippy`. In the course of that work it was decided that the best approach would be to strictly add the features clippy needed to cargo in order to insert `clippy-driver` only for workspace crates. This was accomplished by adding a `RUSTC_WORKSPACE_WRAPPER` env variable to cargo that will override the normal `RUSTC_WRAPPER` when both are present and the current crate is a workspace crate. This change adds support to clippy to use this by setting the `RUSTC_WORKSPACE_WRAPPER` env variable instead `RUSTC_WRAPPER` and by detecting `--fix` as an arg and swapping out the `check` cargo command for `fix` when it is present. WIP, here are the current issues that I still need to resolve - [x] Detect if we're running on nightly rust - [x] Set `RUSTC_WORKSPACE_WRAPPER` on nightly, and `RUSTC_WRAPPER` on stable - [x] Error out on stable when `--fix` is specified, because stable currently hasn't landed the PR for `RUSTC_WORKSPACE_WRAPPER` so if we set this it just runs check and silently fails - [ ] Update the help text - [ ] The current plan is to shell out to `cargo check --help` and then postprocess the output to mention clippy instead of check where appropriate and to add the extra info about `--fix` and the `-- -A lint` options. - [x] tests? changelog: add `--fix` arg to `cargo-clippy`
2 parents 6651c1b + 5cfb9ec commit 1765c5d

File tree

1 file changed

+149
-42
lines changed

1 file changed

+149
-42
lines changed

src/main.rs

+149-42
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
22

33
use rustc_tools_util::VersionInfo;
4+
use std::env;
5+
use std::ffi::OsString;
6+
use std::path::PathBuf;
7+
use std::process::{self, Command};
48

59
const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.
610
@@ -37,68 +41,130 @@ fn show_version() {
3741

3842
pub fn main() {
3943
// Check for version and help flags even when invoked as 'cargo-clippy'
40-
if std::env::args().any(|a| a == "--help" || a == "-h") {
44+
if env::args().any(|a| a == "--help" || a == "-h") {
4145
show_help();
4246
return;
4347
}
4448

45-
if std::env::args().any(|a| a == "--version" || a == "-V") {
49+
if env::args().any(|a| a == "--version" || a == "-V") {
4650
show_version();
4751
return;
4852
}
4953

50-
if let Err(code) = process(std::env::args().skip(2)) {
51-
std::process::exit(code);
54+
if let Err(code) = process(env::args().skip(2)) {
55+
process::exit(code);
5256
}
5357
}
5458

55-
fn process<I>(mut old_args: I) -> Result<(), i32>
56-
where
57-
I: Iterator<Item = String>,
58-
{
59-
let mut args = vec!["check".to_owned()];
59+
struct ClippyCmd {
60+
unstable_options: bool,
61+
cargo_subcommand: &'static str,
62+
args: Vec<String>,
63+
clippy_args: String,
64+
}
65+
66+
impl ClippyCmd {
67+
fn new<I>(mut old_args: I) -> Self
68+
where
69+
I: Iterator<Item = String>,
70+
{
71+
let mut cargo_subcommand = "check";
72+
let mut unstable_options = false;
73+
let mut args = vec![];
74+
75+
for arg in old_args.by_ref() {
76+
match arg.as_str() {
77+
"--fix" => {
78+
cargo_subcommand = "fix";
79+
continue;
80+
},
81+
"--" => break,
82+
// Cover -Zunstable-options and -Z unstable-options
83+
s if s.ends_with("unstable-options") => unstable_options = true,
84+
_ => {},
85+
}
86+
87+
args.push(arg);
88+
}
89+
90+
if cargo_subcommand == "fix" && !unstable_options {
91+
panic!("Usage of `--fix` requires `-Z unstable-options`");
92+
}
6093

61-
for arg in old_args.by_ref() {
62-
if arg == "--" {
63-
break;
94+
// Run the dogfood tests directly on nightly cargo. This is required due
95+
// to a bug in rustup.rs when running cargo on custom toolchains. See issue #3118.
96+
if env::var_os("CLIPPY_DOGFOOD").is_some() && cfg!(windows) {
97+
args.insert(0, "+nightly".to_string());
98+
}
99+
100+
let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect();
101+
102+
ClippyCmd {
103+
unstable_options,
104+
cargo_subcommand,
105+
args,
106+
clippy_args,
107+
}
108+
}
109+
110+
fn path_env(&self) -> &'static str {
111+
if self.unstable_options {
112+
"RUSTC_WORKSPACE_WRAPPER"
113+
} else {
114+
"RUSTC_WRAPPER"
64115
}
65-
args.push(arg);
66116
}
67117

68-
let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect();
118+
fn path() -> PathBuf {
119+
let mut path = env::current_exe()
120+
.expect("current executable path invalid")
121+
.with_file_name("clippy-driver");
122+
123+
if cfg!(windows) {
124+
path.set_extension("exe");
125+
}
69126

70-
let mut path = std::env::current_exe()
71-
.expect("current executable path invalid")
72-
.with_file_name("clippy-driver");
73-
if cfg!(windows) {
74-
path.set_extension("exe");
127+
path
75128
}
76129

77-
let target_dir = std::env::var_os("CLIPPY_DOGFOOD")
78-
.map(|_| {
79-
std::env::var_os("CARGO_MANIFEST_DIR").map_or_else(
80-
|| std::ffi::OsString::from("clippy_dogfood"),
81-
|d| {
82-
std::path::PathBuf::from(d)
83-
.join("target")
84-
.join("dogfood")
85-
.into_os_string()
86-
},
87-
)
88-
})
89-
.map(|p| ("CARGO_TARGET_DIR", p));
90-
91-
// Run the dogfood tests directly on nightly cargo. This is required due
92-
// to a bug in rustup.rs when running cargo on custom toolchains. See issue #3118.
93-
if std::env::var_os("CLIPPY_DOGFOOD").is_some() && cfg!(windows) {
94-
args.insert(0, "+nightly".to_string());
130+
fn target_dir() -> Option<(&'static str, OsString)> {
131+
env::var_os("CLIPPY_DOGFOOD")
132+
.map(|_| {
133+
env::var_os("CARGO_MANIFEST_DIR").map_or_else(
134+
|| std::ffi::OsString::from("clippy_dogfood"),
135+
|d| {
136+
std::path::PathBuf::from(d)
137+
.join("target")
138+
.join("dogfood")
139+
.into_os_string()
140+
},
141+
)
142+
})
143+
.map(|p| ("CARGO_TARGET_DIR", p))
95144
}
96145

97-
let exit_status = std::process::Command::new("cargo")
98-
.args(&args)
99-
.env("RUSTC_WRAPPER", path)
100-
.env("CLIPPY_ARGS", clippy_args)
101-
.envs(target_dir)
146+
fn into_std_cmd(self) -> Command {
147+
let mut cmd = Command::new("cargo");
148+
149+
cmd.env(self.path_env(), Self::path())
150+
.envs(ClippyCmd::target_dir())
151+
.env("CLIPPY_ARGS", self.clippy_args)
152+
.arg(self.cargo_subcommand)
153+
.args(&self.args);
154+
155+
cmd
156+
}
157+
}
158+
159+
fn process<I>(old_args: I) -> Result<(), i32>
160+
where
161+
I: Iterator<Item = String>,
162+
{
163+
let cmd = ClippyCmd::new(old_args);
164+
165+
let mut cmd = cmd.into_std_cmd();
166+
167+
let exit_status = cmd
102168
.spawn()
103169
.expect("could not run cargo")
104170
.wait()
@@ -110,3 +176,44 @@ where
110176
Err(exit_status.code().unwrap_or(-1))
111177
}
112178
}
179+
180+
#[cfg(test)]
181+
mod tests {
182+
use super::ClippyCmd;
183+
184+
#[test]
185+
#[should_panic]
186+
fn fix_without_unstable() {
187+
let args = "cargo clippy --fix".split_whitespace().map(ToString::to_string);
188+
let _ = ClippyCmd::new(args);
189+
}
190+
191+
#[test]
192+
fn fix_unstable() {
193+
let args = "cargo clippy --fix -Zunstable-options"
194+
.split_whitespace()
195+
.map(ToString::to_string);
196+
let cmd = ClippyCmd::new(args);
197+
assert_eq!("fix", cmd.cargo_subcommand);
198+
assert_eq!("RUSTC_WORKSPACE_WRAPPER", cmd.path_env());
199+
assert!(cmd.args.iter().any(|arg| arg.ends_with("unstable-options")));
200+
}
201+
202+
#[test]
203+
fn check() {
204+
let args = "cargo clippy".split_whitespace().map(ToString::to_string);
205+
let cmd = ClippyCmd::new(args);
206+
assert_eq!("check", cmd.cargo_subcommand);
207+
assert_eq!("RUSTC_WRAPPER", cmd.path_env());
208+
}
209+
210+
#[test]
211+
fn check_unstable() {
212+
let args = "cargo clippy -Zunstable-options"
213+
.split_whitespace()
214+
.map(ToString::to_string);
215+
let cmd = ClippyCmd::new(args);
216+
assert_eq!("check", cmd.cargo_subcommand);
217+
assert_eq!("RUSTC_WORKSPACE_WRAPPER", cmd.path_env());
218+
}
219+
}

0 commit comments

Comments
 (0)