X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmain.rs;h=6bd4123ddeb45d92917f1dd043fa9d09ecf208de;hb=a9e9b7f9b2ad52035fe7b57bb0fc8ba62d649c33;hp=057a585e3d7dbf4b389c95dd2eca103850ac63d1;hpb=976bbe822a8abc438240cbf952550e383cb233ee;p=rust.git diff --git a/src/main.rs b/src/main.rs index 057a585e3d7..6bd4123ddeb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,12 @@ -// error-pattern:yummy -#![feature(box_syntax)] -#![feature(rustc_private)] -#![allow(unknown_lints, missing_docs_in_private_items)] +#![cfg_attr(feature = "deny-warnings", deny(warnings))] +// warn on lints, that are included in `rust-lang/rust`s bootstrap +#![warn(rust_2018_idioms, unused_lifetimes)] + +use rustc_tools_util::VersionInfo; +use std::env; +use std::ffi::OsString; +use std::path::PathBuf; +use std::process::{self, Command}; const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code. @@ -22,85 +27,131 @@ -D --deny OPT Set lint denied -F --forbid OPT Set lint forbidden -The feature `cargo-clippy` is automatically defined for convenience. You can use -it to allow or deny lints from the code, eg.: +You can use tool lints to allow or deny lints from your code, eg.: - #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))] + #[allow(clippy::needless_lifetimes)] "#; -#[allow(print_stdout)] fn show_help() { println!("{}", CARGO_CLIPPY_HELP); } -#[allow(print_stdout)] fn show_version() { - println!(env!("CARGO_PKG_VERSION")); + let version_info = rustc_tools_util::get_version_info!(); + println!("{}", version_info); } pub fn main() { // Check for version and help flags even when invoked as 'cargo-clippy' - if std::env::args().any(|a| a == "--help" || a == "-h") { + if env::args().any(|a| a == "--help" || a == "-h") { show_help(); return; } - if std::env::args().any(|a| a == "--version" || a == "-V") { + + if env::args().any(|a| a == "--version" || a == "-V") { show_version(); return; } - if let Err(code) = process(std::env::args().skip(2)) { - std::process::exit(code); + if let Err(code) = process(env::args().skip(2)) { + process::exit(code); } } -fn process(mut old_args: I) -> Result<(), i32> -where - I: Iterator, -{ - let mut args = vec!["check".to_owned()]; +struct ClippyCmd { + cargo_subcommand: &'static str, + args: Vec, + clippy_args: Vec, +} + +impl ClippyCmd { + fn new(mut old_args: I) -> Self + where + I: Iterator, + { + let mut cargo_subcommand = "check"; + let mut args = vec![]; + + for arg in old_args.by_ref() { + match arg.as_str() { + "--fix" => { + cargo_subcommand = "fix"; + continue; + }, + "--" => break, + _ => {}, + } + + args.push(arg); + } + + let mut clippy_args: Vec = old_args.collect(); + if cargo_subcommand == "fix" && !clippy_args.iter().any(|arg| arg == "--no-deps") { + clippy_args.push("--no-deps".into()); + } - let mut found_dashes = false; - for arg in old_args.by_ref() { - found_dashes |= arg == "--"; - if found_dashes { - break; + ClippyCmd { + cargo_subcommand, + args, + clippy_args, } - args.push(arg); } - let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect(); + fn path() -> PathBuf { + let mut path = env::current_exe() + .expect("current executable path invalid") + .with_file_name("clippy-driver"); + + if cfg!(windows) { + path.set_extension("exe"); + } - let mut path = std::env::current_exe() - .expect("current executable path invalid") - .with_file_name("clippy-driver"); - if cfg!(windows) { - path.set_extension("exe"); + path } - let target_dir = std::env::var_os("CLIPPY_DOGFOOD") - .map(|_| { - std::env::var_os("CARGO_MANIFEST_DIR").map_or_else( - || { - let mut fallback = std::ffi::OsString::new(); - fallback.push("clippy_dogfood"); - fallback - }, - |d| { - std::path::PathBuf::from(d) - .join("target") - .join("dogfood") - .into_os_string() - }, - ) - }) - .map(|p| ("CARGO_TARGET_DIR", p)); - - let exit_status = std::process::Command::new("cargo") - .args(&args) - .env("RUSTC_WRAPPER", path) - .env("CLIPPY_ARGS", clippy_args) - .envs(target_dir) + fn target_dir() -> Option<(&'static str, OsString)> { + env::var_os("CLIPPY_DOGFOOD") + .map(|_| { + env::var_os("CARGO_MANIFEST_DIR").map_or_else( + || std::ffi::OsString::from("clippy_dogfood"), + |d| { + std::path::PathBuf::from(d) + .join("target") + .join("dogfood") + .into_os_string() + }, + ) + }) + .map(|p| ("CARGO_TARGET_DIR", p)) + } + + fn into_std_cmd(self) -> Command { + let mut cmd = Command::new("cargo"); + let clippy_args: String = self + .clippy_args + .iter() + .map(|arg| format!("{}__CLIPPY_HACKERY__", arg)) + .collect(); + + cmd.env("RUSTC_WORKSPACE_WRAPPER", Self::path()) + .envs(ClippyCmd::target_dir()) + .env("CLIPPY_ARGS", clippy_args) + .arg(self.cargo_subcommand) + .args(&self.args); + + cmd + } +} + +fn process(old_args: I) -> Result<(), i32> +where + I: Iterator, +{ + let cmd = ClippyCmd::new(old_args); + + let mut cmd = cmd.into_std_cmd(); + + let exit_status = cmd .spawn() .expect("could not run cargo") .wait() @@ -112,3 +163,39 @@ fn process(mut old_args: I) -> Result<(), i32> Err(exit_status.code().unwrap_or(-1)) } } + +#[cfg(test)] +mod tests { + use super::ClippyCmd; + + #[test] + fn fix() { + let args = "cargo clippy --fix".split_whitespace().map(ToString::to_string); + let cmd = ClippyCmd::new(args); + assert_eq!("fix", cmd.cargo_subcommand); + assert!(!cmd.args.iter().any(|arg| arg.ends_with("unstable-options"))); + } + + #[test] + fn fix_implies_no_deps() { + let args = "cargo clippy --fix".split_whitespace().map(ToString::to_string); + let cmd = ClippyCmd::new(args); + assert!(cmd.clippy_args.iter().any(|arg| arg == "--no-deps")); + } + + #[test] + fn no_deps_not_duplicated_with_fix() { + let args = "cargo clippy --fix -- --no-deps" + .split_whitespace() + .map(ToString::to_string); + let cmd = ClippyCmd::new(args); + assert_eq!(cmd.clippy_args.iter().filter(|arg| *arg == "--no-deps").count(), 1); + } + + #[test] + fn check() { + let args = "cargo clippy".split_whitespace().map(ToString::to_string); + let cmd = ClippyCmd::new(args); + assert_eq!("check", cmd.cargo_subcommand); + } +}