@@ -8,7 +8,7 @@ use rustc_errors::{Applicability, Diag, SuggestionStyle};
8
8
use rustc_hir:: { ItemKind , Node } ;
9
9
use rustc_lexer:: TokenKind ;
10
10
use rustc_lint:: LateContext ;
11
- use rustc_span:: { ExpnKind , InnerSpan , Span , SpanData } ;
11
+ use rustc_span:: { BytePos , ExpnKind , InnerSpan , Span , SpanData } ;
12
12
13
13
use super :: { EMPTY_LINE_AFTER_DOC_COMMENTS , EMPTY_LINE_AFTER_OUTER_ATTR } ;
14
14
@@ -144,6 +144,30 @@ impl<'a> Gap<'a> {
144
144
prev_chunk,
145
145
} )
146
146
}
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
+ }
147
171
}
148
172
149
173
/// 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 {
192
216
return false ;
193
217
} ;
194
218
let empty_lines = || gaps. iter ( ) . flat_map ( |gap| gap. empty_lines . iter ( ) . copied ( ) ) ;
219
+ let contiguous_empty_lines = || gaps. iter ( ) . flat_map ( Gap :: contiguous_empty_lines) ;
195
220
let mut has_comment = false ;
196
221
let mut has_attr = false ;
197
222
for gap in gaps {
@@ -227,7 +252,9 @@ fn check_gaps(cx: &LateContext<'_>, gaps: &[Gap<'_>]) -> bool {
227
252
228
253
diag. multipart_suggestion_with_style (
229
254
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 ( ) ,
231
258
Applicability :: MaybeIncorrect ,
232
259
SuggestionStyle :: HideCodeAlways ,
233
260
) ;
0 commit comments