1
1
use clippy_config:: types:: DisallowedPath ;
2
- use clippy_utils:: diagnostics:: span_lint_and_then;
2
+ use clippy_utils:: diagnostics:: { span_lint_and_then, span_lint_hir_and_then } ;
3
3
use clippy_utils:: macros:: macro_backtrace;
4
4
use rustc_ast:: Attribute ;
5
5
use rustc_data_structures:: fx:: FxHashSet ;
6
+ use rustc_errors:: Diagnostic ;
6
7
use rustc_hir:: def_id:: DefIdMap ;
7
- use rustc_hir:: { Expr , ExprKind , ForeignItem , HirId , ImplItem , Item , Pat , Path , Stmt , TraitItem , Ty } ;
8
+ use rustc_hir:: {
9
+ Expr , ExprKind , ForeignItem , HirId , ImplItem , Item , ItemKind , OwnerId , Pat , Path , Stmt , TraitItem , Ty ,
10
+ } ;
8
11
use rustc_lint:: { LateContext , LateLintPass } ;
9
12
use rustc_session:: impl_lint_pass;
10
- use rustc_span:: { ExpnId , Span } ;
13
+ use rustc_span:: { ExpnId , MacroKind , Span } ;
11
14
12
15
declare_clippy_lint ! {
13
16
/// ### What it does
@@ -57,6 +60,10 @@ pub struct DisallowedMacros {
57
60
conf_disallowed : Vec < DisallowedPath > ,
58
61
disallowed : DefIdMap < usize > ,
59
62
seen : FxHashSet < ExpnId > ,
63
+
64
+ // Track the most recently seen node that can have a `derive` attribute.
65
+ // Needed to use the correct lint level.
66
+ derive_src : Option < OwnerId > ,
60
67
}
61
68
62
69
impl DisallowedMacros {
@@ -65,10 +72,11 @@ impl DisallowedMacros {
65
72
conf_disallowed,
66
73
disallowed : DefIdMap :: default ( ) ,
67
74
seen : FxHashSet :: default ( ) ,
75
+ derive_src : None ,
68
76
}
69
77
}
70
78
71
- fn check ( & mut self , cx : & LateContext < ' _ > , span : Span ) {
79
+ fn check ( & mut self , cx : & LateContext < ' _ > , span : Span , derive_src : Option < OwnerId > ) {
72
80
if self . conf_disallowed . is_empty ( ) {
73
81
return ;
74
82
}
@@ -80,18 +88,26 @@ impl DisallowedMacros {
80
88
81
89
if let Some ( & index) = self . disallowed . get ( & mac. def_id ) {
82
90
let conf = & self . conf_disallowed [ index] ;
83
-
84
- span_lint_and_then (
85
- cx,
86
- DISALLOWED_MACROS ,
87
- mac. span ,
88
- & format ! ( "use of a disallowed macro `{}`" , conf. path( ) ) ,
89
- |diag| {
90
- if let Some ( reason) = conf. reason ( ) {
91
- diag. note ( reason) ;
92
- }
93
- } ,
94
- ) ;
91
+ let msg = format ! ( "use of a disallowed macro `{}`" , conf. path( ) ) ;
92
+ let add_note = |diag : & mut Diagnostic | {
93
+ if let Some ( reason) = conf. reason ( ) {
94
+ diag. note ( reason) ;
95
+ }
96
+ } ;
97
+ if matches ! ( mac. kind, MacroKind :: Derive )
98
+ && let Some ( derive_src) = derive_src
99
+ {
100
+ span_lint_hir_and_then (
101
+ cx,
102
+ DISALLOWED_MACROS ,
103
+ cx. tcx . local_def_id_to_hir_id ( derive_src. def_id ) ,
104
+ mac. span ,
105
+ & msg,
106
+ add_note,
107
+ ) ;
108
+ } else {
109
+ span_lint_and_then ( cx, DISALLOWED_MACROS , mac. span , & msg, add_note) ;
110
+ }
95
111
}
96
112
}
97
113
}
@@ -110,49 +126,57 @@ impl LateLintPass<'_> for DisallowedMacros {
110
126
}
111
127
112
128
fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
113
- self . check ( cx, expr. span ) ;
129
+ self . check ( cx, expr. span , None ) ;
114
130
// `$t + $t` can have the context of $t, check also the span of the binary operator
115
131
if let ExprKind :: Binary ( op, ..) = expr. kind {
116
- self . check ( cx, op. span ) ;
132
+ self . check ( cx, op. span , None ) ;
117
133
}
118
134
}
119
135
120
136
fn check_stmt ( & mut self , cx : & LateContext < ' _ > , stmt : & Stmt < ' _ > ) {
121
- self . check ( cx, stmt. span ) ;
137
+ self . check ( cx, stmt. span , None ) ;
122
138
}
123
139
124
140
fn check_ty ( & mut self , cx : & LateContext < ' _ > , ty : & Ty < ' _ > ) {
125
- self . check ( cx, ty. span ) ;
141
+ self . check ( cx, ty. span , None ) ;
126
142
}
127
143
128
144
fn check_pat ( & mut self , cx : & LateContext < ' _ > , pat : & Pat < ' _ > ) {
129
- self . check ( cx, pat. span ) ;
145
+ self . check ( cx, pat. span , None ) ;
130
146
}
131
147
132
148
fn check_item ( & mut self , cx : & LateContext < ' _ > , item : & Item < ' _ > ) {
133
- self . check ( cx, item. span ) ;
134
- self . check ( cx, item. vis_span ) ;
149
+ self . check ( cx, item. span , self . derive_src ) ;
150
+ self . check ( cx, item. vis_span , None ) ;
151
+
152
+ if matches ! (
153
+ item. kind,
154
+ ItemKind :: Struct ( ..) | ItemKind :: Enum ( ..) | ItemKind :: Union ( ..)
155
+ ) && macro_backtrace ( item. span ) . all ( |m| !matches ! ( m. kind, MacroKind :: Derive ) )
156
+ {
157
+ self . derive_src = Some ( item. owner_id ) ;
158
+ }
135
159
}
136
160
137
161
fn check_foreign_item ( & mut self , cx : & LateContext < ' _ > , item : & ForeignItem < ' _ > ) {
138
- self . check ( cx, item. span ) ;
139
- self . check ( cx, item. vis_span ) ;
162
+ self . check ( cx, item. span , None ) ;
163
+ self . check ( cx, item. vis_span , None ) ;
140
164
}
141
165
142
166
fn check_impl_item ( & mut self , cx : & LateContext < ' _ > , item : & ImplItem < ' _ > ) {
143
- self . check ( cx, item. span ) ;
144
- self . check ( cx, item. vis_span ) ;
167
+ self . check ( cx, item. span , None ) ;
168
+ self . check ( cx, item. vis_span , None ) ;
145
169
}
146
170
147
171
fn check_trait_item ( & mut self , cx : & LateContext < ' _ > , item : & TraitItem < ' _ > ) {
148
- self . check ( cx, item. span ) ;
172
+ self . check ( cx, item. span , None ) ;
149
173
}
150
174
151
175
fn check_path ( & mut self , cx : & LateContext < ' _ > , path : & Path < ' _ > , _: HirId ) {
152
- self . check ( cx, path. span ) ;
176
+ self . check ( cx, path. span , None ) ;
153
177
}
154
178
155
179
fn check_attribute ( & mut self , cx : & LateContext < ' _ > , attr : & Attribute ) {
156
- self . check ( cx, attr. span ) ;
180
+ self . check ( cx, attr. span , self . derive_src ) ;
157
181
}
158
182
}
0 commit comments