@@ -8,7 +8,6 @@ use rustc_data_structures::fx::FxHashSet;
88use rustc_hir:: { EnumDef , FieldDef , Item , ItemKind , OwnerId , Variant , VariantData } ;
99use rustc_lint:: { LateContext , LateLintPass } ;
1010use rustc_session:: impl_lint_pass;
11- use rustc_span:: Span ;
1211use rustc_span:: symbol:: Symbol ;
1312
1413declare_clippy_lint ! {
@@ -197,17 +196,86 @@ fn have_no_extra_prefix(prefixes: &[&str]) -> bool {
197196}
198197
199198impl ItemNameRepetitions {
199+ /// Lint the names of enum variants against the name of the enum.
200+ fn check_variants ( & self , cx : & LateContext < ' _ > , item : & Item < ' _ > , def : & EnumDef < ' _ > ) {
201+ if self . avoid_breaking_exported_api && cx. effective_visibilities . is_exported ( item. owner_id . def_id ) {
202+ return ;
203+ }
204+
205+ if ( def. variants . len ( ) as u64 ) < self . enum_threshold {
206+ return ;
207+ }
208+
209+ let item_name = item. ident . name . as_str ( ) ;
210+ for var in def. variants {
211+ check_enum_start ( cx, item_name, var) ;
212+ check_enum_end ( cx, item_name, var) ;
213+ }
214+
215+ Self :: check_enum_common_affix ( cx, item, def) ;
216+ }
217+
200218 /// Lint the names of struct fields against the name of the struct.
201219 fn check_fields ( & self , cx : & LateContext < ' _ > , item : & Item < ' _ > , fields : & [ FieldDef < ' _ > ] ) {
202220 if ( fields. len ( ) as u64 ) < self . struct_threshold {
203221 return ;
204222 }
205223
206224 self . check_struct_name_repetition ( cx, item, fields) ;
207- self . check_common_affix ( cx, item, fields) ;
225+ self . check_struct_common_affix ( cx, item, fields) ;
226+ }
227+
228+ fn check_enum_common_affix ( cx : & LateContext < ' _ > , item : & Item < ' _ > , def : & EnumDef < ' _ > ) {
229+ let first = match def. variants . first ( ) {
230+ Some ( variant) => variant. ident . name . as_str ( ) ,
231+ None => return ,
232+ } ;
233+ let mut pre = camel_case_split ( first) ;
234+ let mut post = pre. clone ( ) ;
235+ post. reverse ( ) ;
236+ for var in def. variants {
237+ let name = var. ident . name . as_str ( ) ;
238+
239+ let variant_split = camel_case_split ( name) ;
240+ if variant_split. len ( ) == 1 {
241+ return ;
242+ }
243+
244+ pre = pre
245+ . iter ( )
246+ . zip ( variant_split. iter ( ) )
247+ . take_while ( |( a, b) | a == b)
248+ . map ( |e| * e. 0 )
249+ . collect ( ) ;
250+ post = post
251+ . iter ( )
252+ . zip ( variant_split. iter ( ) . rev ( ) )
253+ . take_while ( |( a, b) | a == b)
254+ . map ( |e| * e. 0 )
255+ . collect ( ) ;
256+ }
257+ let ( what, value) = match ( have_no_extra_prefix ( & pre) , post. is_empty ( ) ) {
258+ ( true , true ) => return ,
259+ ( false , _) => ( "pre" , pre. join ( "" ) ) ,
260+ ( true , false ) => {
261+ post. reverse ( ) ;
262+ ( "post" , post. join ( "" ) )
263+ } ,
264+ } ;
265+ span_lint_and_help (
266+ cx,
267+ ENUM_VARIANT_NAMES ,
268+ item. span ,
269+ format ! ( "all variants have the same {what}fix: `{value}`" ) ,
270+ None ,
271+ format ! (
272+ "remove the {what}fixes and use full paths to \
273+ the variants instead of glob imports"
274+ ) ,
275+ ) ;
208276 }
209277
210- fn check_common_affix ( & self , cx : & LateContext < ' _ > , item : & Item < ' _ > , fields : & [ FieldDef < ' _ > ] ) {
278+ fn check_struct_common_affix ( & self , cx : & LateContext < ' _ > , item : & Item < ' _ > , fields : & [ FieldDef < ' _ > ] ) {
211279 // if the SyntaxContext of the identifiers of the fields and struct differ dont lint them.
212280 // this prevents linting in macros in which the location of the field identifier names differ
213281 if !fields. iter ( ) . all ( |field| item. ident . span . eq_ctxt ( field. ident . span ) ) {
@@ -357,65 +425,6 @@ fn check_enum_end(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>)
357425 }
358426}
359427
360- fn check_variant ( cx : & LateContext < ' _ > , threshold : u64 , def : & EnumDef < ' _ > , item_name : & str , span : Span ) {
361- if ( def. variants . len ( ) as u64 ) < threshold {
362- return ;
363- }
364-
365- for var in def. variants {
366- check_enum_start ( cx, item_name, var) ;
367- check_enum_end ( cx, item_name, var) ;
368- }
369-
370- let first = match def. variants . first ( ) {
371- Some ( variant) => variant. ident . name . as_str ( ) ,
372- None => return ,
373- } ;
374- let mut pre = camel_case_split ( first) ;
375- let mut post = pre. clone ( ) ;
376- post. reverse ( ) ;
377- for var in def. variants {
378- let name = var. ident . name . as_str ( ) ;
379-
380- let variant_split = camel_case_split ( name) ;
381- if variant_split. len ( ) == 1 {
382- return ;
383- }
384-
385- pre = pre
386- . iter ( )
387- . zip ( variant_split. iter ( ) )
388- . take_while ( |( a, b) | a == b)
389- . map ( |e| * e. 0 )
390- . collect ( ) ;
391- post = post
392- . iter ( )
393- . zip ( variant_split. iter ( ) . rev ( ) )
394- . take_while ( |( a, b) | a == b)
395- . map ( |e| * e. 0 )
396- . collect ( ) ;
397- }
398- let ( what, value) = match ( have_no_extra_prefix ( & pre) , post. is_empty ( ) ) {
399- ( true , true ) => return ,
400- ( false , _) => ( "pre" , pre. join ( "" ) ) ,
401- ( true , false ) => {
402- post. reverse ( ) ;
403- ( "post" , post. join ( "" ) )
404- } ,
405- } ;
406- span_lint_and_help (
407- cx,
408- ENUM_VARIANT_NAMES ,
409- span,
410- format ! ( "all variants have the same {what}fix: `{value}`" ) ,
411- None ,
412- format ! (
413- "remove the {what}fixes and use full paths to \
414- the variants instead of glob imports"
415- ) ,
416- ) ;
417- }
418-
419428impl LateLintPass < ' _ > for ItemNameRepetitions {
420429 fn check_item_post ( & mut self , _cx : & LateContext < ' _ > , _item : & Item < ' _ > ) {
421430 let last = self . modules . pop ( ) ;
@@ -482,11 +491,7 @@ impl LateLintPass<'_> for ItemNameRepetitions {
482491 if span_is_local ( item. span ) {
483492 match item. kind {
484493 ItemKind :: Enum ( def, _) => {
485- if !( self . avoid_breaking_exported_api
486- && cx. effective_visibilities . is_exported ( item. owner_id . def_id ) )
487- {
488- check_variant ( cx, self . enum_threshold , & def, item_name, item. span ) ;
489- }
494+ self . check_variants ( cx, item, & def) ;
490495 } ,
491496 ItemKind :: Struct ( VariantData :: Struct { fields, .. } , _) => {
492497 self . check_fields ( cx, item, fields) ;
0 commit comments