@@ -2,8 +2,9 @@ use rustc_abi::ExternAbi;
22use rustc_attr_data_structures:: { AttributeKind , ReprAttr } ;
33use rustc_attr_parsing:: AttributeParser ;
44use rustc_hir:: def:: { DefKind , Res } ;
5- use rustc_hir:: intravisit:: FnKind ;
5+ use rustc_hir:: intravisit:: { FnKind , Visitor } ;
66use rustc_hir:: { AttrArgs , AttrItem , Attribute , GenericParamKind , PatExprKind , PatKind } ;
7+ use rustc_middle:: hir:: nested_filter:: All ;
78use rustc_middle:: ty;
89use rustc_session:: config:: CrateType ;
910use rustc_session:: { declare_lint, declare_lint_pass} ;
@@ -489,21 +490,59 @@ declare_lint! {
489490declare_lint_pass ! ( NonUpperCaseGlobals => [ NON_UPPER_CASE_GLOBALS ] ) ;
490491
491492impl NonUpperCaseGlobals {
492- fn check_upper_case ( cx : & LateContext < ' _ > , sort : & str , ident : & Ident ) {
493+ fn check_upper_case ( cx : & LateContext < ' _ > , sort : & str , did : Option < LocalDefId > , ident : & Ident ) {
493494 let name = ident. name . as_str ( ) ;
494495 if name. chars ( ) . any ( |c| c. is_lowercase ( ) ) {
495496 let uc = NonSnakeCase :: to_snake_case ( name) . to_uppercase ( ) ;
497+
496498 // We cannot provide meaningful suggestions
497499 // if the characters are in the category of "Lowercase Letter".
498- let sub = if * name != uc {
499- NonUpperCaseGlobalSub :: Suggestion { span : ident. span , replace : uc }
500+ let sub = |span| {
501+ if * name != uc {
502+ NonUpperCaseGlobalSub :: Suggestion { span, replace : uc. clone ( ) }
503+ } else {
504+ NonUpperCaseGlobalSub :: Label { span }
505+ }
506+ } ;
507+
508+ struct UsageCollector < ' a , ' tcx > {
509+ cx : & ' tcx LateContext < ' a > ,
510+ did : LocalDefId ,
511+ collected : Vec < Span > ,
512+ }
513+
514+ impl < ' v , ' tcx > Visitor < ' v > for UsageCollector < ' v , ' tcx > {
515+ type NestedFilter = All ;
516+
517+ fn maybe_tcx ( & mut self ) -> Self :: MaybeTyCtxt {
518+ self . cx . tcx
519+ }
520+
521+ fn visit_path (
522+ & mut self ,
523+ path : & rustc_hir:: Path < ' v > ,
524+ _id : rustc_hir:: HirId ,
525+ ) -> Self :: Result {
526+ for seg in path. segments {
527+ if seg. res . opt_def_id ( ) == Some ( self . did . to_def_id ( ) ) {
528+ self . collected . push ( seg. ident . span ) ;
529+ }
530+ }
531+ }
532+ }
533+
534+ let usages = if let Some ( did) = did {
535+ let mut usage_collector = UsageCollector { cx, did, collected : Vec :: new ( ) } ;
536+ cx. tcx . hir_walk_toplevel_module ( & mut usage_collector) ;
537+ usage_collector. collected . into_iter ( ) . map ( |span| sub ( span) ) . collect ( )
500538 } else {
501- NonUpperCaseGlobalSub :: Label { span : ident . span }
539+ vec ! [ ]
502540 } ;
541+
503542 cx. emit_span_lint (
504543 NON_UPPER_CASE_GLOBALS ,
505544 ident. span ,
506- NonUpperCaseGlobal { sort, name, sub } ,
545+ NonUpperCaseGlobal { sort, name, sub : sub ( ident . span ) , usages } ,
507546 ) ;
508547 }
509548 }
@@ -516,26 +555,36 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
516555 hir:: ItemKind :: Static ( _, ident, ..)
517556 if !ast:: attr:: contains_name ( attrs, sym:: no_mangle) =>
518557 {
519- NonUpperCaseGlobals :: check_upper_case ( cx, "static variable" , & ident) ;
558+ NonUpperCaseGlobals :: check_upper_case (
559+ cx,
560+ "static variable" ,
561+ Some ( it. owner_id . def_id ) ,
562+ & ident,
563+ ) ;
520564 }
521565 hir:: ItemKind :: Const ( ident, ..) => {
522- NonUpperCaseGlobals :: check_upper_case ( cx, "constant" , & ident) ;
566+ NonUpperCaseGlobals :: check_upper_case (
567+ cx,
568+ "constant" ,
569+ Some ( it. owner_id . def_id ) ,
570+ & ident,
571+ ) ;
523572 }
524573 _ => { }
525574 }
526575 }
527576
528577 fn check_trait_item ( & mut self , cx : & LateContext < ' _ > , ti : & hir:: TraitItem < ' _ > ) {
529578 if let hir:: TraitItemKind :: Const ( ..) = ti. kind {
530- NonUpperCaseGlobals :: check_upper_case ( cx, "associated constant" , & ti. ident ) ;
579+ NonUpperCaseGlobals :: check_upper_case ( cx, "associated constant" , None , & ti. ident ) ;
531580 }
532581 }
533582
534583 fn check_impl_item ( & mut self , cx : & LateContext < ' _ > , ii : & hir:: ImplItem < ' _ > ) {
535584 if let hir:: ImplItemKind :: Const ( ..) = ii. kind
536585 && !assoc_item_in_trait_impl ( cx, ii)
537586 {
538- NonUpperCaseGlobals :: check_upper_case ( cx, "associated constant" , & ii. ident ) ;
587+ NonUpperCaseGlobals :: check_upper_case ( cx, "associated constant" , None , & ii. ident ) ;
539588 }
540589 }
541590
@@ -551,6 +600,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
551600 NonUpperCaseGlobals :: check_upper_case (
552601 cx,
553602 "constant in pattern" ,
603+ None ,
554604 & segment. ident ,
555605 ) ;
556606 }
@@ -560,7 +610,12 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
560610
561611 fn check_generic_param ( & mut self , cx : & LateContext < ' _ > , param : & hir:: GenericParam < ' _ > ) {
562612 if let GenericParamKind :: Const { .. } = param. kind {
563- NonUpperCaseGlobals :: check_upper_case ( cx, "const parameter" , & param. name . ident ( ) ) ;
613+ NonUpperCaseGlobals :: check_upper_case (
614+ cx,
615+ "const parameter" ,
616+ Some ( param. def_id ) ,
617+ & param. name . ident ( ) ,
618+ ) ;
564619 }
565620 }
566621}
0 commit comments