diff --git a/clippy_dev/src/lintcheck.rs b/clippy_dev/src/lintcheck.rs index 01f3c9a5bd8a..08f94f7ccb38 100644 --- a/clippy_dev/src/lintcheck.rs +++ b/clippy_dev/src/lintcheck.rs @@ -232,6 +232,7 @@ impl Crate { target_dir_index: &AtomicUsize, thread_limit: usize, total_crates_to_lint: usize, + fix: bool, ) -> Vec { // advance the atomic index by one let index = target_dir_index.fetch_add(1, Ordering::SeqCst); @@ -255,7 +256,18 @@ impl Crate { let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir"); - let mut args = vec!["--", "--message-format=json", "--", "--cap-lints=warn"]; + let mut args = if fix { + vec![ + "-Zunstable-options", + "--fix", + "-Zunstable-options", + "--allow-no-vcs", + "--", + "--cap-lints=warn", + ] + } else { + vec!["--", "--message-format=json", "--", "--cap-lints=warn"] + }; if let Some(options) = &self.options { for opt in options { @@ -285,6 +297,23 @@ impl Crate { ); }); let stdout = String::from_utf8_lossy(&all_output.stdout); + let stderr = String::from_utf8_lossy(&all_output.stderr); + + if fix { + if let Some(stderr) = stderr + .lines() + .find(|line| line.contains("failed to automatically apply fixes suggested by rustc to crate")) + { + let subcrate = &stderr[63..]; + println!( + "ERROR: failed to apply some suggetion to {} / to (sub)crate {}", + self.name, subcrate + ); + } + // fast path, we don't need the warnings anyway + return Vec::new(); + } + let output_lines = stdout.lines(); let warnings: Vec = output_lines .into_iter() @@ -292,6 +321,7 @@ impl Crate { .filter(|line| filter_clippy_warnings(&line)) .map(|json_msg| parse_json_message(json_msg, &self)) .collect(); + warnings } } @@ -304,6 +334,8 @@ struct LintcheckConfig { sources_toml_path: PathBuf, // we save the clippy lint results here lintcheck_results_path: PathBuf, + // whether to just run --fix and not collect all the warnings + fix: bool, } impl LintcheckConfig { @@ -345,11 +377,13 @@ impl LintcheckConfig { // no -j passed, use a single thread None => 1, }; + let fix: bool = clap_config.is_present("fix"); LintcheckConfig { max_jobs, sources_toml_path, lintcheck_results_path, + fix, } } } @@ -597,7 +631,7 @@ pub fn run(clap_config: &ArgMatches) { .into_iter() .map(|krate| krate.download_and_extract()) .filter(|krate| krate.name == only_one_crate) - .map(|krate| krate.run_clippy_lints(&cargo_clippy_path, &AtomicUsize::new(0), 1, 1)) + .map(|krate| krate.run_clippy_lints(&cargo_clippy_path, &AtomicUsize::new(0), 1, 1, config.fix)) .flatten() .collect() } else { @@ -621,7 +655,7 @@ pub fn run(clap_config: &ArgMatches) { crates .into_par_iter() .map(|krate| krate.download_and_extract()) - .map(|krate| krate.run_clippy_lints(&cargo_clippy_path, &counter, num_cpus, num_crates)) + .map(|krate| krate.run_clippy_lints(&cargo_clippy_path, &counter, num_cpus, num_crates, config.fix)) .flatten() .collect() } else { @@ -630,12 +664,17 @@ pub fn run(clap_config: &ArgMatches) { crates .into_iter() .map(|krate| krate.download_and_extract()) - .map(|krate| krate.run_clippy_lints(&cargo_clippy_path, &counter, 1, num_crates)) + .map(|krate| krate.run_clippy_lints(&cargo_clippy_path, &counter, 1, num_crates, config.fix)) .flatten() .collect() } }; + // if we are in --fix mode, don't change the log files, terminate here + if config.fix { + return; + } + // generate some stats let (stats_formatted, new_stats) = gather_stats(&clippy_warnings); diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 505d465760c5..33fef18d553a 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -77,7 +77,8 @@ fn get_clap_config<'a>() -> ArgMatches<'a> { .short("j") .long("jobs") .help("number of threads to use, 0 automatic choice"), - ); + ) + .arg(Arg::with_name("fix").help("runs cargo clippy --fix and checks if all suggestions apply")); let app = App::new("Clippy developer tooling") .subcommand(