]> git.lizzy.rs Git - rust.git/commitdiff
Account for fully overlapping multiline annotations
authorEsteban Küber <esteban@kuber.com.ar>
Thu, 28 Mar 2019 02:26:47 +0000 (19:26 -0700)
committerEsteban Küber <esteban@kuber.com.ar>
Thu, 28 Mar 2019 02:35:30 +0000 (19:35 -0700)
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
```

src/librustc_errors/emitter.rs
src/librustc_errors/snippet.rs
src/libsyntax/test_snippet.rs
src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs
src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr

index e9f269b6e2410b311fbee1c6ad15fd632baf17fe..c3ee1db8d3056c26c85e824cf570acf0bd383994 100644 (file)
@@ -243,6 +243,7 @@ fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
                         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 @@ fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
                 };
 
                 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 @@ fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
                 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 @@ fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
             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;
index 0c62ff0ff89b27e3f9f665c7cffd75cc4e3257f1..60ee0c2572761d161dc839768727d061ff6a982e 100644 (file)
@@ -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 @@ 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,
index 2b3d18835d543bc631dd0e60f511159442ad8fd6..86910ffd894c4ea9870e82ddb46ed67f85d2cbf8 100644 (file)
@@ -374,6 +374,66 @@ fn 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#"
index bf2d105f63fb52dc7e9d35ccc77e9febcd06e204..ef1c09d218058050b2ca72ece7c8412907009a60 100644 (file)
@@ -3,7 +3,7 @@ fn warn(_: &str) {}
 macro_rules! intrinsic_match {
     ($intrinsic:expr) => {
         warn(format!("unsupported intrinsic {}", $intrinsic));
-        //^~ ERROR mismatched types
+        //~^ ERROR mismatched types
     };
 }
 
index 75a08904e69b9d6c22937a2904a8d4c08d403360..bc7a7247a12830e62a557676240d4813e0a3978f 100644 (file)
@@ -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`