Skip to content

Commit 39227b7

Browse files
committed
Switch over to clap for arg parsing
It saves us from having to parse std::env::args manually, though at the cost of mandating that --all/--manifest-path come before any other arguments. Will make adding additional clippy-specific args easier - see rust-lang#2518
1 parent 71582c1 commit 39227b7

File tree

2 files changed

+24
-63
lines changed

2 files changed

+24
-63
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ path = "src/driver.rs"
4040
clippy_lints = { version = "0.0.189", path = "clippy_lints" }
4141
# end automatic update
4242
cargo_metadata = "0.5"
43+
clap = "2.31"
4344
regex = "0.2"
4445
semver = "0.9"
4546

src/main.rs

Lines changed: 23 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,26 @@
33
#![feature(rustc_private)]
44
#![allow(unknown_lints, missing_docs_in_private_items)]
55

6-
use std::collections::HashMap;
7-
use std::process;
8-
use std::io::{self, Write};
9-
106
extern crate cargo_metadata;
7+
extern crate clap;
118

9+
use std::collections::HashMap;
10+
use std::io::{self, Write};
1211
use std::path::{Path, PathBuf};
12+
use std::process;
1313

14-
const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.
15-
16-
Usage:
17-
cargo clippy [options] [--] [<opts>...]
18-
19-
Common options:
20-
-h, --help Print this message
21-
--features Features to compile for the package
22-
-V, --version Print version info and exit
23-
--all Run over all packages in the current workspace
14+
use clap::{App, AppSettings, Arg};
2415

25-
Other options are the same as `cargo rustc`.
16+
pub fn main() {
17+
let matches = App::new("Clippy")
18+
.about("Checks a package to catch common mistakes and improve your Rust code.")
19+
.version(env!("CARGO_PKG_VERSION"))
20+
.setting(AppSettings::TrailingVarArg)
21+
.setting(AppSettings::UnifiedHelpMessage)
22+
.arg(Arg::from_usage("--manifest-path [PATH] 'Path to the manifest to check'"))
23+
.arg(Arg::from_usage("--all 'Run over all packages in the current workspace'"))
24+
.arg(Arg::from_usage("[CMD] ... 'Commands to pass through to cargo rustc'"))
25+
.after_help("Other options are the same as `cargo rustc`.
2626
2727
To allow or deny a lint from the command line you can use `cargo clippy --`
2828
with:
@@ -35,61 +35,23 @@ with:
3535
The feature `cargo-clippy` is automatically defined for convenience. You can use
3636
it to allow or deny lints from the code, eg.:
3737
38-
#[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
39-
"#;
38+
#[cfg_attr(feature = \"cargo-clippy\", allow(needless_lifetimes))]").get_matches();
4039

41-
#[allow(print_stdout)]
42-
fn show_help() {
43-
println!("{}", CARGO_CLIPPY_HELP);
44-
}
40+
let manifest_path_arg = matches.value_of("manifest-path");
4541

46-
#[allow(print_stdout)]
47-
fn show_version() {
48-
println!("{}", env!("CARGO_PKG_VERSION"));
49-
}
50-
51-
pub fn main() {
52-
// Check for version and help flags even when invoked as 'cargo-clippy'
53-
if std::env::args().any(|a| a == "--help" || a == "-h") {
54-
show_help();
55-
return;
56-
}
57-
if std::env::args().any(|a| a == "--version" || a == "-V") {
58-
show_version();
59-
return;
60-
}
61-
62-
let mut manifest_path_arg = std::env::args()
63-
.skip(2)
64-
.skip_while(|val| !val.starts_with("--manifest-path"));
65-
let manifest_path_arg = manifest_path_arg.next().and_then(|val| {
66-
if val == "--manifest-path" {
67-
manifest_path_arg.next()
68-
} else if val.starts_with("--manifest-path=") {
69-
Some(val["--manifest-path=".len()..].to_owned())
70-
} else {
71-
None
72-
}
73-
});
74-
75-
let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)) {
76-
metadata
77-
} else {
78-
println!(
79-
"{:?}",
80-
cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref))
81-
);
42+
let mut metadata = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)).unwrap_or_else(|error| {
43+
println!("{:?}", error);
8244
let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n"));
8345
process::exit(101);
84-
};
46+
});
8547

8648
let manifest_path = manifest_path_arg.map(|arg| {
8749
PathBuf::from(arg)
8850
.canonicalize()
8951
.expect("manifest path could not be canonicalized")
9052
});
9153

92-
let packages = if std::env::args().any(|a| a == "--all") {
54+
let packages = if matches.is_present("all") {
9355
metadata.packages
9456
} else {
9557
let package_index = {
@@ -147,11 +109,9 @@ pub fn main() {
147109
let manifest_path = package.manifest_path;
148110

149111
for target in package.targets {
150-
let args = std::env::args()
151-
.skip(1)
152-
.filter(|a| a != "--all" && !a.starts_with("--manifest-path="));
112+
let args = std::iter::once(format!("--manifest-path={}", manifest_path))
113+
.chain(matches.values_of_lossy("CMD").unwrap_or_default());
153114

154-
let args = std::iter::once(format!("--manifest-path={}", manifest_path)).chain(args);
155115
if let Some(first) = target.kind.get(0) {
156116
if target.kind.len() > 1 || first.ends_with("lib") {
157117
println!("lib: {}", target.name);

0 commit comments

Comments
 (0)