about summary refs log tree commit diff
path: root/src/librustc_errors
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2017-04-14 16:38:10 -0700
committerEsteban Küber <esteban@kuber.com.ar>2017-04-20 17:31:20 -0700
commitcc07c357e421eebff58eb6948c8e1412ae7d8069 (patch)
tree560bdd78cbfc03646386e6d8ed881c901f4bda79 /src/librustc_errors
parent968ae7babecfc6c62ef9699ff052d9ab00411848 (diff)
downloadrust-cc07c357e421eebff58eb6948c8e1412ae7d8069.tar.gz
rust-cc07c357e421eebff58eb6948c8e1412ae7d8069.zip
Reduce visual clutter of multiline start when possible
When a span starts on a line with nothing but whitespace to the left,
and there are no other annotations in that line, simplify the visual
representation of the span.

Go from:

```rust
error[E0072]: recursive type `A` has infinite size
 --> file2.rs:1:1
  |
1 |   struct A {
  |  _^ starting here...
2 | |     a: A,
3 | | }
  | |_^ ...ending here: recursive type has infinite size
  |
```

To:

```rust
error[E0072]: recursive type `A` has infinite size
 --> file2.rs:1:1
  |
1 | / struct A {
2 | |     a: A,
3 | | }
  | |_^ recursive type has infinite size
```

Remove `starting here...`/`...ending here` labels from all multiline
diagnostics.
Diffstat (limited to 'src/librustc_errors')
-rw-r--r--src/librustc_errors/emitter.rs67
-rw-r--r--src/librustc_errors/snippet.rs22
2 files changed, 68 insertions, 21 deletions
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index a52628ceb47..64652bb308b 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -263,6 +263,41 @@ impl EmitterWriter {
 
         draw_col_separator(buffer, line_offset, width_offset - 2);
 
+        // Special case when there's only one annotation involved, it is the start of a multiline
+        // span and there's no text at the beginning of the code line. Instead of doing the whole
+        // graph:
+        //
+        // 2 |   fn foo() {
+        //   |  _^
+        // 3 | |
+        // 4 | | }
+        //   | |_^ test
+        //
+        // we simplify the output to:
+        //
+        // 2 | / fn foo() {
+        // 3 | |
+        // 4 | | }
+        //   | |_^ test
+        if line.annotations.len() == 1 {
+            if let Some(ref ann) = line.annotations.get(0) {
+                if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
+                    if source_string[0..ann.start_col].trim() == "" {
+                        let style = if ann.is_primary {
+                            Style::UnderlinePrimary
+                        } else {
+                            Style::UnderlineSecondary
+                        };
+                        buffer.putc(line_offset,
+                                    width_offset + depth - 1,
+                                    '/',
+                                    style);
+                        return vec![(depth, style)];
+                    }
+                }
+            }
+        }
+
         // We want to display like this:
         //
         //      vec.push(vec.pop().unwrap());
