about summary refs log tree commit diff
path: root/compiler/rustc_errors/src
diff options
context:
space:
mode:
authorEsteban Kuber <esteban@kuber.com.ar>2021-08-12 19:33:19 +0000
committerEsteban Kuber <esteban@kuber.com.ar>2021-08-23 11:58:18 +0000
commit75fd1bf1e60dd140f2ba46a4252195ea2a9b9c89 (patch)
tree32f6be36a9355624b61881031919242dbc29bbb3 /compiler/rustc_errors/src
parent33fdb797f59421c7bbecaa4588ed5d7a31a9494a (diff)
downloadrust-75fd1bf1e60dd140f2ba46a4252195ea2a9b9c89.tar.gz
rust-75fd1bf1e60dd140f2ba46a4252195ea2a9b9c89.zip
Account for tabs when highlighting multiline code suggestions
Diffstat (limited to 'compiler/rustc_errors/src')
-rw-r--r--compiler/rustc_errors/src/emitter.rs48
-rw-r--r--compiler/rustc_errors/src/lib.rs22
2 files changed, 45 insertions, 25 deletions
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 07c864c93a1..645b81b9540 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1623,7 +1623,7 @@ impl EmitterWriter {
             let line_start = sm.lookup_char_pos(parts[0].span.lo()).line;
             draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1);
             let mut lines = complete.lines();
-            for (line_pos, (line, parts)) in
+            for (line_pos, (line, highlight_parts)) in
                 lines.by_ref().zip(highlights).take(MAX_SUGGESTION_HIGHLIGHT_LINES).enumerate()
             {
                 // Print the span column to avoid confusion
@@ -1658,7 +1658,7 @@ impl EmitterWriter {
                     );
                     buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition);
                 } else if is_multiline {
-                    match &parts[..] {
+                    match &highlight_parts[..] {
                         [SubstitutionHighlight { start: 0, end }] if *end == line.len() => {
                             buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition);
                         }
@@ -1676,16 +1676,33 @@ impl EmitterWriter {
                 // print the suggestion
                 buffer.append(row_num, &replace_tabs(line), Style::NoStyle);
 
-                if is_multiline {
-                    for SubstitutionHighlight { start, end } in parts {
-                        buffer.set_style_range(
-                            row_num,
-                            max_line_num_len + 3 + start,
-                            max_line_num_len + 3 + end,
-                            Style::Addition,
-                            true,
-                        );
-                    }
+                // Colorize addition/replacements with green.
+                for &SubstitutionHighlight { start, end } in highlight_parts {
+                    // Account for tabs when highlighting (#87972).
+                    let start: usize = line
+                        .chars()
+                        .take(start)
+                        .map(|ch| match ch {
+                            '\t' => 4,
+                            _ => 1,
+                        })
+                        .sum();
+
+                    let end: usize = line
+                        .chars()
+                        .take(end)
+                        .map(|ch| match ch {
+                            '\t' => 4,
+                            _ => 1,
+                        })
+                        .sum();
+                    buffer.set_style_range(
+                        row_num,
+                        max_line_num_len + 3 + start,
+                        max_line_num_len + 3 + end,
+                        Style::Addition,
+                        true,
+                    );
                 }
                 row_num += 1;
             }
@@ -1723,13 +1740,6 @@ impl EmitterWriter {
                     assert!(underline_start >= 0 && underline_end >= 0);
                     let padding: usize = max_line_num_len + 3;
                     for p in underline_start..underline_end {
-                        // Colorize addition/replacements with green.
-                        buffer.set_style(
-                            row_num - 1,
-                            (padding as isize + p) as usize,
-                            Style::Addition,
-                            true,
-                        );
                         if !show_diff {
                             // If this is a replacement, underline with `^`, if this is an addition
                             // underline with `+`.
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index ec29d8016dd..cae4a6b4723 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -283,6 +283,9 @@ impl CodeSuggestion {
                 let mut buf = String::new();
 
                 let mut line_highlight = vec![];
+                // We need to keep track of the difference between the existing code and the added
+                // or deleted code in order to point at the correct column *after* substitution.
+                let mut acc = 0;
                 for part in &substitution.parts {
                     let cur_lo = sm.lookup_char_pos(part.span.lo());
                     if prev_hi.line == cur_lo.line {
@@ -290,6 +293,7 @@ impl CodeSuggestion {
                             push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo));
                         while count > 0 {
                             highlights.push(std::mem::take(&mut line_highlight));
+                            acc = 0;
                             count -= 1;
                         }
                     } else {
@@ -297,6 +301,7 @@ impl CodeSuggestion {
                         let mut count = push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None);
                         while count > 0 {
                             highlights.push(std::mem::take(&mut line_highlight));
+                            acc = 0;
                             count -= 1;
                         }
                         // push lines between the previous and current span (if any)
@@ -305,6 +310,7 @@ impl CodeSuggestion {
                                 buf.push_str(line.as_ref());
                                 buf.push('\n');
                                 highlights.push(std::mem::take(&mut line_highlight));
+                                acc = 0;
                             }
                         }
                         if let Some(cur_line) = sf.get_line(cur_lo.line - 1) {
@@ -316,18 +322,22 @@ impl CodeSuggestion {
                         }
                     }
                     // Add a whole line highlight per line in the snippet.
+                    let len = part.snippet.split('\n').next().unwrap_or(&part.snippet).len();
                     line_highlight.push(SubstitutionHighlight {
-                        start: cur_lo.col.0,
-                        end: cur_lo.col.0
-                            + part.snippet.split('\n').next().unwrap_or(&part.snippet).len(),
+                        start: (cur_lo.col.0 as isize + acc) as usize,
+                        end: (cur_lo.col.0 as isize + acc + len as isize) as usize,
                     });
+                    buf.push_str(&part.snippet);
+                    prev_hi = sm.lookup_char_pos(part.span.hi());
+                    if prev_hi.line == cur_lo.line {
+                        acc += len as isize - (prev_hi.col.0 - cur_lo.col.0) as isize;
+                    }
+                    prev_line = sf.get_line(prev_hi.line - 1);
                     for line in part.snippet.split('\n').skip(1) {
+                        acc = 0;
                         highlights.push(std::mem::take(&mut line_highlight));
                         line_highlight.push(SubstitutionHighlight { start: 0, end: line.len() });
                     }
-                    buf.push_str(&part.snippet);
-                    prev_hi = sm.lookup_char_pos(part.span.hi());
-                    prev_line = sf.get_line(prev_hi.line - 1);
                 }
                 highlights.push(std::mem::take(&mut line_highlight));
                 let only_capitalization = is_case_difference(sm, &buf, bounding_span);