Use contiguous spans for empty_line_after_* suggestion
Replacing an empty span (which an empty line is) with an empty string triggers a debug assertion in rustc. This fixes the debug assertion by using contiguous spans, with the same resulting suggestion.
This commit is contained in:
parent
43e3384581
commit
7f30dafa9b
@ -8,7 +8,7 @@
|
|||||||
use rustc_hir::{ItemKind, Node};
|
use rustc_hir::{ItemKind, Node};
|
||||||
use rustc_lexer::TokenKind;
|
use rustc_lexer::TokenKind;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::{ExpnKind, InnerSpan, Span, SpanData};
|
use rustc_span::{BytePos, ExpnKind, InnerSpan, Span, SpanData};
|
||||||
|
|
||||||
use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
|
use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
|
||||||
|
|
||||||
@ -144,6 +144,19 @@ fn new(cx: &LateContext<'_>, prev_chunk: &'a [Stop], next_chunk: &'a [Stop]) ->
|
|||||||
prev_chunk,
|
prev_chunk,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn contiguous_empty_lines(&self) -> impl Iterator<Item = Span> + '_ {
|
||||||
|
self.empty_lines
|
||||||
|
// The `+ BytePos(1)` means "next line", because each empty line span is "N:1-N:1".
|
||||||
|
.chunk_by(|a, b| a.hi() + BytePos(1) == b.lo())
|
||||||
|
.map(|chunk| {
|
||||||
|
let first = chunk.first().expect("at least one empty line");
|
||||||
|
let last = chunk.last().expect("at least one empty line");
|
||||||
|
// The BytePos subtraction here is safe, as before an empty line, there must be at least one
|
||||||
|
// attribute/comment. The span needs to start at the end of the previous line.
|
||||||
|
first.with_lo(first.lo() - BytePos(1)).with_hi(last.hi())
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the node the attributes/docs apply to is the first in the module/crate suggest converting
|
/// If the node the attributes/docs apply to is the first in the module/crate suggest converting
|
||||||
@ -192,6 +205,7 @@ fn check_gaps(cx: &LateContext<'_>, gaps: &[Gap<'_>]) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
let empty_lines = || gaps.iter().flat_map(|gap| gap.empty_lines.iter().copied());
|
let empty_lines = || gaps.iter().flat_map(|gap| gap.empty_lines.iter().copied());
|
||||||
|
let contiguous_empty_lines = || gaps.iter().flat_map(Gap::contiguous_empty_lines);
|
||||||
let mut has_comment = false;
|
let mut has_comment = false;
|
||||||
let mut has_attr = false;
|
let mut has_attr = false;
|
||||||
for gap in gaps {
|
for gap in gaps {
|
||||||
@ -227,7 +241,9 @@ fn check_gaps(cx: &LateContext<'_>, gaps: &[Gap<'_>]) -> bool {
|
|||||||
|
|
||||||
diag.multipart_suggestion_with_style(
|
diag.multipart_suggestion_with_style(
|
||||||
format!("if the empty {lines} {are} unintentional remove {them}"),
|
format!("if the empty {lines} {are} unintentional remove {them}"),
|
||||||
empty_lines().map(|empty_line| (empty_line, String::new())).collect(),
|
contiguous_empty_lines()
|
||||||
|
.map(|empty_lines| (empty_lines, String::new()))
|
||||||
|
.collect(),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
SuggestionStyle::HideCodeAlways,
|
SuggestionStyle::HideCodeAlways,
|
||||||
);
|
);
|
||||||
|
@ -51,6 +51,11 @@ mod foo {}
|
|||||||
// Still lint cases where the empty line does not immediately follow the attribute
|
// Still lint cases where the empty line does not immediately follow the attribute
|
||||||
fn comment_before_empty_line() {}
|
fn comment_before_empty_line() {}
|
||||||
|
|
||||||
|
//~v empty_line_after_outer_attr
|
||||||
|
#[allow(unused)]
|
||||||
|
// This comment is isolated
|
||||||
|
pub fn isolated_comment() {}
|
||||||
|
|
||||||
#[doc = "
|
#[doc = "
|
||||||
Returns the escaped value of the textual representation of
|
Returns the escaped value of the textual representation of
|
||||||
|
|
||||||
|
@ -54,6 +54,11 @@ mod foo {}
|
|||||||
// Still lint cases where the empty line does not immediately follow the attribute
|
// Still lint cases where the empty line does not immediately follow the attribute
|
||||||
fn comment_before_empty_line() {}
|
fn comment_before_empty_line() {}
|
||||||
|
|
||||||
|
//~v empty_line_after_outer_attr
|
||||||
|
#[allow(unused)]
|
||||||
|
// This comment is isolated
|
||||||
|
pub fn isolated_comment() {}
|
||||||
|
|
||||||
#[doc = "
|
#[doc = "
|
||||||
Returns the escaped value of the textual representation of
|
Returns the escaped value of the textual representation of
|
||||||
|
|
||||||
|
@ -60,6 +60,13 @@ mod foo {}
|
|||||||
|
|
||||||
fn comment_before_empty_line() {}
|
fn comment_before_empty_line() {}
|
||||||
|
|
||||||
|
//~v empty_line_after_outer_attr
|
||||||
|
#[allow(unused)]
|
||||||
|
|
||||||
|
// This comment is isolated
|
||||||
|
|
||||||
|
pub fn isolated_comment() {}
|
||||||
|
|
||||||
#[doc = "
|
#[doc = "
|
||||||
Returns the escaped value of the textual representation of
|
Returns the escaped value of the textual representation of
|
||||||
|
|
||||||
|
@ -99,5 +99,18 @@ LL | fn comment_before_empty_line() {}
|
|||||||
|
|
|
|
||||||
= help: if the empty line is unintentional remove it
|
= help: if the empty line is unintentional remove it
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: empty lines after outer attribute
|
||||||
|
--> tests/ui/empty_line_after/outer_attribute.rs:64:1
|
||||||
|
|
|
||||||
|
LL | / #[allow(unused)]
|
||||||
|
LL | |
|
||||||
|
LL | | // This comment is isolated
|
||||||
|
LL | |
|
||||||
|
| |_
|
||||||
|
LL | pub fn isolated_comment() {}
|
||||||
|
| ------------------------- the attribute applies to this function
|
||||||
|
|
|
||||||
|
= help: if the empty lines are unintentional remove them
|
||||||
|
|
||||||
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user