about summary refs log tree commit diff
path: root/src/librustc_errors/emitter.rs
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-05-22 21:05:35 -0700
committerEsteban Küber <esteban@kuber.com.ar>2018-05-24 04:16:13 -0700
commit2daa013290e054151424849e51c0b1f24db7e7f9 (patch)
tree492876ce95c03d8575c4b2137d339e7702c9c6ce /src/librustc_errors/emitter.rs
parent7426f5ccf7b362785a5abeb365674d3da3d4df2e (diff)
downloadrust-2daa013290e054151424849e51c0b1f24db7e7f9.tar.gz
rust-2daa013290e054151424849e51c0b1f24db7e7f9.zip
Underline multiple suggested replacements in the same line
Follow up to #50943.

Fix #50977.
Diffstat (limited to 'src/librustc_errors/emitter.rs')
-rw-r--r--src/librustc_errors/emitter.rs65
1 files changed, 47 insertions, 18 deletions
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 91075ddcfa4..123b6abab50 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -1215,19 +1215,20 @@ impl EmitterWriter {
 
             let mut row_num = 2;
             for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) {
-                let show_underline = parts.len() == 1
-                    && complete.lines().count() == 1
-                    && parts[0].snippet.trim() != complete.trim();
+                // Only show underline if the suggestion spans a single line and doesn't cover the
+                // entirety of the code output. If you have multiple replacements in the same line
+                // of code, show the underline.
+                let show_underline = !(parts.len() == 1
+                    && parts[0].snippet.trim() == complete.trim())
+                    && complete.lines().count() == 1;
 
                 let lines = cm.span_to_lines(parts[0].span).unwrap();
 
                 assert!(!lines.lines.is_empty());
 
-                let span_start_pos = cm.lookup_char_pos(parts[0].span.lo());
-                let line_start = span_start_pos.line;
+                let line_start = cm.lookup_char_pos(parts[0].span.lo()).line;
                 draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1);
                 let mut line_pos = 0;
-                // Only show underline if there's a single suggestion and it is a single line
                 let mut lines = complete.lines();
                 for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
                     // Print the span column to avoid confusion
@@ -1241,22 +1242,50 @@ impl EmitterWriter {
                     line_pos += 1;
                     row_num += 1;
                 }
+                let mut extra = 0;
                 // Only show an underline in the suggestions if the suggestion is not the
                 // entirety of the code being shown and the displayed code is not multiline.
                 if show_underline {
                     draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
-                    let start = parts[0].snippet.len() - parts[0].snippet.trim_left().len();
-                    // account for substitutions containing unicode characters
-                    let sub_len = parts[0].snippet.trim().chars().fold(0, |acc, ch| {
-                        acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0)
-                    });
-                    let underline_start = span_start_pos.col_display + start;
-                    let underline_end = span_start_pos.col_display + start + sub_len;
-                    for p in underline_start..underline_end {
-                        buffer.putc(row_num,
-                                    max_line_num_len + 3 + p,
-                                    '^',
-                                    Style::UnderlinePrimary);
+                    for part in parts {
+                        let span_start_pos = cm.lookup_char_pos(part.span.lo());
+                        let span_end_pos = cm.lookup_char_pos(part.span.hi());
+                        // length of the code to be substituted
+                        let snippet_len = span_end_pos.col_display - span_start_pos.col_display;
+
+                        // Do not underline the leading or trailing spaces.
+                        let start = part.snippet.len() - part.snippet.trim_left().len();
+                        // account for substitutions containing unicode characters
+                        let sub_len = part.snippet.trim().chars().fold(0, |acc, ch| {
+                            acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0)
+                        });
+
+                        let underline_start = span_start_pos.col_display + start + extra;
+                        let underline_end = span_start_pos.col_display + start + sub_len + extra;
+                        for p in underline_start..underline_end {
+                            buffer.putc(row_num,
+                                        max_line_num_len + 3 + p,
+                                        '^',
+                                        Style::UnderlinePrimary);
+                        }
+                        // underline removals too
+                        if underline_start == underline_end {
+                            for p in underline_start-1..underline_start+1 {
+                                buffer.putc(row_num,
+                                            max_line_num_len + 3 + p,
+                                            '-',
+                                            Style::UnderlineSecondary);
+                            }
+                        }
+
+                        // length of the code after substitution
+                        let full_sub_len = part.snippet.chars().fold(0, |acc, ch| {
+                            acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0)
+                        });
+
+                        // For multiple substitutions, use the position *after* the previous
+                        // substitutions have happened.
+                        extra += full_sub_len - snippet_len;
                     }
                     row_num += 1;
                 }