Account for fully overlapping multiline annotations
When two multiline span labels point at the same span, we special case the output to avoid weird behavior: ``` foo( _____^ |_____| || bar, || ); || ^ ||______| |______foo baz ``` instead showing ``` foo( _____^ | bar, | ); | ^ | | |______foo baz ```
This commit is contained in:
parent
925ca49cf1
commit
326ec800b9
5 changed files with 116 additions and 25 deletions
|
@ -243,6 +243,7 @@ impl EmitterWriter {
|
|||
end_col: hi.col_display,
|
||||
is_primary: span_label.is_primary,
|
||||
label: span_label.label.clone(),
|
||||
overlaps: false,
|
||||
};
|
||||
multiline_annotations.push((lo.file.clone(), ml.clone()));
|
||||
AnnotationType::Multiline(ml)
|
||||
|
@ -258,10 +259,7 @@ impl EmitterWriter {
|
|||
};
|
||||
|
||||
if !ann.is_multiline() {
|
||||
add_annotation_to_file(&mut output,
|
||||
lo.file,
|
||||
lo.line,
|
||||
ann);
|
||||
add_annotation_to_file(&mut output, lo.file, lo.line, ann);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -274,10 +272,12 @@ impl EmitterWriter {
|
|||
let ref mut a = item.1;
|
||||
// Move all other multiline annotations overlapping with this one
|
||||
// one level to the right.
|
||||
if &ann != a &&
|
||||
if !(ann.same_span(a)) &&
|
||||
num_overlap(ann.line_start, ann.line_end, a.line_start, a.line_end, true)
|
||||
{
|
||||
a.increase_depth();
|
||||
} else if ann.same_span(a) && &ann != a {
|
||||
a.overlaps = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -289,17 +289,44 @@ impl EmitterWriter {
|
|||
if ann.depth > max_depth {
|
||||
max_depth = ann.depth;
|
||||
}
|
||||
add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start());
|
||||
let middle = min(ann.line_start + 4, ann.line_end);
|
||||
for line in ann.line_start + 1..middle {
|
||||
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
|
||||
}
|
||||
if middle < ann.line_end - 1 {
|
||||
for line in ann.line_end - 1..ann.line_end {
|
||||
let mut end_ann = ann.as_end();
|
||||
if !ann.overlaps {
|
||||
// avoid output like
|
||||
//
|
||||
// | foo(
|
||||
// | _____^
|
||||
// | |_____|
|
||||
// | || bar,
|
||||
// | || );
|
||||
// | || ^
|
||||
// | ||______|
|
||||
// | |______foo
|
||||
// | baz
|
||||
//
|
||||
// and instead get
|
||||
//
|
||||
// | foo(
|
||||
// | _____^
|
||||
// | | bar,
|
||||
// | | );
|
||||
// | | ^
|
||||
// | | |
|
||||
// | |______foo
|
||||
// | baz
|
||||
add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start());
|
||||
let middle = min(ann.line_start + 4, ann.line_end);
|
||||
for line in ann.line_start + 1..middle {
|
||||
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
|
||||
}
|
||||
if middle < ann.line_end - 1 {
|
||||
for line in ann.line_end - 1..ann.line_end {
|
||||
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
end_ann.annotation_type = AnnotationType::Singleline;
|
||||
}
|
||||
add_annotation_to_file(&mut output, file, ann.line_end, ann.as_end());
|
||||
add_annotation_to_file(&mut output, file, ann.line_end, end_ann);
|
||||
}
|
||||
for file_vec in output.iter_mut() {
|
||||
file_vec.multiline_depth = max_depth;
|
||||
|
|
|
@ -18,6 +18,7 @@ pub struct MultilineAnnotation {
|
|||
pub end_col: usize,
|
||||
pub is_primary: bool,
|
||||
pub label: Option<String>,
|
||||
pub overlaps: bool,
|
||||
}
|
||||
|
||||
impl MultilineAnnotation {
|
||||
|
@ -25,6 +26,12 @@ impl MultilineAnnotation {
|
|||
self.depth += 1;
|
||||
}
|
||||
|
||||
/// Compare two `MultilineAnnotation`s considering only the `Span` they cover.
|
||||
pub fn same_span(&self, other: &MultilineAnnotation) -> bool {
|
||||
self.line_start == other.line_start && self.line_end == other.line_end
|
||||
&& self.start_col == other.start_col && self.end_col == other.end_col
|
||||
}
|
||||
|
||||
pub fn as_start(&self) -> Annotation {
|
||||
Annotation {
|
||||
start_col: self.start_col,
|
||||
|
|
|
@ -374,6 +374,66 @@ error: foo
|
|||
"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn triple_exact_overlap() {
|
||||
test_harness(r#"
|
||||
fn foo() {
|
||||
X0 Y0 Z0
|
||||
X1 Y1 Z1
|
||||
X2 Y2 Z2
|
||||
}
|
||||
"#,
|
||||
vec![
|
||||
SpanLabel {
|
||||
start: Position {
|
||||
string: "X0",
|
||||
count: 1,
|
||||
},
|
||||
end: Position {
|
||||
string: "X2",
|
||||
count: 1,
|
||||
},
|
||||
label: "`X` is a good letter",
|
||||
},
|
||||
SpanLabel {
|
||||
start: Position {
|
||||
string: "X0",
|
||||
count: 1,
|
||||
},
|
||||
end: Position {
|
||||
string: "X2",
|
||||
count: 1,
|
||||
},
|
||||
label: "`Y` is a good letter too",
|
||||
},
|
||||
SpanLabel {
|
||||
start: Position {
|
||||
string: "X0",
|
||||
count: 1,
|
||||
},
|
||||
end: Position {
|
||||
string: "X2",
|
||||
count: 1,
|
||||
},
|
||||
label: "`Z` label",
|
||||
},
|
||||
],
|
||||
r#"
|
||||
error: foo
|
||||
--> test.rs:3:3
|
||||
|
|
||||
3 | / X0 Y0 Z0
|
||||
4 | | X1 Y1 Z1
|
||||
5 | | X2 Y2 Z2
|
||||
| | ^
|
||||
| | |
|
||||
| | `X` is a good letter
|
||||
| |____`Y` is a good letter too
|
||||
| `Z` label
|
||||
|
||||
"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn minimum_depth() {
|
||||
test_harness(r#"
|
||||
|
|
|
@ -3,7 +3,7 @@ fn warn(_: &str) {}
|
|||
macro_rules! intrinsic_match {
|
||||
($intrinsic:expr) => {
|
||||
warn(format!("unsupported intrinsic {}", $intrinsic));
|
||||
//^~ ERROR mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-deref-inside-macro-issue-58298.rs:10:5
|
||||
--> $DIR/dont-suggest-deref-inside-macro-issue-58298.rs:11:5
|
||||
|
|
||||
LL | intrinsic_match! {
|
||||
| _____^
|
||||
| |_____|
|
||||
| ||
|
||||
LL | || "abc"
|
||||
LL | || };
|
||||
| || ^
|
||||
| ||______|
|
||||
| |_______expected &str, found struct `std::string::String`
|
||||
| in this macro invocation
|
||||
LL | / intrinsic_match! {
|
||||
LL | | "abc"
|
||||
LL | | };
|
||||
| | ^
|
||||
| | |
|
||||
| |______expected &str, found struct `std::string::String`
|
||||
| in this macro invocation
|
||||
|
|
||||
= note: expected type `&str`
|
||||
found type `std::string::String`
|
||||
|
|
Loading…
Reference in a new issue