@@ -5,7 +5,7 @@ use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
5
5
use std:: collections:: { HashMap , HashSet } ;
6
6
use std:: ffi:: OsStr ;
7
7
use std:: fs;
8
- use std:: io:: Write as _;
8
+ use std:: io:: { self , Read as _ , Seek as _ , Write as _} ;
9
9
use std:: path:: { Path , PathBuf } ;
10
10
use walkdir:: { DirEntry , WalkDir } ;
11
11
@@ -189,7 +189,7 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
189
189
} ;
190
190
191
191
// Renamed lints and deprecated lints shouldn't have been found in the lint list, but check just in
192
- // case.)
192
+ // case.
193
193
assert ! (
194
194
!renamed_lints. iter( ) . any( |l| lint. old_name == l. old_name) ,
195
195
"`{}` has already been renamed" ,
@@ -207,18 +207,15 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
207
207
. map ( Result :: unwrap)
208
208
. filter ( |f| {
209
209
let name = f. path ( ) . file_name ( ) ;
210
- f. path ( ) . extension ( ) == Some ( OsStr :: new ( "rs" ) )
210
+ let ext = f. path ( ) . extension ( ) ;
211
+ ( ext == Some ( OsStr :: new ( "rs" ) ) || ext == Some ( OsStr :: new ( "fixed" ) ) )
211
212
&& name != Some ( OsStr :: new ( "rename.rs" ) )
212
213
&& name != Some ( OsStr :: new ( "renamed_lints.rs" ) )
213
214
} )
214
215
{
215
- let path = file. path ( ) ;
216
- let contents =
217
- fs:: read_to_string ( path) . unwrap_or_else ( |e| panic ! ( "Cannot read from `{}`: {}" , path. display( ) , e) ) ;
218
- if let Some ( contents) = replace_ident_like ( & contents, & [ ( & lint. old_name , & lint. new_name ) ] ) {
219
- fs:: write ( path, contents. as_bytes ( ) )
220
- . unwrap_or_else ( |e| panic ! ( "Cannot write to `{}`: {}" , path. display( ) , e) ) ;
221
- }
216
+ rewrite_file ( file. path ( ) , |s| {
217
+ replace_ident_like ( s, & [ ( & lint. old_name , & lint. new_name ) ] )
218
+ } ) ;
222
219
}
223
220
224
221
renamed_lints. push ( lint) ;
@@ -230,72 +227,75 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
230
227
. then_with ( || lhs. old_name . cmp ( & rhs. old_name ) )
231
228
} ) ;
232
229
230
+ write_file (
231
+ Path :: new ( "clippy_lints/src/renamed_lints.rs" ) ,
232
+ & gen_renamed_lints_list ( & renamed_lints) ,
233
+ ) ;
234
+
233
235
if uplift {
236
+ write_file ( Path :: new ( "tests/ui/rename.rs" ) , & gen_renamed_lints_list ( & renamed_lints) ) ;
234
237
println ! (
235
- "`{}` has be uplifted. Please remove all the code inside `clippy_lints` related to it." ,
238
+ "`{}` has be uplifted. All the code inside `clippy_lints` related to it needs to be removed manually ." ,
236
239
old_name
237
240
) ;
238
- let contents = gen_renamed_lints_test ( & renamed_lints) ;
239
- fs:: write ( "tests/ui/rename.rs" , contents. as_bytes ( ) )
240
- . unwrap_or_else ( |e| panic ! ( "error writing file `tests/ui/rename.rs`: {}" , e) ) ;
241
241
} else if found_new_name {
242
+ write_file ( Path :: new ( "tests/ui/rename.rs" ) , & gen_renamed_lints_list ( & renamed_lints) ) ;
242
243
println ! (
243
- "`{}` is already defined. The old linting code inside `clippy_lints` has to be updated/removed manually" ,
244
+ "`{}` is already defined. The old linting code inside `clippy_lints` needs to be updated/removed manually. " ,
244
245
new_name
245
246
) ;
246
- let contents = gen_renamed_lints_test ( & renamed_lints) ;
247
- fs:: write ( "tests/ui/rename.rs" , contents. as_bytes ( ) )
248
- . unwrap_or_else ( |e| panic ! ( "error writing file `tests/ui/rename.rs`: {}" , e) ) ;
249
247
} else {
250
248
// Rename the lint struct and the containing module if it shares the lint name across all files.
251
249
let lint = & mut lints[ old_lint_index] ;
252
250
let old_name_upper = old_name. to_uppercase ( ) ;
253
251
let new_name_upper = new_name. to_uppercase ( ) ;
254
- let new_module_path = PathBuf :: from ( format ! ( "clippy_lints/src/{}.rs" , new_name) ) ;
255
- let replacements;
256
252
257
- let ( replacements, mut renamed_file) = if lint. module == lint. name
258
- // Only rename the module if the file doesn't already exist.
259
- && let Ok ( file) = fs:: OpenOptions :: new ( ) . create_new ( true ) . write ( true ) . open ( & new_module_path)
260
- {
253
+ if try_rename_file (
254
+ Path :: new ( & format ! ( "tests/ui/{}.rs" , old_name) ) ,
255
+ Path :: new ( & format ! ( "tests/ui/{}.rs" , new_name) ) ,
256
+ ) {
257
+ try_rename_file (
258
+ Path :: new ( & format ! ( "tests/ui/{}.stderr" , old_name) ) ,
259
+ Path :: new ( & format ! ( "tests/ui/{}.stderr" , new_name) ) ,
260
+ ) ;
261
+ try_rename_file (
262
+ Path :: new ( & format ! ( "tests/ui/{}.fixed" , old_name) ) ,
263
+ Path :: new ( & format ! ( "tests/ui/{}.fixed" , new_name) ) ,
264
+ ) ;
265
+ }
266
+
267
+ let replacements;
268
+ let replacements = if lint. module == lint. name
269
+ && try_rename_file (
270
+ Path :: new ( & format ! ( "clippy_lints/src/{}.rs" , old_name) ) ,
271
+ Path :: new ( & format ! ( "clippy_lints/src/{}.rs" , new_name) ) ,
272
+ ) {
261
273
lint. module = new_name. into ( ) ;
262
274
replacements = [ ( & * old_name_upper, & * new_name_upper) , ( old_name, new_name) ] ;
263
- ( replacements. as_slice ( ) , Some ( file) )
275
+ replacements. as_slice ( )
276
+ } else if !lint. module . contains ( "::" )
277
+ && try_rename_file (
278
+ Path :: new ( & format ! ( "clippy_lints/src/{}/{}.rs" , lint. module, old_name) ) ,
279
+ Path :: new ( & format ! ( "clippy_lints/src/{}/{}.rs" , lint. module, new_name) ) ,
280
+ )
281
+ {
282
+ replacements = [ ( & * old_name_upper, & * new_name_upper) , ( old_name, new_name) ] ;
283
+ replacements. as_slice ( )
264
284
} else {
265
285
replacements = [ ( & * old_name_upper, & * new_name_upper) , ( "" , "" ) ] ;
266
- ( & replacements[ 0 ..1 ] , None )
286
+ & replacements[ 0 ..1 ]
267
287
} ;
268
288
lint. name = new_name. into ( ) ;
269
289
270
- for ( rel_path, file) in clippy_lints_src_files ( ) {
271
- let path = file. path ( ) ;
272
- let contents =
273
- fs:: read_to_string ( path) . unwrap_or_else ( |e| panic ! ( "Cannot read from `{}`: {}" , path. display( ) , e) ) ;
274
- let new_contents = replace_ident_like ( & contents, replacements) ;
275
-
276
- if let Some ( ref mut file) = renamed_file
277
- // Make sure the file is directly in the src directory and not a sub-directory.
278
- && rel_path. parent ( ) . map_or ( false , |p| p. as_os_str ( ) . is_empty ( ) )
279
- && rel_path. file_stem ( ) == Some ( OsStr :: new ( old_name) )
280
- {
281
- let contents = new_contents. as_ref ( ) . unwrap_or ( & contents) ;
282
- file. write_all ( contents. as_bytes ( ) )
283
- . unwrap_or_else ( |e| panic ! ( "Cannot write to `{}`: {}" , new_module_path. display( ) , e) ) ;
284
- renamed_file = None ;
285
- fs:: remove_file ( path)
286
- . unwrap_or_else ( |e| panic ! ( "Cannot delete file `{}`: {}" , path. display( ) , e) ) ;
287
- } else if let Some ( contents) = new_contents {
288
- fs:: write ( path, contents. as_bytes ( ) )
289
- . unwrap_or_else ( |e| panic ! ( "Cannot write to `{}`: {}" , path. display( ) , e) ) ;
290
- }
290
+ for ( _, file) in clippy_lints_src_files ( ) {
291
+ rewrite_file ( file. path ( ) , |s| replace_ident_like ( s, replacements) ) ;
291
292
}
292
293
293
294
generate_lint_files ( UpdateMode :: Change , & lints, & deprecated_lints, & renamed_lints) ;
295
+ println ! ( "{} has been successfully renamed" , old_name) ;
294
296
}
295
297
296
- let contents = gen_renamed_lints_list ( & renamed_lints) ;
297
- fs:: write ( "clippy_lints/src/renamed_lints.rs" , contents. as_bytes ( ) )
298
- . unwrap_or_else ( |e| panic ! ( "error writing file `clippy_lints/src/renamed_lints.rs`: {}" , e) ) ;
298
+ println ! ( "note: `cargo uitest` still needs to be run to update the test results" ) ;
299
299
}
300
300
301
301
/// Replace substrings if they aren't bordered by identifier characters. Returns `None` if there
@@ -741,6 +741,52 @@ fn replace_region_in_text<'a>(
741
741
Ok ( res)
742
742
}
743
743
744
+ fn try_rename_file ( old_name : & Path , new_name : & Path ) -> bool {
745
+ match fs:: OpenOptions :: new ( ) . create_new ( true ) . write ( true ) . open ( new_name) {
746
+ Ok ( file) => drop ( file) ,
747
+ Err ( e) if e. kind ( ) == io:: ErrorKind :: AlreadyExists => return false ,
748
+ Err ( e) => panic_file ( e, new_name, "create" ) ,
749
+ } ;
750
+ match fs:: rename ( old_name, new_name) {
751
+ Ok ( ( ) ) => true ,
752
+ Err ( e) => {
753
+ drop ( fs:: remove_file ( new_name) ) ;
754
+ if e. kind ( ) == io:: ErrorKind :: NotFound {
755
+ false
756
+ } else {
757
+ panic_file ( e, old_name, "rename" ) ;
758
+ }
759
+ } ,
760
+ }
761
+ }
762
+
763
+ #[ allow( clippy:: needless_pass_by_value) ]
764
+ fn panic_file ( error : io:: Error , name : & Path , action : & str ) -> ! {
765
+ panic ! ( "failed to {} file `{}`: {}" , action, name. display( ) , error)
766
+ }
767
+
768
+ fn rewrite_file ( path : & Path , f : impl FnOnce ( & str ) -> Option < String > ) {
769
+ let mut file = fs:: OpenOptions :: new ( )
770
+ . write ( true )
771
+ . read ( true )
772
+ . open ( path)
773
+ . unwrap_or_else ( |e| panic_file ( e, path, "open" ) ) ;
774
+ let mut buf = String :: new ( ) ;
775
+ file. read_to_string ( & mut buf)
776
+ . unwrap_or_else ( |e| panic_file ( e, path, "read" ) ) ;
777
+ if let Some ( new_contents) = f ( & buf) {
778
+ file. rewind ( ) . unwrap_or_else ( |e| panic_file ( e, path, "write" ) ) ;
779
+ file. write_all ( new_contents. as_bytes ( ) )
780
+ . unwrap_or_else ( |e| panic_file ( e, path, "write" ) ) ;
781
+ file. set_len ( new_contents. len ( ) as u64 )
782
+ . unwrap_or_else ( |e| panic_file ( e, path, "write" ) ) ;
783
+ }
784
+ }
785
+
786
+ fn write_file ( path : & Path , contents : & str ) {
787
+ fs:: write ( path, contents) . unwrap_or_else ( |e| panic_file ( e, path, "write" ) ) ;
788
+ }
789
+
744
790
#[ cfg( test) ]
745
791
mod tests {
746
792
use super :: * ;
0 commit comments