@@ -8,7 +8,7 @@ use rustc_errors::{Applicability, Diag, SuggestionStyle};
88use rustc_hir:: { ItemKind , Node } ;
99use rustc_lexer:: TokenKind ;
1010use rustc_lint:: LateContext ;
11- use rustc_span:: { ExpnKind , InnerSpan , Span , SpanData } ;
11+ use rustc_span:: { BytePos , ExpnKind , InnerSpan , Span , SpanData } ;
1212
1313use super :: { EMPTY_LINE_AFTER_DOC_COMMENTS , EMPTY_LINE_AFTER_OUTER_ATTR } ;
1414
@@ -144,6 +144,30 @@ impl<'a> Gap<'a> {
144144 prev_chunk,
145145 } )
146146 }
147+
148+ fn contiguous_empty_lines ( & self ) -> Vec < Span > {
149+ let mut spans = Vec :: new ( ) ;
150+
151+ let mut prev_span = * self . empty_lines . first ( ) . expect ( "at least one empty line" ) ;
152+
153+ // The BytePos subtraction here is safe, as before an empty line, there must be at least one
154+ // attribute/comment.
155+ prev_span = prev_span. with_lo ( prev_span. lo ( ) - BytePos ( 1 ) ) ;
156+ for empty_line in & self . empty_lines {
157+ if empty_line. lo ( ) - prev_span. hi ( ) > BytePos ( 1 ) {
158+ // If the empty line doesn't immidiately follow the previous one, push the previous span...
159+ spans. push ( prev_span) ;
160+ // ...and start a new one
161+ prev_span = empty_line. with_lo ( empty_line. lo ( ) - BytePos ( 1 ) ) ;
162+ } else {
163+ // Otherwise, extend the previous span
164+ prev_span = prev_span. with_hi ( empty_line. hi ( ) ) ;
165+ }
166+ }
167+ spans. push ( prev_span) ;
168+
169+ spans
170+ }
147171}
148172
149173/// If the node the attributes/docs apply to is the first in the module/crate suggest converting
@@ -192,6 +216,7 @@ fn check_gaps(cx: &LateContext<'_>, gaps: &[Gap<'_>]) -> bool {
192216 return false ;
193217 } ;
194218 let empty_lines = || gaps. iter ( ) . flat_map ( |gap| gap. empty_lines . iter ( ) . copied ( ) ) ;
219+ let contiguous_empty_lines = || gaps. iter ( ) . flat_map ( |gap| gap. contiguous_empty_lines ( ) ) ;
195220 let mut has_comment = false ;
196221 let mut has_attr = false ;
197222 for gap in gaps {
@@ -227,7 +252,9 @@ fn check_gaps(cx: &LateContext<'_>, gaps: &[Gap<'_>]) -> bool {
227252
228253 diag. multipart_suggestion_with_style (
229254 format ! ( "if the empty {lines} {are} unintentional remove {them}" ) ,
230- empty_lines ( ) . map ( |empty_line| ( empty_line, String :: new ( ) ) ) . collect ( ) ,
255+ contiguous_empty_lines ( )
256+ . map ( |empty_lines| ( empty_lines, String :: new ( ) ) )
257+ . collect ( ) ,
231258 Applicability :: MaybeIncorrect ,
232259 SuggestionStyle :: HideCodeAlways ,
233260 ) ;
0 commit comments