1
1
use clippy_utils:: diagnostics:: span_lint_and_help;
2
2
use rustc_ast:: {
3
- visit:: { walk_item, Visitor } ,
3
+ node_id:: NodeId ,
4
+ visit:: { walk_item, FnKind , Visitor } ,
4
5
* ,
5
6
} ;
6
7
use rustc_lint:: { EarlyContext , EarlyLintPass , LateContext , LateLintPass , LintContext } ;
@@ -30,28 +31,7 @@ declare_clippy_lint! {
30
31
nursery,
31
32
"checks for lines indented beyond a certain threshold"
32
33
}
33
- declare_clippy_lint ! {
34
- /// ### What it does
35
- ///
36
- /// Checks for lines which are longer than a certain threshold.
37
- ///
38
- /// ### Why is this bad?
39
- ///
40
- /// It can severely hinder readability. Running rustfmt will almost always get any
41
- /// lines below this threshold (or whatever you have set as max_width), but if it
42
- /// fails, it's probably a sign you should refactor.
43
- ///
44
- /// ### Example
45
- /// TODO
46
- /// Use instead:
47
- /// TODO
48
- #[ clippy:: version = "1.70.0" ]
49
- pub EXCESSIVE_WIDTH ,
50
- nursery,
51
- "checks for lines longer than a certain threshold"
52
- }
53
- // TODO: Split this into 2 structs
54
- impl_lint_pass ! ( ExcessiveIndentation => [ EXCESSIVE_INDENTATION , EXCESSIVE_WIDTH ] ) ;
34
+ impl_lint_pass ! ( ExcessiveIndentation => [ EXCESSIVE_INDENTATION ] ) ;
55
35
56
36
#[ derive( Clone , Copy ) ]
57
37
pub struct ExcessiveIndentation {
@@ -61,10 +41,17 @@ pub struct ExcessiveIndentation {
61
41
}
62
42
63
43
impl EarlyLintPass for ExcessiveIndentation {
64
- fn check_item ( & mut self , cx : & EarlyContext < ' _ > , item : & Item ) {
65
- match & item. kind {
66
- _ => ( ) ,
67
- }
44
+ fn check_crate ( & mut self , cx : & EarlyContext < ' _ > , krate : & Crate ) {
45
+ IndentationVisitor { indent : 0 } . visit_crate ( krate) ;
46
+ }
47
+ }
48
+
49
+ /// RAII guard to add 1 to our indent counter when constructed, and remove 1 when dropped.
50
+ struct IndentationGuard < ' i > ( & ' i mut u64 ) ;
51
+
52
+ impl < ' i > IndentationGuard < ' i > {
53
+ fn new ( indent : & ' i mut u64 ) -> Self {
54
+ Self ( indent)
68
55
}
69
56
}
70
57
@@ -73,24 +60,75 @@ struct IndentationVisitor {
73
60
}
74
61
75
62
impl Visitor < ' _ > for IndentationVisitor {
63
+ fn visit_foreign_item ( & mut self , item : & ForeignItem ) {
64
+ match & item. kind {
65
+ ForeignItemKind :: Static ( .., expr) => {
66
+ if let Some ( expr) = expr {
67
+ self . visit_expr ( & * expr)
68
+ }
69
+ } ,
70
+ ForeignItemKind :: Fn ( fk) if let Some ( block) = fk. body . as_ref ( ) => self . visit_block ( block) ,
71
+ _ => ( ) ,
72
+ }
73
+ }
74
+
75
+ fn visit_block ( & mut self , block : & Block ) {
76
+ IndentationGuard :: new ( & mut self . indent ) ;
77
+
78
+ todo ! ( ) ;
79
+ }
80
+
81
+ fn visit_expr ( & mut self , expr : & Expr ) {
82
+ todo ! ( ) ;
83
+ }
84
+
85
+ fn visit_fn ( & mut self , fk : FnKind < ' _ > , _: Span , _: NodeId ) {
86
+ IndentationGuard :: new ( & mut self . indent ) ;
87
+
88
+ match fk {
89
+ FnKind :: Fn ( .., block) if let Some ( block) = block => self . visit_block ( block) ,
90
+ FnKind :: Closure ( .., expr) => self . visit_expr ( expr) ,
91
+ _ => ( ) ,
92
+ }
93
+ }
94
+
95
+ fn visit_use_tree ( & mut self , use_tree : & UseTree , _: NodeId , _: bool ) {
96
+ // TODO: I don't think this should be linted, as some devious crate may decide to put some type
97
+ // nested within 10 modules. Maybe it can be optional using config?
98
+ IndentationGuard :: new ( & mut self . indent ) ;
99
+
100
+ if let UseTreeKind :: Nested ( use_trees) = & use_tree. kind {
101
+ for use_tree in use_trees {
102
+ self . visit_use_tree ( & use_tree. 0 , NodeId :: MAX , bool:: default ( ) ) ;
103
+ }
104
+ }
105
+ }
106
+
76
107
fn visit_crate ( & mut self , krate : & Crate ) {
77
- for item in krate. items {
78
- match item. kind {
108
+ for item in & krate. items {
109
+ match & item. kind {
79
110
// TODO:
80
111
// Use ✅
81
- // Static ❌
82
- // Const ❌
112
+ // Static ✅
113
+ // Const ✅
83
114
// Fn ❌
84
115
// Mod ❌
85
- // ForeignMod ❌
116
+ // ForeignMod ✅
86
117
// Enum ❌
87
118
// Struct ❌
88
119
// Union ❌
89
120
// Trait ❌
90
121
// Impl ❌
91
- // MacroDef ❓
92
- // Others don't increase indentation (unless your formatting is really weird) so they won't be included.
93
- ItemKind :: Use ( use_tree) => todo ! ( ) ,
122
+ // Others should never increase indentation (unless your formatting is really weird), so they won't be included.
123
+ ItemKind :: Use ( use_tree) => self . visit_use_tree ( use_tree, NodeId :: MAX , bool:: default ( ) ) ,
124
+ ItemKind :: Static ( static_item) if let Some ( expr) = static_item. expr . as_ref ( ) => self . visit_expr ( & * expr) ,
125
+ ItemKind :: Const ( const_item) if let Some ( expr) = const_item. expr . as_ref ( ) => self . visit_expr ( & * expr) ,
126
+ ItemKind :: Fn ( fk) if let Some ( block) = fk. body . as_ref ( ) => self . visit_block ( block) ,
127
+ ItemKind :: ForeignMod ( foreign_mod) => {
128
+ for item in & foreign_mod. items {
129
+ self . visit_foreign_item ( item)
130
+ }
131
+ } ,
94
132
_ => ( ) ,
95
133
}
96
134
}
0 commit comments