@@ -10,7 +10,7 @@ use rustc_errors::{Applicability, Diag, SuggestionStyle};
1010use rustc_lexer:: TokenKind ;
1111use rustc_lint:: { EarlyContext , EarlyLintPass , LintContext } ;
1212use 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 } ;
1414
1515declare_clippy_lint ! {
1616 /// ### What it does
@@ -129,18 +129,54 @@ struct Stop {
129129 kind : StopKind ,
130130 first : usize ,
131131 last : usize ,
132+ ident : Option < Ident > ,
132133}
133134
134135impl Stop {
135- fn convert_to_inner ( & self ) -> ( Span , String ) {
136+ fn could_only_be_outer_attr ( & self ) -> bool {
137+ if let Some ( ident) = self . ident {
138+ return matches ! (
139+ ident. name,
140+ // Cannot be used at crate level
141+ sym:: repr | sym:: test | sym:: derive | sym:: automatically_derived | sym:: macro_export |
142+ sym:: on_unimplemented | sym:: do_not_recommend | sym:: path | sym:: panic_handler | sym:: global_allocator |
143+ // Only has an effect on items but not throgh compile errors
144+ sym:: ignore | sym:: should_panic | sym:: proc_macro | sym:: proc_macro_derive | sym:: proc_macro_attribute |
145+ // Has no effect when applied to a module
146+ sym:: must_use |
147+ // Should be applied to a foreign function or static
148+ sym:: link_name | sym:: link_ordinal | sym:: link_section |
149+ // Should be applied to an `extern crate` item
150+ sym:: no_link |
151+ // Should be applied to a free function, impl method or static
152+ sym:: export_name | sym:: no_mangle |
153+ // Should be applied to a `static` variable
154+ sym:: used |
155+ // Should be applied to function or closure
156+ sym:: inline |
157+ // Should be applied to a function definition
158+ sym:: cold | sym:: target_feature | sym:: track_caller | sym:: instruction_set |
159+ // Only has an effect on modules
160+ sym:: no_implicit_prelude | sym:: debugger_visualizer |
161+ // Should be applied to a struct or enum
162+ sym:: non_exhaustive
163+ ) ;
164+ }
165+ false
166+ }
167+
168+ fn convert_to_inner ( & self ) -> Option < ( Span , String ) > {
169+ if self . could_only_be_outer_attr ( ) {
170+ return None ;
171+ }
136172 let inner = match self . kind {
137173 // #![...]
138174 StopKind :: Attr => InnerSpan :: new ( 1 , 1 ) ,
139175 // /// or /**
140176 // ^ ^
141177 StopKind :: Doc ( _) => InnerSpan :: new ( 2 , 3 ) ,
142178 } ;
143- ( self . span . from_inner ( inner) , "!" . into ( ) )
179+ Some ( ( self . span . from_inner ( inner) , "!" . into ( ) ) )
144180 }
145181
146182 fn comment_out ( & self , cx : & EarlyContext < ' _ > , suggestions : & mut Vec < ( Span , String ) > ) {
@@ -177,6 +213,7 @@ impl Stop {
177213 } ,
178214 first : file. lookup_line ( file. relative_position ( lo) ) ?,
179215 last : file. lookup_line ( file. relative_position ( hi) ) ?,
216+ ident : attr. ident ( ) ,
180217 } )
181218 }
182219}
@@ -356,6 +393,12 @@ impl EmptyLineAfter {
356393 if let Some ( parent) = self . items . iter ( ) . rev ( ) . nth ( 1 )
357394 && ( parent. kind == "module" || parent. kind == "crate" )
358395 && parent. mod_items == Some ( id)
396+ && let suggestions = gaps
397+ . iter ( )
398+ . flat_map ( |gap| gap. prev_chunk )
399+ . filter_map ( Stop :: convert_to_inner)
400+ . collect :: < Vec < ( Span , String ) > > ( )
401+ && !suggestions. is_empty ( )
359402 {
360403 let desc = if parent. kind == "module" {
361404 "parent module"
@@ -367,10 +410,7 @@ impl EmptyLineAfter {
367410 StopKind :: Attr => format ! ( "if the attribute should apply to the {desc} use an inner attribute" ) ,
368411 StopKind :: Doc ( _) => format ! ( "if the comment should document the {desc} use an inner doc comment" ) ,
369412 } ,
370- gaps. iter ( )
371- . flat_map ( |gap| gap. prev_chunk )
372- . map ( Stop :: convert_to_inner)
373- . collect ( ) ,
413+ suggestions,
374414 Applicability :: MaybeIncorrect ,
375415 ) ;
376416 }
@@ -425,6 +465,7 @@ impl EmptyLineAfter {
425465 first : line. line ,
426466 // last doesn't need to be accurate here, we don't compare it with anything
427467 last : line. line ,
468+ ident : None ,
428469 } ) ;
429470 }
430471
0 commit comments