11use clippy_utils:: diagnostics:: span_lint_and_help;
22use rustc_ast:: {
3+ node_id:: NodeSet ,
34 visit:: { walk_block, walk_item, Visitor } ,
4- Block , Crate , Inline , Item , ItemKind , ModKind ,
5+ Block , Crate , Inline , Item , ItemKind , ModKind , NodeId ,
56} ;
67use rustc_lint:: { EarlyContext , EarlyLintPass , LintContext } ;
78use rustc_middle:: lint:: in_external_macro;
@@ -52,23 +53,42 @@ declare_clippy_lint! {
5253 /// }
5354 /// }
5455 /// ```
56+ /// lib.rs:
57+ /// ```rust,ignore
58+ /// pub mod a;
59+ /// ```
5560 #[ clippy:: version = "1.70.0" ]
5661 pub EXCESSIVE_NESTING ,
5762 restriction,
5863 "checks for blocks nested beyond a certain threshold"
5964}
6065impl_lint_pass ! ( ExcessiveNesting => [ EXCESSIVE_NESTING ] ) ;
6166
62- #[ derive( Clone , Copy ) ]
67+ #[ derive( Clone ) ]
6368pub struct ExcessiveNesting {
6469 pub excessive_nesting_threshold : u64 ,
70+ pub nodes : NodeSet ,
71+ }
72+
73+ impl ExcessiveNesting {
74+ pub fn check_node_id ( & self , cx : & EarlyContext < ' _ > , span : Span , node_id : NodeId ) {
75+ if self . nodes . contains ( & node_id) {
76+ span_lint_and_help (
77+ cx,
78+ EXCESSIVE_NESTING ,
79+ span,
80+ "this block is too nested" ,
81+ None ,
82+ "try refactoring your code to minimize nesting" ,
83+ ) ;
84+ }
85+ }
6586}
6687
6788impl EarlyLintPass for ExcessiveNesting {
6889 fn check_crate ( & mut self , cx : & EarlyContext < ' _ > , krate : & Crate ) {
69- let conf = self ;
7090 let mut visitor = NestingVisitor {
71- conf,
91+ conf : self ,
7292 cx,
7393 nest_level : 0 ,
7494 } ;
@@ -77,25 +97,26 @@ impl EarlyLintPass for ExcessiveNesting {
7797 visitor. visit_item ( item) ;
7898 }
7999 }
100+
101+ fn check_block ( & mut self , cx : & EarlyContext < ' _ > , block : & Block ) {
102+ self . check_node_id ( cx, block. span , block. id ) ;
103+ }
104+
105+ fn check_item ( & mut self , cx : & EarlyContext < ' _ > , item : & Item ) {
106+ self . check_node_id ( cx, item. span , item. id ) ;
107+ }
80108}
81109
82110struct NestingVisitor < ' conf , ' cx > {
83- conf : & ' conf ExcessiveNesting ,
111+ conf : & ' conf mut ExcessiveNesting ,
84112 cx : & ' cx EarlyContext < ' cx > ,
85113 nest_level : u64 ,
86114}
87115
88116impl NestingVisitor < ' _ , ' _ > {
89- fn check_indent ( & self , span : Span ) -> bool {
117+ fn check_indent ( & mut self , span : Span , id : NodeId ) -> bool {
90118 if self . nest_level > self . conf . excessive_nesting_threshold && !in_external_macro ( self . cx . sess ( ) , span) {
91- span_lint_and_help (
92- self . cx ,
93- EXCESSIVE_NESTING ,
94- span,
95- "this block is too nested" ,
96- None ,
97- "try refactoring your code to minimize nesting" ,
98- ) ;
119+ self . conf . nodes . insert ( id) ;
99120
100121 return true ;
101122 }
@@ -106,14 +127,13 @@ impl NestingVisitor<'_, '_> {
106127
107128impl < ' conf , ' cx > Visitor < ' _ > for NestingVisitor < ' conf , ' cx > {
108129 fn visit_block ( & mut self , block : & Block ) {
109- // TODO: Probably not necessary, since any block would already be ignored by the check in visit_item
110130 if block. span . from_expansion ( ) {
111131 return ;
112132 }
113133
114134 self . nest_level += 1 ;
115135
116- if !self . check_indent ( block. span ) {
136+ if !self . check_indent ( block. span , block . id ) {
117137 walk_block ( self , block) ;
118138 }
119139
@@ -129,7 +149,7 @@ impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> {
129149 ItemKind :: Trait ( _) | ItemKind :: Impl ( _) | ItemKind :: Mod ( .., ModKind :: Loaded ( _, Inline :: Yes , _) ) => {
130150 self . nest_level += 1 ;
131151
132- if !self . check_indent ( item. span ) {
152+ if !self . check_indent ( item. span , item . id ) {
133153 walk_item ( self , item) ;
134154 }
135155
0 commit comments