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