]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/lintcheck/src/config.rs
Rollup merge of #104581 - notriddle:notriddle/js-iife-2, r=GuillaumeGomez
[rust.git] / src / tools / clippy / lintcheck / src / config.rs
1 use clap::{Arg, ArgAction, ArgMatches, Command};
2 use std::env;
3 use std::path::PathBuf;
4
5 fn get_clap_config() -> ArgMatches {
6     Command::new("lintcheck")
7         .about("run clippy on a set of crates and check output")
8         .args([
9             Arg::new("only")
10                 .action(ArgAction::Set)
11                 .value_name("CRATE")
12                 .long("only")
13                 .help("Only process a single crate of the list"),
14             Arg::new("crates-toml")
15                 .action(ArgAction::Set)
16                 .value_name("CRATES-SOURCES-TOML-PATH")
17                 .long("crates-toml")
18                 .help("Set the path for a crates.toml where lintcheck should read the sources from"),
19             Arg::new("threads")
20                 .action(ArgAction::Set)
21                 .value_name("N")
22                 .value_parser(clap::value_parser!(usize))
23                 .short('j')
24                 .long("jobs")
25                 .help("Number of threads to use, 0 automatic choice"),
26             Arg::new("fix")
27                 .long("fix")
28                 .help("Runs cargo clippy --fix and checks if all suggestions apply"),
29             Arg::new("filter")
30                 .long("filter")
31                 .action(ArgAction::Append)
32                 .value_name("clippy_lint_name")
33                 .help("Apply a filter to only collect specified lints, this also overrides `allow` attributes"),
34             Arg::new("markdown")
35                 .long("markdown")
36                 .help("Change the reports table to use markdown links"),
37             Arg::new("recursive")
38                 .long("--recursive")
39                 .help("Run clippy on the dependencies of crates specified in crates-toml")
40                 .conflicts_with("threads")
41                 .conflicts_with("fix"),
42         ])
43         .get_matches()
44 }
45
46 #[derive(Debug, Clone)]
47 pub(crate) struct LintcheckConfig {
48     /// max number of jobs to spawn (default 1)
49     pub max_jobs: usize,
50     /// we read the sources to check from here
51     pub sources_toml_path: PathBuf,
52     /// we save the clippy lint results here
53     pub lintcheck_results_path: PathBuf,
54     /// Check only a specified package
55     pub only: Option<String>,
56     /// whether to just run --fix and not collect all the warnings
57     pub fix: bool,
58     /// A list of lints that this lintcheck run should focus on
59     pub lint_filter: Vec<String>,
60     /// Indicate if the output should support markdown syntax
61     pub markdown: bool,
62     /// Run clippy on the dependencies of crates
63     pub recursive: bool,
64 }
65
66 impl LintcheckConfig {
67     pub fn new() -> Self {
68         let clap_config = get_clap_config();
69
70         // first, check if we got anything passed via the LINTCHECK_TOML env var,
71         // if not, ask clap if we got any value for --crates-toml  <foo>
72         // if not, use the default "lintcheck/lintcheck_crates.toml"
73         let sources_toml = env::var("LINTCHECK_TOML").unwrap_or_else(|_| {
74             clap_config
75                 .get_one::<String>("crates-toml")
76                 .map_or("lintcheck/lintcheck_crates.toml", |s| &**s)
77                 .into()
78         });
79
80         let markdown = clap_config.contains_id("markdown");
81         let sources_toml_path = PathBuf::from(sources_toml);
82
83         // for the path where we save the lint results, get the filename without extension (so for
84         // wasd.toml, use "wasd"...)
85         let filename: PathBuf = sources_toml_path.file_stem().unwrap().into();
86         let lintcheck_results_path = PathBuf::from(format!(
87             "lintcheck-logs/{}_logs.{}",
88             filename.display(),
89             if markdown { "md" } else { "txt" }
90         ));
91
92         // look at the --threads arg, if 0 is passed, ask rayon rayon how many threads it would spawn and
93         // use half of that for the physical core count
94         // by default use a single thread
95         let max_jobs = match clap_config.get_one::<usize>("threads") {
96             Some(&0) => {
97                 // automatic choice
98                 // Rayon seems to return thread count so half that for core count
99                 rayon::current_num_threads() / 2
100             },
101             Some(&threads) => threads,
102             // no -j passed, use a single thread
103             None => 1,
104         };
105
106         let lint_filter: Vec<String> = clap_config
107             .get_many::<String>("filter")
108             .map(|iter| {
109                 iter.map(|lint_name| {
110                     let mut filter = lint_name.replace('_', "-");
111                     if !filter.starts_with("clippy::") {
112                         filter.insert_str(0, "clippy::");
113                     }
114                     filter
115                 })
116                 .collect()
117             })
118             .unwrap_or_default();
119
120         LintcheckConfig {
121             max_jobs,
122             sources_toml_path,
123             lintcheck_results_path,
124             only: clap_config.get_one::<String>("only").map(String::from),
125             fix: clap_config.contains_id("fix"),
126             lint_filter,
127             markdown,
128             recursive: clap_config.contains_id("recursive"),
129         }
130     }
131 }