@@ -4,8 +4,8 @@ use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
4
4
use std:: collections:: { HashMap , HashSet } ;
5
5
use std:: ffi:: OsStr ;
6
6
use std:: fs;
7
- use std:: path:: Path ;
8
- use walkdir:: WalkDir ;
7
+ use std:: path:: { Path , PathBuf } ;
8
+ use walkdir:: { DirEntry , WalkDir } ;
9
9
10
10
use crate :: clippy_project_root;
11
11
@@ -30,12 +30,19 @@ pub enum UpdateMode {
30
30
/// # Panics
31
31
///
32
32
/// Panics if a file path could not read from or then written to
33
- #[ allow( clippy:: too_many_lines) ]
34
- pub fn run ( update_mode : UpdateMode ) {
33
+ pub fn update ( update_mode : UpdateMode ) {
35
34
let ( lints, deprecated_lints, renamed_lints) = gather_all ( ) ;
35
+ generate_lint_files ( update_mode, & lints, & deprecated_lints, & renamed_lints) ;
36
+ }
36
37
37
- let internal_lints = Lint :: internal_lints ( & lints) ;
38
- let usable_lints = Lint :: usable_lints ( & lints) ;
38
+ fn generate_lint_files (
39
+ update_mode : UpdateMode ,
40
+ lints : & [ Lint ] ,
41
+ deprecated_lints : & [ DeprecatedLint ] ,
42
+ renamed_lints : & [ RenamedLint ] ,
43
+ ) {
44
+ let internal_lints = Lint :: internal_lints ( lints) ;
45
+ let usable_lints = Lint :: usable_lints ( lints) ;
39
46
let mut sorted_usable_lints = usable_lints. clone ( ) ;
40
47
sorted_usable_lints. sort_by_key ( |lint| lint. name . clone ( ) ) ;
41
48
@@ -87,7 +94,7 @@ pub fn run(update_mode: UpdateMode) {
87
94
process_file (
88
95
"clippy_lints/src/lib.deprecated.rs" ,
89
96
update_mode,
90
- & gen_deprecated ( & deprecated_lints) ,
97
+ & gen_deprecated ( deprecated_lints) ,
91
98
) ;
92
99
93
100
let all_group_lints = usable_lints. iter ( ) . filter ( |l| {
@@ -108,10 +115,10 @@ pub fn run(update_mode: UpdateMode) {
108
115
) ;
109
116
}
110
117
111
- let content = gen_deprecated_lints_test ( & deprecated_lints) ;
118
+ let content = gen_deprecated_lints_test ( deprecated_lints) ;
112
119
process_file ( "tests/ui/deprecated.rs" , update_mode, & content) ;
113
120
114
- let content = gen_renamed_lints_test ( & renamed_lints) ;
121
+ let content = gen_renamed_lints_test ( renamed_lints) ;
115
122
process_file ( "tests/ui/rename.rs" , update_mode, & content) ;
116
123
}
117
124
@@ -134,6 +141,117 @@ pub fn print_lints() {
134
141
println ! ( "there are {} lints" , usable_lint_count) ;
135
142
}
136
143
144
+ /// Runs the `rename_lint` command.
145
+ ///
146
+ /// # Panics
147
+ /// Panics for the following conditions:
148
+ /// * If a file path could not read from or then written to
149
+ /// * If either lint name has a prefix
150
+ /// * If `old_name` doesn't name an existing lint.
151
+ /// * If `old_name` names a deprecated or renamed lint.
152
+ pub fn rename ( old_name : & str , new_name : & str , uplift : bool ) {
153
+ if let Some ( ( prefix, _) ) = old_name. split_once ( "::" ) {
154
+ panic ! ( "`{}` should not contain the `{}` prefix" , old_name, prefix) ;
155
+ }
156
+ if let Some ( ( prefix, _) ) = new_name. split_once ( "::" ) {
157
+ panic ! ( "`{}` should not contain the `{}` prefix" , new_name, prefix) ;
158
+ }
159
+
160
+ let ( mut lints, deprecated_lints, mut renamed_lints) = gather_all ( ) ;
161
+ let mut old_lint_index = None ;
162
+ let mut found_new_name = false ;
163
+ for ( i, lint) in lints. iter ( ) . enumerate ( ) {
164
+ if lint. name == old_name {
165
+ old_lint_index = Some ( i) ;
166
+ } else if lint. name == new_name {
167
+ found_new_name = true ;
168
+ }
169
+ }
170
+ let old_lint_index = old_lint_index. unwrap_or_else ( || panic ! ( "could not find lint `{}`" , old_name) ) ;
171
+
172
+ let lint = RenamedLint {
173
+ old_name : format ! ( "clippy::{}" , old_name) ,
174
+ new_name : if uplift {
175
+ new_name. into ( )
176
+ } else {
177
+ format ! ( "clippy::{}" , new_name)
178
+ } ,
179
+ } ;
180
+
181
+ // Renamed lints and deprecated lints shouldn't have been found in the lint list, but check just in
182
+ // case.)
183
+ assert ! (
184
+ renamed_lints. iter( ) . any( |l| lint. old_name == l. old_name) ,
185
+ "`{}` has already been renamed" ,
186
+ old_name
187
+ ) ;
188
+ assert ! (
189
+ deprecated_lints. iter( ) . any( |l| lint. old_name == l. name) ,
190
+ "`{}` has already been deprecated" ,
191
+ old_name
192
+ ) ;
193
+
194
+ // Update all lint level attributes.
195
+ for file in WalkDir :: new ( clippy_project_root ( ) )
196
+ . into_iter ( )
197
+ . map ( Result :: unwrap)
198
+ . filter ( |f| {
199
+ let name = f. path ( ) . file_name ( ) ;
200
+ f. path ( ) . extension ( ) == Some ( OsStr :: new ( "rs" ) )
201
+ && name != Some ( OsStr :: new ( "rename.rs" ) )
202
+ && name != Some ( OsStr :: new ( "renamed_lints.rs" ) )
203
+ } )
204
+ {
205
+ let path = file. path ( ) ;
206
+ let contents =
207
+ fs:: read_to_string ( path) . unwrap_or_else ( |e| panic ! ( "Cannot read from `{}`: {}" , path. display( ) , e) ) ;
208
+ if contents. contains ( & lint. old_name ) {
209
+ fs:: write ( path, contents. replace ( & lint. old_name , & lint. new_name ) . as_bytes ( ) )
210
+ . unwrap_or_else ( |e| panic ! ( "Cannot write to `{}`: {}" , path. display( ) , e) ) ;
211
+ }
212
+ }
213
+
214
+ renamed_lints. push ( lint) ;
215
+ renamed_lints. sort_by ( |lhs, rhs| {
216
+ lhs. new_name
217
+ . starts_with ( "clippy::" )
218
+ . cmp ( & rhs. new_name . starts_with ( "clippy::" ) )
219
+ . reverse ( )
220
+ . then_with ( || lhs. old_name . cmp ( & rhs. old_name ) )
221
+ } ) ;
222
+
223
+ if found_new_name {
224
+ println ! (
225
+ "`{}` is already defined. Removal the old lint code in `clippy_lints` will have to be done manually" ,
226
+ new_name
227
+ ) ;
228
+ let contents = gen_renamed_lints_test ( & renamed_lints) ;
229
+ fs:: write ( "tests/ui/rename.rs" , contents. as_bytes ( ) )
230
+ . unwrap_or_else ( |e| panic ! ( "error writing file `tests/ui/rename.rs`: {}" , e) ) ;
231
+ } else {
232
+ // Update the lint struct name
233
+ lints[ old_lint_index] . name = new_name. into ( ) ;
234
+ let old_name = old_name. to_uppercase ( ) ;
235
+ let new_name = new_name. to_uppercase ( ) ;
236
+
237
+ for ( _, file) in clippy_lints_src_files ( ) {
238
+ let path = file. path ( ) ;
239
+ let contents =
240
+ fs:: read_to_string ( path) . unwrap_or_else ( |e| panic ! ( "Cannot read from `{}`: {}" , path. display( ) , e) ) ;
241
+ if contents. contains ( & old_name) {
242
+ fs:: write ( path, contents. replace ( & old_name, & new_name) . as_bytes ( ) )
243
+ . unwrap_or_else ( |e| panic ! ( "Cannot write to `{}`: {}" , path. display( ) , e) ) ;
244
+ }
245
+ }
246
+
247
+ generate_lint_files ( UpdateMode :: Change , & lints, & deprecated_lints, & renamed_lints) ;
248
+ }
249
+
250
+ let contents = gen_renamed_lints_list ( & renamed_lints) ;
251
+ fs:: write ( "clippy_lints/src/renamed_lints.rs" , contents. as_bytes ( ) )
252
+ . unwrap_or_else ( |e| panic ! ( "error writing file `clippy_lints/src/renamed_lints.rs`: {}" , e) ) ;
253
+ }
254
+
137
255
fn round_to_fifty ( count : usize ) -> usize {
138
256
count / 50 * 50
139
257
}
@@ -324,19 +442,22 @@ fn gen_renamed_lints_test(lints: &[RenamedLint]) -> String {
324
442
res
325
443
}
326
444
445
+ fn gen_renamed_lints_list ( lints : & [ RenamedLint ] ) -> String {
446
+ let mut res = String :: from ( "pub static RENAMED_LINTS: &[(&str, &str)] = &[\n " ) ;
447
+ for lint in lints {
448
+ writeln ! ( res, " (\" {}\" , \" {}\" )," , lint. old_name, lint. new_name) . unwrap ( ) ;
449
+ }
450
+ res. push_str ( "];\n " ) ;
451
+ res
452
+ }
453
+
327
454
/// Gathers all lints defined in `clippy_lints/src`
328
455
fn gather_all ( ) -> ( Vec < Lint > , Vec < DeprecatedLint > , Vec < RenamedLint > ) {
329
456
let mut lints = Vec :: with_capacity ( 1000 ) ;
330
457
let mut deprecated_lints = Vec :: with_capacity ( 50 ) ;
331
458
let mut renamed_lints = Vec :: with_capacity ( 50 ) ;
332
- let root_path = clippy_project_root ( ) . join ( "clippy_lints/src" ) ;
333
459
334
- for ( rel_path, file) in WalkDir :: new ( & root_path)
335
- . into_iter ( )
336
- . map ( Result :: unwrap)
337
- . filter ( |f| f. path ( ) . extension ( ) == Some ( OsStr :: new ( "rs" ) ) )
338
- . map ( |f| ( f. path ( ) . strip_prefix ( & root_path) . unwrap ( ) . to_path_buf ( ) , f) )
339
- {
460
+ for ( rel_path, file) in clippy_lints_src_files ( ) {
340
461
let path = file. path ( ) ;
341
462
let contents =
342
463
fs:: read_to_string ( path) . unwrap_or_else ( |e| panic ! ( "Cannot read from `{}`: {}" , path. display( ) , e) ) ;
@@ -363,6 +484,14 @@ fn gather_all() -> (Vec<Lint>, Vec<DeprecatedLint>, Vec<RenamedLint>) {
363
484
( lints, deprecated_lints, renamed_lints)
364
485
}
365
486
487
+ fn clippy_lints_src_files ( ) -> impl Iterator < Item = ( PathBuf , DirEntry ) > {
488
+ let root_path = clippy_project_root ( ) . join ( "clippy_lints/src" ) ;
489
+ let iter = WalkDir :: new ( & root_path) . into_iter ( ) ;
490
+ iter. map ( Result :: unwrap)
491
+ . filter ( |f| f. path ( ) . extension ( ) == Some ( OsStr :: new ( "rs" ) ) )
492
+ . map ( move |f| ( f. path ( ) . strip_prefix ( & root_path) . unwrap ( ) . to_path_buf ( ) , f) )
493
+ }
494
+
366
495
macro_rules! match_tokens {
367
496
( $iter: ident, $( $token: ident $( { $( $fields: tt) * } ) ? $( ( $capture: ident) ) ?) * ) => {
368
497
{
0 commit comments