@@ -355,10 +390,8 @@ impl EmitterWriter {
         for (i, annotation) in annotations.iter().enumerate() {
             for (j, next) in annotations.iter().enumerate() {
                 if overlaps(next, annotation, 0)  // This label overlaps with another one and both
-                    && !annotation.is_line()      // take space (they have text and are not
-                    && !next.is_line()            // multiline lines).
-                    && annotation.has_label()
-                    && j > i
+                    && annotation.has_label()     // take space (they have text and are not
+                    && j > i                      // multiline lines).
                     && p == 0  // We're currently on the first line, move the label one line down
                 {
                     // This annotation needs a new line in the output.
@@ -374,7 +407,7 @@ impl EmitterWriter {
                     } else {
                         0
                     };
-                    if overlaps(next, annotation, l) // Do not allow two labels to be in the same
+                    if (overlaps(next, annotation, l) // Do not allow two labels to be in the same
                                                      // line if they overlap including padding, to
                                                      // avoid situations like:
                                                      //
@@ -383,11 +416,18 @@ impl EmitterWriter {
                                                      //      |      |
                                                      //      fn_spanx_span
                                                      //
-                        && !annotation.is_line()     // Do not add a new line if this annotation
-                        && !next.is_line()           // or the next are vertical line placeholders.
                         && annotation.has_label()    // Both labels must have some text, otherwise
-                        && next.has_label()          // they are not overlapping.
+                        && next.has_label())         // they are not overlapping.
+                                                     // Do not add a new line if this annotation
+                                                     // or the next are vertical line placeholders.
+                        || (annotation.takes_space() // If either this or the next annotation is
+                            && next.has_label())     // multiline start/end, move it to a new line
+                        || (annotation.has_label()   // so as not to overlap the orizontal lines.
+                            && next.takes_space())
+                        || (annotation.takes_space()
+                            && next.takes_space())
                     {
+                        // This annotation needs a new line in the output.
                         p += 1;
                         break;
                     }
@@ -397,6 +437,7 @@ impl EmitterWriter {
                 line_len = p;
             }
         }
+
         if line_len != 0 {
             line_len += 1;
         }
@@ -480,7 +521,7 @@ impl EmitterWriter {
             };
             let pos = pos + 1;
 
-            if pos > 1 && annotation.has_label() {
+            if pos > 1 && (annotation.has_label() || annotation.takes_space()) {
                 for p in line_offset + 1..line_offset + pos + 1 {
                     buffer.putc(p,
                                 code_offset + annotation.start_col,
@@ -514,12 +555,12 @@ impl EmitterWriter {
         // After this we will have:
         //
         // 2 |   fn foo() {
-        //   |  __________ starting here...
+        //   |  __________
         //   |      |
         //   |      something about `foo`
         // 3 |
         // 4 |   }
-        //   |  _  ...ending here: test
+        //   |  _  test
         for &(pos, annotation) in &annotations_position {
             let style = if annotation.is_primary {
                 Style::LabelPrimary
@@ -557,12 +598,12 @@ impl EmitterWriter {
         // After this we will have:
         //
         // 2 |   fn foo() {
-        //   |  ____-_____^ starting here...
+        //   |  ____-_____^
         //   |      |
         //   |      something about `foo`
         // 3 |
         // 4 |   }
-        //   |  _^  ...ending here: test
+        //   |  _^  test
         for &(_, annotation) in &annotations_position {
             let (underline, style) = if annotation.is_primary {
                 ('^', Style::UnderlinePrimary)
diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs
index 9aa4682e1af..7401ead2208 100644
--- a/src/librustc_errors/snippet.rs
+++ b/src/librustc_errors/snippet.rs
@@ -63,7 +63,7 @@ impl MultilineAnnotation {
             start_col: self.start_col,
             end_col: self.start_col + 1,
             is_primary: self.is_primary,
-            label: Some("starting here...".to_owned()),
+            label: None,
             annotation_type: AnnotationType::MultilineStart(self.depth)
         }
     }
@@ -73,10 +73,7 @@ impl MultilineAnnotation {
             start_col: self.end_col - 1,
             end_col: self.end_col,
             is_primary: self.is_primary,
-            label: match self.label {
-                Some(ref label) => Some(format!("...ending here: {}", label)),
-                None => Some("...ending here".to_owned()),
-            },
+            label: self.label.clone(),
             annotation_type: AnnotationType::MultilineEnd(self.depth)
         }
     }
@@ -106,9 +103,9 @@ pub enum AnnotationType {
     // Each of these corresponds to one part of the following diagram:
     //
     //     x |   foo(1 + bar(x,
-    //       |  _________^ starting here...           < MultilineStart
-    //     x | |             y),                      < MultilineLine
-    //       | |______________^ ...ending here: label < MultilineEnd
+    //       |  _________^              < MultilineStart
+    //     x | |             y),        < MultilineLine
+    //       | |______________^ label   < MultilineEnd
     //     x |       z);
     /// Annotation marking the first character of a fully shown multiline span
     MultilineStart(usize),
@@ -189,6 +186,15 @@ impl Annotation {
             false
         }
     }
+
+    pub fn takes_space(&self) -> bool {
+        // Multiline annotations always have to keep vertical space.
+        match self.annotation_type {
+            AnnotationType::MultilineStart(_) |
+            AnnotationType::MultilineEnd(_) => true,
+            _ => false,
+        }
+    }
 }
 
 #[derive(Debug)]