@@ -2,8 +2,9 @@ use rustc_abi::ExternAbi;
2
2
use rustc_attr_data_structures:: { AttributeKind , ReprAttr } ;
3
3
use rustc_attr_parsing:: AttributeParser ;
4
4
use rustc_hir:: def:: { DefKind , Res } ;
5
- use rustc_hir:: intravisit:: FnKind ;
5
+ use rustc_hir:: intravisit:: { FnKind , Visitor } ;
6
6
use rustc_hir:: { AttrArgs , AttrItem , Attribute , GenericParamKind , PatExprKind , PatKind } ;
7
+ use rustc_middle:: hir:: nested_filter:: All ;
7
8
use rustc_middle:: ty;
8
9
use rustc_session:: config:: CrateType ;
9
10
use rustc_session:: { declare_lint, declare_lint_pass} ;
@@ -13,7 +14,7 @@ use {rustc_ast as ast, rustc_hir as hir};
13
14
14
15
use crate :: lints:: {
15
16
NonCamelCaseType , NonCamelCaseTypeSub , NonSnakeCaseDiag , NonSnakeCaseDiagSub ,
16
- NonUpperCaseGlobal , NonUpperCaseGlobalSub ,
17
+ NonUpperCaseGlobal , NonUpperCaseGlobalSub , NonUpperCaseGlobalSubTool ,
17
18
} ;
18
19
use crate :: { EarlyContext , EarlyLintPass , LateContext , LateLintPass , LintContext } ;
19
20
@@ -489,21 +490,63 @@ declare_lint! {
489
490
declare_lint_pass ! ( NonUpperCaseGlobals => [ NON_UPPER_CASE_GLOBALS ] ) ;
490
491
491
492
impl 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 ) {
493
494
let name = ident. name . as_str ( ) ;
494
495
if name. chars ( ) . any ( |c| c. is_lowercase ( ) ) {
495
496
let uc = NonSnakeCase :: to_snake_case ( name) . to_uppercase ( ) ;
497
+
496
498
// We cannot provide meaningful suggestions
497
499
// if the characters are in the category of "Lowercase Letter".
498
500
let sub = if * name != uc {
499
- NonUpperCaseGlobalSub :: Suggestion { span : ident. span , replace : uc }
501
+ NonUpperCaseGlobalSub :: Suggestion { span : ident. span , replace : uc. clone ( ) }
500
502
} else {
501
503
NonUpperCaseGlobalSub :: Label { span : ident. span }
502
504
} ;
505
+
506
+ struct UsageCollector < ' a , ' tcx > {
507
+ cx : & ' tcx LateContext < ' a > ,
508
+ did : LocalDefId ,
509
+ collected : Vec < Span > ,
510
+ }
511
+
512
+ impl < ' v , ' tcx > Visitor < ' v > for UsageCollector < ' v , ' tcx > {
513
+ type NestedFilter = All ;
514
+
515
+ fn maybe_tcx ( & mut self ) -> Self :: MaybeTyCtxt {
516
+ self . cx . tcx
517
+ }
518
+
519
+ fn visit_path (
520
+ & mut self ,
521
+ path : & rustc_hir:: Path < ' v > ,
522
+ _id : rustc_hir:: HirId ,
523
+ ) -> Self :: Result {
524
+ for seg in path. segments {
525
+ if seg. res . opt_def_id ( ) == Some ( self . did . to_def_id ( ) ) {
526
+ self . collected . push ( seg. ident . span ) ;
527
+ }
528
+ }
529
+ }
530
+ }
531
+
532
+ let usages = if let Some ( did) = did
533
+ && * name != uc
534
+ {
535
+ let mut usage_collector = UsageCollector { cx, did, collected : Vec :: new ( ) } ;
536
+ cx. tcx . hir_walk_toplevel_module ( & mut usage_collector) ;
537
+ usage_collector
538
+ . collected
539
+ . into_iter ( )
540
+ . map ( |span| NonUpperCaseGlobalSubTool { span, replace : uc. clone ( ) } )
541
+ . collect ( )
542
+ } else {
543
+ vec ! [ ]
544
+ } ;
545
+
503
546
cx. emit_span_lint (
504
547
NON_UPPER_CASE_GLOBALS ,
505
548
ident. span ,
506
- NonUpperCaseGlobal { sort, name, sub } ,
549
+ NonUpperCaseGlobal { sort, name, sub, usages } ,
507
550
) ;
508
551
}
509
552
}
@@ -516,26 +559,36 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
516
559
hir:: ItemKind :: Static ( _, ident, ..)
517
560
if !ast:: attr:: contains_name ( attrs, sym:: no_mangle) =>
518
561
{
519
- NonUpperCaseGlobals :: check_upper_case ( cx, "static variable" , & ident) ;
562
+ NonUpperCaseGlobals :: check_upper_case (
563
+ cx,
564
+ "static variable" ,
565
+ Some ( it. owner_id . def_id ) ,
566
+ & ident,
567
+ ) ;
520
568
}
521
569
hir:: ItemKind :: Const ( ident, ..) => {
522
- NonUpperCaseGlobals :: check_upper_case ( cx, "constant" , & ident) ;
570
+ NonUpperCaseGlobals :: check_upper_case (
571
+ cx,
572
+ "constant" ,
573
+ Some ( it. owner_id . def_id ) ,
574
+ & ident,
575
+ ) ;
523
576
}
524
577
_ => { }
525
578
}
526
579
}
527
580
528
581
fn check_trait_item ( & mut self , cx : & LateContext < ' _ > , ti : & hir:: TraitItem < ' _ > ) {
529
582
if let hir:: TraitItemKind :: Const ( ..) = ti. kind {
530
- NonUpperCaseGlobals :: check_upper_case ( cx, "associated constant" , & ti. ident ) ;
583
+ NonUpperCaseGlobals :: check_upper_case ( cx, "associated constant" , None , & ti. ident ) ;
531
584
}
532
585
}
533
586
534
587
fn check_impl_item ( & mut self , cx : & LateContext < ' _ > , ii : & hir:: ImplItem < ' _ > ) {
535
588
if let hir:: ImplItemKind :: Const ( ..) = ii. kind
536
589
&& !assoc_item_in_trait_impl ( cx, ii)
537
590
{
538
- NonUpperCaseGlobals :: check_upper_case ( cx, "associated constant" , & ii. ident ) ;
591
+ NonUpperCaseGlobals :: check_upper_case ( cx, "associated constant" , None , & ii. ident ) ;
539
592
}
540
593
}
541
594
@@ -551,6 +604,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
551
604
NonUpperCaseGlobals :: check_upper_case (
552
605
cx,
553
606
"constant in pattern" ,
607
+ None ,
554
608
& segment. ident ,
555
609
) ;
556
610
}
@@ -560,7 +614,12 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
560
614
561
615
fn check_generic_param ( & mut self , cx : & LateContext < ' _ > , param : & hir:: GenericParam < ' _ > ) {
562
616
if let GenericParamKind :: Const { .. } = param. kind {
563
- NonUpperCaseGlobals :: check_upper_case ( cx, "const parameter" , & param. name . ident ( ) ) ;
617
+ NonUpperCaseGlobals :: check_upper_case (
618
+ cx,
619
+ "const parameter" ,
620
+ Some ( param. def_id ) ,
621
+ & param. name . ident ( ) ,
622
+ ) ;
564
623
}
565
624
}
566
625
}
0 commit comments