]>
Commit | Line | Data |
---|---|---|
f20569fa | 1 | #![cfg_attr(feature = "deny-warnings", deny(warnings))] |
17df50a5 XL |
2 | // warn on lints, that are included in `rust-lang/rust`s bootstrap |
3 | #![warn(rust_2018_idioms, unused_lifetimes)] | |
f20569fa | 4 | |
9ffffee4 | 5 | use clap::{Arg, ArgAction, ArgMatches, Command}; |
fe692bf9 | 6 | use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints}; |
04454e1e | 7 | use indoc::indoc; |
fe692bf9 | 8 | use std::convert::Infallible; |
064997fb | 9 | |
f20569fa XL |
10 | fn main() { |
11 | let matches = get_clap_config(); | |
12 | ||
13 | match matches.subcommand() { | |
fe692bf9 FG |
14 | Some(("bless", _)) => { |
15 | eprintln!("use `cargo bless` to automatically replace `.stderr` and `.fixed` files as tests are being run"); | |
f20569fa | 16 | }, |
064997fb FG |
17 | Some(("dogfood", matches)) => { |
18 | dogfood::dogfood( | |
9ffffee4 FG |
19 | matches.get_flag("fix"), |
20 | matches.get_flag("allow-dirty"), | |
21 | matches.get_flag("allow-staged"), | |
064997fb FG |
22 | ); |
23 | }, | |
923072b8 | 24 | Some(("fmt", matches)) => { |
9ffffee4 | 25 | fmt::run(matches.get_flag("check"), matches.get_flag("verbose")); |
f20569fa | 26 | }, |
923072b8 | 27 | Some(("update_lints", matches)) => { |
9ffffee4 | 28 | if matches.get_flag("print-only") { |
f20569fa | 29 | update_lints::print_lints(); |
9ffffee4 | 30 | } else if matches.get_flag("check") { |
04454e1e | 31 | update_lints::update(update_lints::UpdateMode::Check); |
f20569fa | 32 | } else { |
04454e1e | 33 | update_lints::update(update_lints::UpdateMode::Change); |
f20569fa XL |
34 | } |
35 | }, | |
923072b8 | 36 | Some(("new_lint", matches)) => { |
f20569fa | 37 | match new_lint::create( |
fe692bf9 | 38 | matches.get_one::<String>("pass").unwrap(), |
923072b8 | 39 | matches.get_one::<String>("name"), |
064997fb FG |
40 | matches.get_one::<String>("category").map(String::as_str), |
41 | matches.get_one::<String>("type").map(String::as_str), | |
9ffffee4 | 42 | matches.get_flag("msrv"), |
f20569fa | 43 | ) { |
add651ee | 44 | Ok(()) => update_lints::update(update_lints::UpdateMode::Change), |
2b03887a | 45 | Err(e) => eprintln!("Unable to create lint: {e}"), |
f20569fa XL |
46 | } |
47 | }, | |
923072b8 FG |
48 | Some(("setup", sub_command)) => match sub_command.subcommand() { |
49 | Some(("intellij", matches)) => { | |
9ffffee4 | 50 | if matches.get_flag("remove") { |
04454e1e FG |
51 | setup::intellij::remove_rustc_src(); |
52 | } else { | |
53 | setup::intellij::setup_rustc_src( | |
54 | matches | |
923072b8 | 55 | .get_one::<String>("rustc-repo-path") |
04454e1e FG |
56 | .expect("this field is mandatory and therefore always valid"), |
57 | ); | |
58 | } | |
59 | }, | |
923072b8 | 60 | Some(("git-hook", matches)) => { |
9ffffee4 | 61 | if matches.get_flag("remove") { |
04454e1e FG |
62 | setup::git_hook::remove_hook(); |
63 | } else { | |
9ffffee4 | 64 | setup::git_hook::install_hook(matches.get_flag("force-override")); |
04454e1e FG |
65 | } |
66 | }, | |
923072b8 | 67 | Some(("vscode-tasks", matches)) => { |
9ffffee4 | 68 | if matches.get_flag("remove") { |
04454e1e FG |
69 | setup::vscode::remove_tasks(); |
70 | } else { | |
9ffffee4 | 71 | setup::vscode::install_tasks(matches.get_flag("force-override")); |
04454e1e FG |
72 | } |
73 | }, | |
136023e0 XL |
74 | _ => {}, |
75 | }, | |
923072b8 FG |
76 | Some(("remove", sub_command)) => match sub_command.subcommand() { |
77 | Some(("git-hook", _)) => setup::git_hook::remove_hook(), | |
78 | Some(("intellij", _)) => setup::intellij::remove_rustc_src(), | |
79 | Some(("vscode-tasks", _)) => setup::vscode::remove_tasks(), | |
136023e0 XL |
80 | _ => {}, |
81 | }, | |
923072b8 FG |
82 | Some(("serve", matches)) => { |
83 | let port = *matches.get_one::<u16>("port").unwrap(); | |
84 | let lint = matches.get_one::<String>("lint"); | |
f20569fa XL |
85 | serve::run(port, lint); |
86 | }, | |
923072b8 FG |
87 | Some(("lint", matches)) => { |
88 | let path = matches.get_one::<String>("path").unwrap(); | |
89 | let args = matches.get_many::<String>("args").into_iter().flatten(); | |
90 | lint::run(path, args); | |
04454e1e | 91 | }, |
923072b8 FG |
92 | Some(("rename_lint", matches)) => { |
93 | let old_name = matches.get_one::<String>("old_name").unwrap(); | |
94 | let new_name = matches.get_one::<String>("new_name").unwrap_or(old_name); | |
9ffffee4 | 95 | let uplift = matches.get_flag("uplift"); |
04454e1e | 96 | update_lints::rename(old_name, new_name, uplift); |
a2a8927a | 97 | }, |
064997fb FG |
98 | Some(("deprecate", matches)) => { |
99 | let name = matches.get_one::<String>("name").unwrap(); | |
100 | let reason = matches.get_one("reason"); | |
101 | update_lints::deprecate(name, reason); | |
102 | }, | |
f20569fa XL |
103 | _ => {}, |
104 | } | |
105 | } | |
106 | ||
923072b8 FG |
107 | fn get_clap_config() -> ArgMatches { |
108 | Command::new("Clippy developer tooling") | |
109 | .arg_required_else_help(true) | |
110 | .subcommands([ | |
111 | Command::new("bless").about("bless the test output changes").arg( | |
112 | Arg::new("ignore-timestamp") | |
113 | .long("ignore-timestamp") | |
9ffffee4 | 114 | .action(ArgAction::SetTrue) |
923072b8 FG |
115 | .help("Include files updated before clippy was built"), |
116 | ), | |
064997fb | 117 | Command::new("dogfood").about("Runs the dogfood test").args([ |
9ffffee4 FG |
118 | Arg::new("fix") |
119 | .long("fix") | |
120 | .action(ArgAction::SetTrue) | |
121 | .help("Apply the suggestions when possible"), | |
064997fb FG |
122 | Arg::new("allow-dirty") |
123 | .long("allow-dirty") | |
9ffffee4 | 124 | .action(ArgAction::SetTrue) |
064997fb FG |
125 | .help("Fix code even if the working directory has changes") |
126 | .requires("fix"), | |
127 | Arg::new("allow-staged") | |
128 | .long("allow-staged") | |
9ffffee4 | 129 | .action(ArgAction::SetTrue) |
064997fb FG |
130 | .help("Fix code even if the working directory has staged changes") |
131 | .requires("fix"), | |
132 | ]), | |
923072b8 | 133 | Command::new("fmt") |
f20569fa | 134 | .about("Run rustfmt on all projects and tests") |
923072b8 | 135 | .args([ |
9ffffee4 FG |
136 | Arg::new("check") |
137 | .long("check") | |
138 | .action(ArgAction::SetTrue) | |
139 | .help("Use the rustfmt --check option"), | |
140 | Arg::new("verbose") | |
141 | .short('v') | |
142 | .long("verbose") | |
143 | .action(ArgAction::SetTrue) | |
144 | .help("Echo commands run"), | |
923072b8 FG |
145 | ]), |
146 | Command::new("update_lints") | |
f20569fa XL |
147 | .about("Updates lint registration and information from the source code") |
148 | .long_about( | |
149 | "Makes sure that:\n \ | |
923072b8 FG |
150 | * the lint count in README.md is correct\n \ |
151 | * the changelog contains markdown link references at the bottom\n \ | |
152 | * all lint groups include the correct lints\n \ | |
153 | * lint modules in `clippy_lints/*` are visible in `src/lib.rs` via `pub mod`\n \ | |
154 | * all lints are registered in the lint store", | |
f20569fa | 155 | ) |
923072b8 | 156 | .args([ |
9ffffee4 FG |
157 | Arg::new("print-only") |
158 | .long("print-only") | |
159 | .action(ArgAction::SetTrue) | |
160 | .help( | |
161 | "Print a table of lints to STDOUT. \ | |
162 | This does not include deprecated and internal lints. \ | |
163 | (Does not modify any files)", | |
164 | ), | |
923072b8 | 165 | Arg::new("check") |
f20569fa | 166 | .long("check") |
9ffffee4 | 167 | .action(ArgAction::SetTrue) |
f20569fa | 168 | .help("Checks that `cargo dev update_lints` has been run. Used on CI."), |
923072b8 FG |
169 | ]), |
170 | Command::new("new_lint") | |
f20569fa | 171 | .about("Create new lint and run `cargo dev update_lints`") |
923072b8 FG |
172 | .args([ |
173 | Arg::new("pass") | |
174 | .short('p') | |
f20569fa XL |
175 | .long("pass") |
176 | .help("Specify whether the lint runs during the early or late pass") | |
9ffffee4 | 177 | .value_parser(["early", "late"]) |
064997fb | 178 | .conflicts_with("type") |
fe692bf9 | 179 | .default_value("late"), |
923072b8 FG |
180 | Arg::new("name") |
181 | .short('n') | |
f20569fa XL |
182 | .long("name") |
183 | .help("Name of the new lint in snake case, ex: fn_too_long") | |
fe692bf9 FG |
184 | .required(true) |
185 | .value_parser(|name: &str| Ok::<_, Infallible>(name.replace('-', "_"))), | |
923072b8 FG |
186 | Arg::new("category") |
187 | .short('c') | |
f20569fa XL |
188 | .long("category") |
189 | .help("What category the lint belongs to") | |
190 | .default_value("nursery") | |
923072b8 | 191 | .value_parser([ |
9ffffee4 FG |
192 | "style", |
193 | "correctness", | |
194 | "suspicious", | |
195 | "complexity", | |
196 | "perf", | |
197 | "pedantic", | |
198 | "restriction", | |
199 | "cargo", | |
200 | "nursery", | |
201 | "internal", | |
9ffffee4 FG |
202 | ]), |
203 | Arg::new("type").long("type").help("What directory the lint belongs in"), | |
204 | Arg::new("msrv") | |
205 | .long("msrv") | |
206 | .action(ArgAction::SetTrue) | |
207 | .help("Add MSRV config code to the lint"), | |
923072b8 FG |
208 | ]), |
209 | Command::new("setup") | |
136023e0 | 210 | .about("Support for setting up your personal development environment") |
923072b8 FG |
211 | .arg_required_else_help(true) |
212 | .subcommands([ | |
213 | Command::new("intellij") | |
136023e0 | 214 | .about("Alter dependencies so Intellij Rust can find rustc internals") |
923072b8 FG |
215 | .args([ |
216 | Arg::new("remove") | |
04454e1e | 217 | .long("remove") |
9ffffee4 FG |
218 | .action(ArgAction::SetTrue) |
219 | .help("Remove the dependencies added with 'cargo dev setup intellij'"), | |
923072b8 | 220 | Arg::new("rustc-repo-path") |
136023e0 | 221 | .long("repo-path") |
923072b8 | 222 | .short('r') |
136023e0 | 223 | .help("The path to a rustc repo that will be used for setting the dependencies") |
136023e0 | 224 | .value_name("path") |
04454e1e | 225 | .conflicts_with("remove") |
136023e0 | 226 | .required(true), |
923072b8 FG |
227 | ]), |
228 | Command::new("git-hook") | |
136023e0 | 229 | .about("Add a pre-commit git hook that formats your code to make it look pretty") |
923072b8 FG |
230 | .args([ |
231 | Arg::new("remove") | |
04454e1e | 232 | .long("remove") |
9ffffee4 FG |
233 | .action(ArgAction::SetTrue) |
234 | .help("Remove the pre-commit hook added with 'cargo dev setup git-hook'"), | |
923072b8 | 235 | Arg::new("force-override") |
136023e0 | 236 | .long("force-override") |
923072b8 | 237 | .short('f') |
9ffffee4 FG |
238 | .action(ArgAction::SetTrue) |
239 | .help("Forces the override of an existing git pre-commit hook"), | |
923072b8 FG |
240 | ]), |
241 | Command::new("vscode-tasks") | |
136023e0 | 242 | .about("Add several tasks to vscode for formatting, validation and testing") |
923072b8 FG |
243 | .args([ |
244 | Arg::new("remove") | |
04454e1e | 245 | .long("remove") |
9ffffee4 FG |
246 | .action(ArgAction::SetTrue) |
247 | .help("Remove the tasks added with 'cargo dev setup vscode-tasks'"), | |
923072b8 | 248 | Arg::new("force-override") |
136023e0 | 249 | .long("force-override") |
923072b8 | 250 | .short('f') |
9ffffee4 FG |
251 | .action(ArgAction::SetTrue) |
252 | .help("Forces the override of existing vscode tasks"), | |
923072b8 FG |
253 | ]), |
254 | ]), | |
255 | Command::new("remove") | |
136023e0 | 256 | .about("Support for undoing changes done by the setup command") |
923072b8 FG |
257 | .arg_required_else_help(true) |
258 | .subcommands([ | |
259 | Command::new("git-hook").about("Remove any existing pre-commit git hook"), | |
260 | Command::new("vscode-tasks").about("Remove any existing vscode tasks"), | |
261 | Command::new("intellij").about("Removes rustc source paths added via `cargo dev setup intellij`"), | |
262 | ]), | |
263 | Command::new("serve") | |
f20569fa | 264 | .about("Launch a local 'ALL the Clippy Lints' website in a browser") |
923072b8 FG |
265 | .args([ |
266 | Arg::new("port") | |
f20569fa | 267 | .long("port") |
923072b8 | 268 | .short('p') |
f20569fa XL |
269 | .help("Local port for the http server") |
270 | .default_value("8000") | |
923072b8 FG |
271 | .value_parser(clap::value_parser!(u16)), |
272 | Arg::new("lint").help("Which lint's page to load initially (optional)"), | |
273 | ]), | |
274 | Command::new("lint") | |
04454e1e FG |
275 | .about("Manually run clippy on a file or package") |
276 | .after_help(indoc! {" | |
277 | EXAMPLES | |
278 | Lint a single file: | |
279 | cargo dev lint tests/ui/attrs.rs | |
280 | ||
281 | Lint a package directory: | |
282 | cargo dev lint tests/ui-cargo/wildcard_dependencies/fail | |
283 | cargo dev lint ~/my-project | |
923072b8 FG |
284 | |
285 | Run rustfix: | |
286 | cargo dev lint ~/my-project -- --fix | |
287 | ||
288 | Set lint levels: | |
289 | cargo dev lint file.rs -- -W clippy::pedantic | |
290 | cargo dev lint ~/my-project -- -- -W clippy::pedantic | |
04454e1e | 291 | "}) |
923072b8 FG |
292 | .args([ |
293 | Arg::new("path") | |
a2a8927a | 294 | .required(true) |
04454e1e | 295 | .help("The path to a file or package directory to lint"), |
923072b8 FG |
296 | Arg::new("args") |
297 | .action(ArgAction::Append) | |
298 | .help("Pass extra arguments to cargo/clippy-driver"), | |
299 | ]), | |
300 | Command::new("rename_lint").about("Renames the given lint").args([ | |
301 | Arg::new("old_name") | |
302 | .index(1) | |
303 | .required(true) | |
304 | .help("The name of the lint to rename"), | |
305 | Arg::new("new_name") | |
306 | .index(2) | |
307 | .required_unless_present("uplift") | |
308 | .help("The new name of the lint"), | |
309 | Arg::new("uplift") | |
310 | .long("uplift") | |
9ffffee4 | 311 | .action(ArgAction::SetTrue) |
923072b8 FG |
312 | .help("This lint will be uplifted into rustc"), |
313 | ]), | |
064997fb FG |
314 | Command::new("deprecate").about("Deprecates the given lint").args([ |
315 | Arg::new("name") | |
316 | .index(1) | |
317 | .required(true) | |
318 | .help("The name of the lint to deprecate"), | |
319 | Arg::new("reason") | |
320 | .long("reason") | |
321 | .short('r') | |
064997fb FG |
322 | .help("The reason for deprecation"), |
323 | ]), | |
923072b8 | 324 | ]) |
f20569fa XL |
325 | .get_matches() |
326 | } |