@@ -15,6 +15,8 @@ use rustc_tools_util::*;
15
15
use std:: path:: Path ;
16
16
use std:: process:: { exit, Command } ;
17
17
18
+ mod lintlist;
19
+
18
20
/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
19
21
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
20
22
fn arg_value < ' a > (
@@ -108,6 +110,142 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
108
110
}
109
111
}
110
112
113
+ #[ allow( clippy:: find_map, clippy:: filter_map) ]
114
+ fn describe_lints ( ) {
115
+ use lintlist:: * ;
116
+ use std:: collections:: HashSet ;
117
+
118
+ println ! (
119
+ "
120
+ Available lint options:
121
+ -W <foo> Warn about <foo>
122
+ -A <foo> Allow <foo>
123
+ -D <foo> Deny <foo>
124
+ -F <foo> Forbid <foo> (deny <foo> and all attempts to override)
125
+
126
+ "
127
+ ) ;
128
+
129
+ let lint_level = |lint : & Lint | {
130
+ LINT_LEVELS
131
+ . iter ( )
132
+ . find ( |level_mapping| level_mapping. 0 == lint. group )
133
+ . map ( |( _, level) | match level {
134
+ Level :: Allow => "allow" ,
135
+ Level :: Warn => "warn" ,
136
+ Level :: Deny => "deny" ,
137
+ } )
138
+ . unwrap ( )
139
+ } ;
140
+
141
+ let mut lints: Vec < _ > = ALL_LINTS . iter ( ) . collect ( ) ;
142
+ // The sort doesn't case-fold but it's doubtful we care.
143
+ lints. sort_by_cached_key ( |x : & & Lint | ( lint_level ( x) , x. name ) ) ;
144
+
145
+ let max_lint_name_len = lints
146
+ . iter ( )
147
+ . map ( |lint| lint. name . len ( ) )
148
+ . map ( |len| len + "clippy::" . len ( ) )
149
+ . max ( )
150
+ . unwrap_or ( 0 ) ;
151
+
152
+ let padded = |x : & str | {
153
+ let mut s = " " . repeat ( max_lint_name_len - x. chars ( ) . count ( ) ) ;
154
+ s. push_str ( x) ;
155
+ s
156
+ } ;
157
+
158
+ let scoped = |x : & str | format ! ( "clippy::{}" , x) ;
159
+
160
+ let lint_groups: HashSet < _ > = lints. iter ( ) . map ( |lint| lint. group ) . collect ( ) ;
161
+
162
+ println ! ( "Lint checks provided by clippy:\n " ) ;
163
+ println ! ( " {} {:7.7} meaning" , padded( "name" ) , "default" ) ;
164
+ println ! ( " {} {:7.7} -------" , padded( "----" ) , "-------" ) ;
165
+
166
+ let print_lints = |lints : & [ & Lint ] | {
167
+ for lint in lints {
168
+ let name = lint. name . replace ( "_" , "-" ) ;
169
+ println ! (
170
+ " {} {:7.7} {}" ,
171
+ padded( & scoped( & name) ) ,
172
+ lint_level( lint) ,
173
+ lint. desc
174
+ ) ;
175
+ }
176
+ println ! ( "\n " ) ;
177
+ } ;
178
+
179
+ print_lints ( & lints) ;
180
+
181
+ let max_group_name_len = std:: cmp:: max (
182
+ "clippy::all" . len ( ) ,
183
+ lint_groups
184
+ . iter ( )
185
+ . map ( |group| group. len ( ) )
186
+ . map ( |len| len + "clippy::" . len ( ) )
187
+ . max ( )
188
+ . unwrap_or ( 0 ) ,
189
+ ) ;
190
+
191
+ let padded_group = |x : & str | {
192
+ let mut s = " " . repeat ( max_group_name_len - x. chars ( ) . count ( ) ) ;
193
+ s. push_str ( x) ;
194
+ s
195
+ } ;
196
+
197
+ println ! ( "Lint groups provided by clippy:\n " ) ;
198
+ println ! ( " {} sub-lints" , padded_group( "name" ) ) ;
199
+ println ! ( " {} ---------" , padded_group( "----" ) ) ;
200
+ println ! ( " {} the set of all clippy lints" , padded_group( "clippy::all" ) ) ;
201
+
202
+ let print_lint_groups = || {
203
+ for group in lint_groups {
204
+ let name = group. to_lowercase ( ) . replace ( "_" , "-" ) ;
205
+ let desc = lints
206
+ . iter ( )
207
+ . filter ( |& lint| lint. group == group)
208
+ . map ( |lint| lint. name )
209
+ . map ( |name| name. replace ( "_" , "-" ) )
210
+ . collect :: < Vec < String > > ( )
211
+ . join ( ", " ) ;
212
+ println ! ( " {} {}" , padded_group( & scoped( & name) ) , desc) ;
213
+ }
214
+ println ! ( "\n " ) ;
215
+ } ;
216
+
217
+ print_lint_groups ( ) ;
218
+ }
219
+
220
+ fn display_help ( ) {
221
+ println ! (
222
+ "\
223
+ Checks a package to catch common mistakes and improve your Rust code.
224
+
225
+ Usage:
226
+ cargo clippy [options] [--] [<opts>...]
227
+
228
+ Common options:
229
+ -h, --help Print this message
230
+ -V, --version Print version info and exit
231
+
232
+ Other options are the same as `cargo check`.
233
+
234
+ To allow or deny a lint from the command line you can use `cargo clippy --`
235
+ with:
236
+
237
+ -W --warn OPT Set lint warnings
238
+ -A --allow OPT Set lint allowed
239
+ -D --deny OPT Set lint denied
240
+ -F --forbid OPT Set lint forbidden
241
+
242
+ You can use tool lints to allow or deny lints from your code, eg.:
243
+
244
+ #[allow(clippy::needless_lifetimes)]
245
+ "
246
+ ) ;
247
+ }
248
+
111
249
pub fn main ( ) {
112
250
rustc_driver:: init_rustc_env_logger ( ) ;
113
251
exit (
@@ -153,13 +291,34 @@ pub fn main() {
153
291
154
292
// Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
155
293
// We're invoking the compiler programmatically, so we ignore this/
156
- if orig_args. len ( ) <= 1 {
157
- std:: process:: exit ( 1 ) ;
158
- }
159
- if Path :: new ( & orig_args[ 1 ] ) . file_stem ( ) == Some ( "rustc" . as_ref ( ) ) {
294
+ let wrapper_mode = Path :: new ( & orig_args[ 1 ] ) . file_stem ( ) == Some ( "rustc" . as_ref ( ) ) ;
295
+
296
+ if wrapper_mode {
160
297
// we still want to be able to invoke it normally though
161
298
orig_args. remove ( 1 ) ;
162
299
}
300
+
301
+ if !wrapper_mode && std:: env:: args ( ) . any ( |a| a == "--help" || a == "-h" ) {
302
+ display_help ( ) ;
303
+ exit ( 0 ) ;
304
+ }
305
+
306
+ let should_describe_lints = || {
307
+ let args: Vec < _ > = std:: env:: args ( ) . collect ( ) ;
308
+ args. windows ( 2 ) . any ( |args| {
309
+ args[ 1 ] == "help"
310
+ && match args[ 0 ] . as_str ( ) {
311
+ "-W" | "-A" | "-D" | "-F" => true ,
312
+ _ => false ,
313
+ }
314
+ } )
315
+ } ;
316
+
317
+ if !wrapper_mode && should_describe_lints ( ) {
318
+ describe_lints ( ) ;
319
+ exit ( 0 ) ;
320
+ }
321
+
163
322
// this conditional check for the --sysroot flag is there so users can call
164
323
// `clippy_driver` directly
165
324
// without having to pass --sysroot or anything
0 commit comments