Skip to content
Permalink
Browse files

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
```
  • Loading branch information...
estebank committed Mar 28, 2019
1 parent 925ca49 commit 326ec800b952749d0afc90be0604dc0332d70324
@@ -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,13 +18,20 @@ pub struct MultilineAnnotation {
pub end_col: usize,
pub is_primary: bool,
pub label: Option<String>,
pub overlaps: bool,
}

impl MultilineAnnotation {
pub fn increase_depth(&mut self) {
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`

0 comments on commit 326ec80

Please sign in to comment.
You can’t perform that action at this time.