Skip to content

Commit 01ea624

Browse files
committed
Auto merge of #8607 - Alexendoo:cargo-dev-lint-dir, r=flip1995,giraffate
Allow running `cargo dev lint` on a package directory Allows you run the local clippy in a specified directory, e.g. allowing ```sh # Lint a ui-cargo test cargo dev lint tests/ui-cargo/wildcard_dependencies/fail # Lint some other project cargo dev lint ~/my-project ``` The `target` directory is set to a tempdir which isn't ideal for medium/large projects as it would be compiled from scratch. This is to avoid cached clippy messages where you `cargo dev lint dir`, change something in clippy, and run `cargo dev lint dir` again changelog: Dev: `cargo dev lint` can now be run on a package directory
2 parents 8ec7ba4 + 9a02386 commit 01ea624

File tree

5 files changed

+80
-30
lines changed

5 files changed

+80
-30
lines changed

clippy_dev/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ indoc = "1.0"
99
itertools = "0.10.1"
1010
opener = "0.5"
1111
shell-escape = "0.1"
12+
tempfile = "3.3"
1213
walkdir = "2.3"
1314

1415
[features]

clippy_dev/src/bless.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,15 @@
11
//! `bless` updates the reference files in the repo with changed output files
22
//! from the last test run.
33
4+
use crate::cargo_clippy_path;
45
use std::ffi::OsStr;
56
use std::fs;
67
use std::lazy::SyncLazy;
78
use std::path::{Path, PathBuf};
89
use walkdir::{DirEntry, WalkDir};
910

10-
#[cfg(not(windows))]
11-
static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
12-
#[cfg(windows)]
13-
static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe";
14-
15-
static CLIPPY_BUILD_TIME: SyncLazy<Option<std::time::SystemTime>> = SyncLazy::new(|| {
16-
let mut path = std::env::current_exe().unwrap();
17-
path.set_file_name(CARGO_CLIPPY_EXE);
18-
fs::metadata(path).ok()?.modified().ok()
19-
});
11+
static CLIPPY_BUILD_TIME: SyncLazy<Option<std::time::SystemTime>> =
12+
SyncLazy::new(|| cargo_clippy_path().metadata().ok()?.modified().ok());
2013

2114
/// # Panics
2215
///

clippy_dev/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ pub mod serve;
1717
pub mod setup;
1818
pub mod update_lints;
1919

20+
#[cfg(not(windows))]
21+
static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
22+
#[cfg(windows)]
23+
static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe";
24+
25+
/// Returns the path to the `cargo-clippy` binary
26+
#[must_use]
27+
pub fn cargo_clippy_path() -> PathBuf {
28+
let mut path = std::env::current_exe().expect("failed to get current executable name");
29+
path.set_file_name(CARGO_CLIPPY_EXE);
30+
path
31+
}
32+
2033
/// Returns the path to the Clippy project directory
2134
///
2235
/// # Panics

clippy_dev/src/lint.rs

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,52 @@
1-
use std::process::{self, Command};
1+
use crate::cargo_clippy_path;
2+
use std::process::{self, Command, ExitStatus};
3+
use std::{fs, io};
24

3-
pub fn run(filename: &str) {
4-
let code = Command::new("cargo")
5-
.args(["run", "--bin", "clippy-driver", "--"])
6-
.args(["-L", "./target/debug"])
7-
.args(["-Z", "no-codegen"])
8-
.args(["--edition", "2021"])
9-
.arg(filename)
10-
.status()
11-
.expect("failed to run cargo")
12-
.code();
13-
14-
if code.is_none() {
15-
eprintln!("Killed by signal");
5+
fn exit_if_err(status: io::Result<ExitStatus>) {
6+
match status.expect("failed to run command").code() {
7+
Some(0) => {},
8+
Some(n) => process::exit(n),
9+
None => {
10+
eprintln!("Killed by signal");
11+
process::exit(1);
12+
},
1613
}
14+
}
15+
16+
pub fn run(path: &str) {
17+
let is_file = match fs::metadata(path) {
18+
Ok(metadata) => metadata.is_file(),
19+
Err(e) => {
20+
eprintln!("Failed to read {path}: {e:?}");
21+
process::exit(1);
22+
},
23+
};
24+
25+
if is_file {
26+
exit_if_err(
27+
Command::new("cargo")
28+
.args(["run", "--bin", "clippy-driver", "--"])
29+
.args(["-L", "./target/debug"])
30+
.args(["-Z", "no-codegen"])
31+
.args(["--edition", "2021"])
32+
.arg(path)
33+
.status(),
34+
);
35+
} else {
36+
exit_if_err(Command::new("cargo").arg("build").status());
1737

18-
process::exit(code.unwrap_or(1));
38+
// Run in a tempdir as changes to clippy do not retrigger linting
39+
let target = tempfile::Builder::new()
40+
.prefix("clippy")
41+
.tempdir()
42+
.expect("failed to create tempdir");
43+
44+
let status = Command::new(cargo_clippy_path())
45+
.current_dir(path)
46+
.env("CARGO_TARGET_DIR", target.as_ref())
47+
.status();
48+
49+
target.close().expect("failed to remove tempdir");
50+
exit_if_err(status);
51+
}
1952
}

clippy_dev/src/main.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
66
use clippy_dev::{bless, fmt, lint, new_lint, serve, setup, update_lints};
7+
use indoc::indoc;
78
fn main() {
89
let matches = get_clap_config();
910

@@ -56,8 +57,8 @@ fn main() {
5657
serve::run(port, lint);
5758
},
5859
("lint", Some(matches)) => {
59-
let filename = matches.value_of("filename").unwrap();
60-
lint::run(filename);
60+
let path = matches.value_of("path").unwrap();
61+
lint::run(path);
6162
},
6263
_ => {},
6364
}
@@ -225,11 +226,20 @@ fn get_clap_config<'a>() -> ArgMatches<'a> {
225226
)
226227
.subcommand(
227228
SubCommand::with_name("lint")
228-
.about("Manually run clippy on a file")
229+
.about("Manually run clippy on a file or package")
230+
.after_help(indoc! {"
231+
EXAMPLES
232+
Lint a single file:
233+
cargo dev lint tests/ui/attrs.rs
234+
235+
Lint a package directory:
236+
cargo dev lint tests/ui-cargo/wildcard_dependencies/fail
237+
cargo dev lint ~/my-project
238+
"})
229239
.arg(
230-
Arg::with_name("filename")
240+
Arg::with_name("path")
231241
.required(true)
232-
.help("The path to a file to lint"),
242+
.help("The path to a file or package directory to lint"),
233243
),
234244
)
235245
.get_matches()

0 commit comments

Comments
 (0)