1
1
use clippy_utils:: diagnostics:: span_lint_and_help;
2
2
use rustc_ast:: {
3
+ node_id:: NodeSet ,
3
4
visit:: { walk_block, walk_item, Visitor } ,
4
- Block , Crate , Inline , Item , ItemKind , ModKind ,
5
+ Block , Crate , Inline , Item , ItemKind , ModKind , NodeId ,
5
6
} ;
6
7
use rustc_lint:: { EarlyContext , EarlyLintPass , LintContext } ;
7
8
use rustc_middle:: lint:: in_external_macro;
@@ -52,23 +53,42 @@ declare_clippy_lint! {
52
53
/// }
53
54
/// }
54
55
/// ```
56
+ /// lib.rs:
57
+ /// ```rust,ignore
58
+ /// pub mod a;
59
+ /// ```
55
60
#[ clippy:: version = "1.70.0" ]
56
61
pub EXCESSIVE_NESTING ,
57
62
restriction,
58
63
"checks for blocks nested beyond a certain threshold"
59
64
}
60
65
impl_lint_pass ! ( ExcessiveNesting => [ EXCESSIVE_NESTING ] ) ;
61
66
62
- #[ derive( Clone , Copy ) ]
67
+ #[ derive( Clone ) ]
63
68
pub struct ExcessiveNesting {
64
69
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
+ }
65
86
}
66
87
67
88
impl EarlyLintPass for ExcessiveNesting {
68
89
fn check_crate ( & mut self , cx : & EarlyContext < ' _ > , krate : & Crate ) {
69
- let conf = self ;
70
90
let mut visitor = NestingVisitor {
71
- conf,
91
+ conf : self ,
72
92
cx,
73
93
nest_level : 0 ,
74
94
} ;
@@ -77,25 +97,26 @@ impl EarlyLintPass for ExcessiveNesting {
77
97
visitor. visit_item ( item) ;
78
98
}
79
99
}
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
+ }
80
108
}
81
109
82
110
struct NestingVisitor < ' conf , ' cx > {
83
- conf : & ' conf ExcessiveNesting ,
111
+ conf : & ' conf mut ExcessiveNesting ,
84
112
cx : & ' cx EarlyContext < ' cx > ,
85
113
nest_level : u64 ,
86
114
}
87
115
88
116
impl NestingVisitor < ' _ , ' _ > {
89
- fn check_indent ( & self , span : Span ) -> bool {
117
+ fn check_indent ( & mut self , span : Span , id : NodeId ) -> bool {
90
118
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) ;
99
120
100
121
return true ;
101
122
}
@@ -106,14 +127,13 @@ impl NestingVisitor<'_, '_> {
106
127
107
128
impl < ' conf , ' cx > Visitor < ' _ > for NestingVisitor < ' conf , ' cx > {
108
129
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
110
130
if block. span . from_expansion ( ) {
111
131
return ;
112
132
}
113
133
114
134
self . nest_level += 1 ;
115
135
116
- if !self . check_indent ( block. span ) {
136
+ if !self . check_indent ( block. span , block . id ) {
117
137
walk_block ( self , block) ;
118
138
}
119
139
@@ -129,7 +149,7 @@ impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> {
129
149
ItemKind :: Trait ( _) | ItemKind :: Impl ( _) | ItemKind :: Mod ( .., ModKind :: Loaded ( _, Inline :: Yes , _) ) => {
130
150
self . nest_level += 1 ;
131
151
132
- if !self . check_indent ( item. span ) {
152
+ if !self . check_indent ( item. span , item . id ) {
133
153
walk_item ( self , item) ;
134
154
}
135
155
0 commit comments