Skip to content

Commit fc77d91

Browse files
committed
Add cargo lintcheck --recursive to check dependencies of crates
1 parent 826a893 commit fc77d91

File tree

7 files changed

+339
-55
lines changed

7 files changed

+339
-55
lines changed

lintcheck/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ publish = false
1212
[dependencies]
1313
cargo_metadata = "0.14"
1414
clap = "3.2"
15+
crossbeam-channel = "0.5.6"
1516
flate2 = "1.0"
1617
rayon = "1.5.1"
1718
serde = { version = "1.0", features = ["derive"] }
19+
serde_json = "1.0.85"
1820
tar = "0.4"
1921
toml = "0.5"
2022
ureq = "2.2"

lintcheck/README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,27 @@ is checked.
6969
is explicitly specified in the options.
7070

7171
### Fix mode
72-
You can run `./lintcheck/target/debug/lintcheck --fix` which will run Clippy with `--fix` and
72+
You can run `cargo lintcheck --fix` which will run Clippy with `--fix` and
7373
print a warning if Clippy's suggestions fail to apply (if the resulting code does not build).
7474
This lets us spot bad suggestions or false positives automatically in some cases.
7575

7676
Please note that the target dir should be cleaned afterwards since clippy will modify
7777
the downloaded sources which can lead to unexpected results when running lintcheck again afterwards.
78+
79+
### Recursive mode
80+
You can run `cargo lintcheck --recursive` to also run Clippy on the dependencies
81+
of the crates listed in the crates source `.toml`. e.g. adding `rand 0.8.5`
82+
would also lint `rand_core`, `rand_chacha`, etc.
83+
84+
Particularly slow crates in the dependency graph can be ignored using
85+
`recursive.ignore`:
86+
87+
```toml
88+
[crates]
89+
cargo = {name = "cargo", versions = ['0.64.0']}
90+
91+
[recursive]
92+
ignore = [
93+
"unicode-normalization",
94+
]
95+
```

lintcheck/lintcheck_crates.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,11 @@ cfg-expr = {name = "cfg-expr", versions = ['0.7.1']}
3333
puffin = {name = "puffin", git_url = "https://github.com/EmbarkStudios/puffin", git_hash = "02dd4a3"}
3434
rpmalloc = {name = "rpmalloc", versions = ['0.2.0']}
3535
tame-oidc = {name = "tame-oidc", versions = ['0.1.0']}
36+
37+
[recursive]
38+
ignore = [
39+
# Takes ~30s to lint
40+
"combine",
41+
# Has 1.2 million `clippy::match_same_arms`s
42+
"unicode-normalization",
43+
]

lintcheck/src/config.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,16 @@ fn get_clap_config() -> ArgMatches {
3434
Arg::new("markdown")
3535
.long("markdown")
3636
.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"),
3742
])
3843
.get_matches()
3944
}
4045

41-
#[derive(Debug)]
46+
#[derive(Debug, Clone)]
4247
pub(crate) struct LintcheckConfig {
4348
/// max number of jobs to spawn (default 1)
4449
pub max_jobs: usize,
@@ -54,6 +59,8 @@ pub(crate) struct LintcheckConfig {
5459
pub lint_filter: Vec<String>,
5560
/// Indicate if the output should support markdown syntax
5661
pub markdown: bool,
62+
/// Run clippy on the dependencies of crates
63+
pub recursive: bool,
5764
}
5865

5966
impl LintcheckConfig {
@@ -119,6 +126,7 @@ impl LintcheckConfig {
119126
fix: clap_config.contains_id("fix"),
120127
lint_filter,
121128
markdown,
129+
recursive: clap_config.contains_id("recursive"),
122130
}
123131
}
124132
}

lintcheck/src/driver.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use crate::recursive::{deserialize_line, serialize_line, DriverInfo};
2+
3+
use std::io::{self, BufReader, Write};
4+
use std::net::TcpStream;
5+
use std::process::{self, Command, Stdio};
6+
use std::{env, mem};
7+
8+
/// 1. Sends [DriverInfo] to the [crate::recursive::LintcheckServer] running on `addr`
9+
/// 2. Receives [bool] from the server, if `false` returns `None`
10+
/// 3. Otherwise sends the stderr of running `clippy-driver` to the server
11+
fn run_clippy(addr: &str) -> Option<i32> {
12+
let driver_info = DriverInfo {
13+
package_name: env::var("CARGO_PKG_NAME").ok()?,
14+
crate_name: env::var("CARGO_CRATE_NAME").ok()?,
15+
version: env::var("CARGO_PKG_VERSION").ok()?,
16+
};
17+
18+
let mut stream = BufReader::new(TcpStream::connect(addr).unwrap());
19+
20+
serialize_line(&driver_info, stream.get_mut());
21+
22+
let should_run = deserialize_line::<bool, _>(&mut stream);
23+
if !should_run {
24+
return None;
25+
}
26+
27+
// Remove --cap-lints allow so that clippy runs and lints are emitted
28+
let mut include_next = true;
29+
let args = env::args().skip(1).filter(|arg| match arg.as_str() {
30+
"--cap-lints=allow" => false,
31+
"--cap-lints" => {
32+
include_next = false;
33+
false
34+
},
35+
_ => mem::replace(&mut include_next, true),
36+
});
37+
38+
let output = Command::new(env::var("CLIPPY_DRIVER").expect("missing env CLIPPY_DRIVER"))
39+
.args(args)
40+
.stdout(Stdio::inherit())
41+
.output()
42+
.expect("failed to run clippy-driver");
43+
44+
stream
45+
.get_mut()
46+
.write_all(&output.stderr)
47+
.unwrap_or_else(|e| panic!("{e:?} in {driver_info:?}"));
48+
49+
match output.status.code() {
50+
Some(0) => Some(0),
51+
code => {
52+
io::stderr().write_all(&output.stderr).unwrap();
53+
Some(code.expect("killed by signal"))
54+
},
55+
}
56+
}
57+
58+
pub fn drive(addr: &str) {
59+
process::exit(run_clippy(addr).unwrap_or_else(|| {
60+
Command::new("rustc")
61+
.args(env::args_os().skip(2))
62+
.status()
63+
.unwrap()
64+
.code()
65+
.unwrap()
66+
}))
67+
}

0 commit comments

Comments
 (0)