@@ -10,7 +10,7 @@ use rustc_errors::{Applicability, Diag, SuggestionStyle};
10
10
use rustc_lexer:: TokenKind ;
11
11
use rustc_lint:: { EarlyContext , EarlyLintPass , LintContext } ;
12
12
use rustc_session:: impl_lint_pass;
13
- use rustc_span:: { BytePos , ExpnKind , Ident , InnerSpan , Span , SpanData , Symbol , kw} ;
13
+ use rustc_span:: { BytePos , ExpnKind , Ident , InnerSpan , Span , SpanData , Symbol , kw, sym } ;
14
14
15
15
declare_clippy_lint ! {
16
16
/// ### What it does
@@ -129,18 +129,63 @@ struct Stop {
129
129
kind : StopKind ,
130
130
first : usize ,
131
131
last : usize ,
132
+ name : Option < Symbol > ,
132
133
}
133
134
134
135
impl Stop {
135
- fn convert_to_inner ( & self ) -> ( Span , String ) {
136
+ fn is_outer_attr_only ( & self ) -> bool {
137
+ let Some ( name) = self . name else {
138
+ return false ;
139
+ } ;
140
+ // Check if the attribute only has effect when as an outer attribute
141
+ // The below attributes are collected from the builtin attributes of The Rust Reference
142
+ // https://doc.rust-lang.org/reference/attributes.html#r-attributes.builtin
143
+ // And the comments below are from compiler errors and warnings
144
+ matches ! (
145
+ name,
146
+ // Cannot be used at crate level
147
+ sym:: repr | sym:: test | sym:: derive | sym:: automatically_derived | sym:: path | sym:: global_allocator |
148
+ // Only has an effect on macro definitions
149
+ sym:: macro_export |
150
+ // Only be applied to trait definitions
151
+ sym:: on_unimplemented |
152
+ // Only be placed on trait implementations
153
+ sym:: do_not_recommend |
154
+ // Only has an effect on items
155
+ sym:: ignore | sym:: should_panic | sym:: proc_macro | sym:: proc_macro_derive | sym:: proc_macro_attribute |
156
+ // Has no effect when applied to a module
157
+ sym:: must_use |
158
+ // Should be applied to a foreign function or static
159
+ sym:: link_name | sym:: link_ordinal | sym:: link_section |
160
+ // Should be applied to an `extern crate` item
161
+ sym:: no_link |
162
+ // Should be applied to a free function, impl method or static
163
+ sym:: export_name | sym:: no_mangle |
164
+ // Should be applied to a `static` variable
165
+ sym:: used |
166
+ // Should be applied to function or closure
167
+ sym:: inline |
168
+ // Should be applied to a function definition
169
+ sym:: cold | sym:: target_feature | sym:: track_caller | sym:: instruction_set |
170
+ // Should be applied to a struct or enum
171
+ sym:: non_exhaustive |
172
+ // Note: No any warning when it as an inner attribute, but it has no effect
173
+ sym:: panic_handler
174
+ )
175
+ }
176
+
177
+ fn convert_to_inner ( & self ) -> Option < ( Span , String ) > {
178
+ if self . is_outer_attr_only ( ) {
179
+ return None ;
180
+ }
136
181
let inner = match self . kind {
137
182
// #![...]
138
183
StopKind :: Attr => InnerSpan :: new ( 1 , 1 ) ,
139
184
// /// or /**
140
185
// ^ ^
141
186
StopKind :: Doc ( _) => InnerSpan :: new ( 2 , 3 ) ,
142
187
} ;
143
- ( self . span . from_inner ( inner) , "!" . into ( ) )
188
+ Some ( ( self . span . from_inner ( inner) , "!" . into ( ) ) )
144
189
}
145
190
146
191
fn comment_out ( & self , cx : & EarlyContext < ' _ > , suggestions : & mut Vec < ( Span , String ) > ) {
@@ -177,6 +222,7 @@ impl Stop {
177
222
} ,
178
223
first : file. lookup_line ( file. relative_position ( lo) ) ?,
179
224
last : file. lookup_line ( file. relative_position ( hi) ) ?,
225
+ name : attr. name ( ) ,
180
226
} )
181
227
}
182
228
}
@@ -356,6 +402,12 @@ impl EmptyLineAfter {
356
402
if let Some ( parent) = self . items . iter ( ) . rev ( ) . nth ( 1 )
357
403
&& ( parent. kind == "module" || parent. kind == "crate" )
358
404
&& parent. mod_items == Some ( id)
405
+ && let suggestions = gaps
406
+ . iter ( )
407
+ . flat_map ( |gap| gap. prev_chunk )
408
+ . filter_map ( Stop :: convert_to_inner)
409
+ . collect :: < Vec < _ > > ( )
410
+ && !suggestions. is_empty ( )
359
411
{
360
412
let desc = if parent. kind == "module" {
361
413
"parent module"
@@ -367,10 +419,7 @@ impl EmptyLineAfter {
367
419
StopKind :: Attr => format ! ( "if the attribute should apply to the {desc} use an inner attribute" ) ,
368
420
StopKind :: Doc ( _) => format ! ( "if the comment should document the {desc} use an inner doc comment" ) ,
369
421
} ,
370
- gaps. iter ( )
371
- . flat_map ( |gap| gap. prev_chunk )
372
- . map ( Stop :: convert_to_inner)
373
- . collect ( ) ,
422
+ suggestions,
374
423
Applicability :: MaybeIncorrect ,
375
424
) ;
376
425
}
@@ -425,6 +474,7 @@ impl EmptyLineAfter {
425
474
first : line. line ,
426
475
// last doesn't need to be accurate here, we don't compare it with anything
427
476
last : line. line ,
477
+ name : None ,
428
478
} ) ;
429
479
}
430
480
0 commit comments