55
66use itertools:: Itertools ;
77use regex:: Regex ;
8- use std:: collections:: HashMap ;
8+ use std:: collections:: { BTreeSet , HashMap } ;
99use std:: ffi:: OsStr ;
1010use std:: fs;
1111use std:: lazy:: SyncLazy ;
@@ -19,6 +19,10 @@ pub mod serve;
1919pub mod setup;
2020pub mod update_lints;
2121
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+
2226static DEC_CLIPPY_LINT_RE : SyncLazy < Regex > = SyncLazy :: new ( || {
2327 Regex :: new (
2428 r#"(?x)
@@ -98,37 +102,35 @@ impl Lint {
98102 }
99103}
100104
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 ( ) ;
111109
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 ( ) ;
117111
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 " ) ;
119120
120- result
121+ output
121122}
122123
123- /// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`.
124+ /// Generates the module declarations for `lints`
124125#[ 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
132134}
133135
134136/// 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
140142 . collect ( )
141143}
142144
143- /// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`.
145+ /// Generates the `register_removed` code
144146#[ 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
162165}
163166
167+ /// Generates the code for registering lints
164168#[ must_use]
165169pub fn gen_register_lint_list < ' a > (
166170 internal_lints : impl Iterator < Item = & ' a Lint > ,
167171 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
189191}
190192
191193/// Gathers all files in `src/clippy_lints` and gathers all lints inside
@@ -524,21 +526,23 @@ fn test_gen_deprecated() {
524526 "module_name" ,
525527 ) ,
526528 ] ;
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+
542546 assert_eq ! ( expected, gen_deprecated( lints. iter( ) ) ) ;
543547}
544548
@@ -555,7 +559,7 @@ fn test_gen_modules_list() {
555559 Lint :: new( "should_assert_eq" , "group1" , "abc" , None , "module_name" ) ,
556560 Lint :: new( "incorrect_stuff" , "group3" , "abc" , None , "another_module" ) ,
557561 ] ;
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 " ;
559563 assert_eq ! ( expected, gen_modules_list( lints. iter( ) ) ) ;
560564}
561565
@@ -566,12 +570,18 @@ fn test_gen_lint_group_list() {
566570 Lint :: new( "should_assert_eq" , "group1" , "abc" , None , "module_name" ) ,
567571 Lint :: new( "internal" , "internal_style" , "abc" , None , "module_name" ) ,
568572 ] ;
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) ;
577587}
0 commit comments