5
5
6
6
use itertools:: Itertools ;
7
7
use regex:: Regex ;
8
- use std:: collections:: HashMap ;
8
+ use std:: collections:: { BTreeSet , HashMap } ;
9
9
use std:: ffi:: OsStr ;
10
10
use std:: fs;
11
11
use std:: lazy:: SyncLazy ;
@@ -19,6 +19,10 @@ pub mod serve;
19
19
pub mod setup;
20
20
pub mod update_lints;
21
21
22
+ const GENERATED_FILE_COMMENT : & str = "// This file was generated by `cargo dev update_lints`.\n \
23
+ // Use that command to update this file and do not edit by hand.\n \
24
+ // Manual edits will be overwritten.\n \n ";
25
+
22
26
static DEC_CLIPPY_LINT_RE : SyncLazy < Regex > = SyncLazy :: new ( || {
23
27
Regex :: new (
24
28
r#"(?x)
@@ -98,37 +102,35 @@ impl Lint {
98
102
}
99
103
}
100
104
101
- /// Generates the Vec items for `register_lint_group` calls in `clippy_lints/src/lib.rs`.
102
- #[ must_use]
103
- pub fn gen_lint_group_list < ' a > ( group_name : & str , lints : impl Iterator < Item = & ' a Lint > ) -> Vec < String > {
104
- let header = format ! (
105
- r#"store.register_group(true, "clippy::{0}", Some("clippy_{0}"), vec!["# ,
106
- group_name
107
- ) ;
108
- let footer = "])" . to_string ( ) ;
109
-
110
- let mut result = vec ! [ header] ;
105
+ /// Generates the code for registering a group
106
+ pub fn gen_lint_group_list < ' a > ( group_name : & str , lints : impl Iterator < Item = & ' a Lint > ) -> String {
107
+ let mut details: Vec < _ > = lints. map ( |l| ( & l. module , l. name . to_uppercase ( ) ) ) . collect ( ) ;
108
+ details. sort_unstable ( ) ;
111
109
112
- result. extend (
113
- lints
114
- . map ( |l| format ! ( "LintId::of({}::{})," , l. module, l. name. to_uppercase( ) ) )
115
- . sorted ( ) ,
116
- ) ;
110
+ let mut output = GENERATED_FILE_COMMENT . to_string ( ) ;
117
111
118
- result. push ( footer) ;
112
+ output. push_str ( & format ! (
113
+ "store.register_group(true, \" clippy::{0}\" , Some(\" clippy_{0}\" ), vec![\n " ,
114
+ group_name
115
+ ) ) ;
116
+ for ( module, name) in details {
117
+ output. push_str ( & format ! ( " LintId::of({}::{}),\n " , module, name) ) ;
118
+ }
119
+ output. push_str ( "])\n " ) ;
119
120
120
- result
121
+ output
121
122
}
122
123
123
- /// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`.
124
+ /// Generates the module declarations for `lints`
124
125
#[ must_use]
125
- pub fn gen_modules_list < ' a > ( lints : impl Iterator < Item = & ' a Lint > ) -> Vec < String > {
126
- lints
127
- . map ( |l| & l. module )
128
- . unique ( )
129
- . map ( |module| format ! ( "mod {};" , module) )
130
- . sorted ( )
131
- . collect :: < Vec < String > > ( )
126
+ pub fn gen_modules_list < ' a > ( lints : impl Iterator < Item = & ' a Lint > ) -> String {
127
+ let module_names: BTreeSet < _ > = lints. map ( |l| & l. module ) . collect ( ) ;
128
+
129
+ let mut output = GENERATED_FILE_COMMENT . to_string ( ) ;
130
+ for name in module_names {
131
+ output. push_str ( & format ! ( "mod {};\n " , name) ) ;
132
+ }
133
+ output
132
134
}
133
135
134
136
/// Generates the list of lint links at the bottom of the README
@@ -140,52 +142,52 @@ pub fn gen_changelog_lint_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec
140
142
. collect ( )
141
143
}
142
144
143
- /// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`.
145
+ /// Generates the `register_removed` code
144
146
#[ must_use]
145
- pub fn gen_deprecated < ' a > ( lints : impl Iterator < Item = & ' a Lint > ) -> Vec < String > {
146
- let mut result = vec ! [ "{" . to_string( ) ] ;
147
- result. extend ( lints. flat_map ( |l| {
148
- l. deprecation
149
- . clone ( )
150
- . map ( |depr_text| {
151
- vec ! [
152
- " store.register_removed(" . to_string( ) ,
153
- format!( " \" clippy::{}\" ," , l. name) ,
154
- format!( " \" {}\" ," , depr_text) ,
155
- " );" . to_string( ) ,
156
- ]
157
- } )
158
- . expect ( "only deprecated lints should be passed" )
159
- } ) ) ;
160
- result. push ( "}" . to_string ( ) ) ;
161
- result
147
+ pub fn gen_deprecated < ' a > ( lints : impl Iterator < Item = & ' a Lint > ) -> String {
148
+ let mut output = GENERATED_FILE_COMMENT . to_string ( ) ;
149
+ output. push_str ( "{\n " ) ;
150
+ for Lint { name, deprecation, .. } in lints {
151
+ output. push_str ( & format ! (
152
+ concat!(
153
+ " store.register_removed(\n " ,
154
+ " \" clippy::{}\" ,\n " ,
155
+ " \" {}\" ,\n " ,
156
+ " );\n "
157
+ ) ,
158
+ name,
159
+ deprecation. as_ref( ) . expect( "`lints` are deprecated" )
160
+ ) ) ;
161
+ }
162
+ output. push_str ( "}\n " ) ;
163
+
164
+ output
162
165
}
163
166
167
+ /// Generates the code for registering lints
164
168
#[ must_use]
165
169
pub fn gen_register_lint_list < ' a > (
166
170
internal_lints : impl Iterator < Item = & ' a Lint > ,
167
171
usable_lints : impl Iterator < Item = & ' a Lint > ,
168
- ) -> Vec < String > {
169
- let header = " store.register_lints(&[" . to_string ( ) ;
170
- let footer = " ])" . to_string ( ) ;
171
- let internal_lints = internal_lints
172
- . sorted_by_key ( |l| format ! ( " {}::{}," , l. module, l. name. to_uppercase( ) ) )
173
- . map ( |l| {
174
- format ! (
175
- " #[cfg(feature = \" internal-lints\" )]\n {}::{}," ,
176
- l. module,
177
- l. name. to_uppercase( )
178
- )
179
- } ) ;
180
- let other_lints = usable_lints
181
- . sorted_by_key ( |l| format ! ( " {}::{}," , l. module, l. name. to_uppercase( ) ) )
182
- . map ( |l| format ! ( " {}::{}," , l. module, l. name. to_uppercase( ) ) )
183
- . sorted ( ) ;
184
- let mut lint_list = vec ! [ header] ;
185
- lint_list. extend ( internal_lints) ;
186
- lint_list. extend ( other_lints) ;
187
- lint_list. push ( footer) ;
188
- lint_list
172
+ ) -> String {
173
+ let mut details: Vec < _ > = internal_lints
174
+ . map ( |l| ( false , & l. module , l. name . to_uppercase ( ) ) )
175
+ . chain ( usable_lints. map ( |l| ( true , & l. module , l. name . to_uppercase ( ) ) ) )
176
+ . collect ( ) ;
177
+ details. sort_unstable ( ) ;
178
+
179
+ let mut output = GENERATED_FILE_COMMENT . to_string ( ) ;
180
+ output. push_str ( "store.register_lints(&[\n " ) ;
181
+
182
+ for ( is_public, module_name, lint_name) in details {
183
+ if !is_public {
184
+ output. push_str ( " #[cfg(feature = \" internal-lints\" )]\n " ) ;
185
+ }
186
+ output. push_str ( & format ! ( " {}::{},\n " , module_name, lint_name) ) ;
187
+ }
188
+ output. push_str ( "])\n " ) ;
189
+
190
+ output
189
191
}
190
192
191
193
/// Gathers all files in `src/clippy_lints` and gathers all lints inside
@@ -524,21 +526,23 @@ fn test_gen_deprecated() {
524
526
"module_name" ,
525
527
) ,
526
528
] ;
527
- let expected: Vec < String > = vec ! [
528
- "{" ,
529
- " store.register_removed(" ,
530
- " \" clippy::should_assert_eq\" ," ,
531
- " \" has been superseded by should_assert_eq2\" ," ,
532
- " );" ,
533
- " store.register_removed(" ,
534
- " \" clippy::another_deprecated\" ," ,
535
- " \" will be removed\" ," ,
536
- " );" ,
537
- "}" ,
538
- ]
539
- . into_iter ( )
540
- . map ( String :: from)
541
- . collect ( ) ;
529
+
530
+ let expected = GENERATED_FILE_COMMENT . to_string ( )
531
+ + & [
532
+ "{" ,
533
+ " store.register_removed(" ,
534
+ " \" clippy::should_assert_eq\" ," ,
535
+ " \" has been superseded by should_assert_eq2\" ," ,
536
+ " );" ,
537
+ " store.register_removed(" ,
538
+ " \" clippy::another_deprecated\" ," ,
539
+ " \" will be removed\" ," ,
540
+ " );" ,
541
+ "}" ,
542
+ ]
543
+ . join ( "\n " )
544
+ + "\n " ;
545
+
542
546
assert_eq ! ( expected, gen_deprecated( lints. iter( ) ) ) ;
543
547
}
544
548
@@ -555,7 +559,7 @@ fn test_gen_modules_list() {
555
559
Lint :: new( "should_assert_eq" , "group1" , "abc" , None , "module_name" ) ,
556
560
Lint :: new( "incorrect_stuff" , "group3" , "abc" , None , "another_module" ) ,
557
561
] ;
558
- let expected = vec ! [ "mod another_module;" . to_string ( ) , "mod module_name;" . to_string ( ) ] ;
562
+ let expected = GENERATED_FILE_COMMENT . to_string ( ) + & [ "mod another_module;" , "mod module_name;" ] . join ( " \n " ) + " \n " ;
559
563
assert_eq ! ( expected, gen_modules_list( lints. iter( ) ) ) ;
560
564
}
561
565
@@ -566,12 +570,18 @@ fn test_gen_lint_group_list() {
566
570
Lint :: new( "should_assert_eq" , "group1" , "abc" , None , "module_name" ) ,
567
571
Lint :: new( "internal" , "internal_style" , "abc" , None , "module_name" ) ,
568
572
] ;
569
- let expected = vec ! [
570
- "store.register_group(true, \" clippy::group1\" , Some(\" clippy_group1\" ), vec![" ,
571
- "LintId::of(module_name::ABC)," ,
572
- "LintId::of(module_name::INTERNAL)," ,
573
- "LintId::of(module_name::SHOULD_ASSERT_EQ)," ,
574
- "])" ,
575
- ] ;
576
- assert_eq ! ( expected, gen_lint_group_list( "group1" , lints. iter( ) ) ) ;
573
+ let expected = GENERATED_FILE_COMMENT . to_string ( )
574
+ + & [
575
+ "store.register_group(true, \" clippy::group1\" , Some(\" clippy_group1\" ), vec![" ,
576
+ " LintId::of(module_name::ABC)," ,
577
+ " LintId::of(module_name::INTERNAL)," ,
578
+ " LintId::of(module_name::SHOULD_ASSERT_EQ)," ,
579
+ "])" ,
580
+ ]
581
+ . join ( "\n " )
582
+ + "\n " ;
583
+
584
+ let result = gen_lint_group_list ( "group1" , lints. iter ( ) ) ;
585
+
586
+ assert_eq ! ( expected, result) ;
577
587
}
0 commit comments