Account for tabs when highlighting multiline code suggestions

This commit is contained in:
Esteban Kuber 2021-08-12 19:33:19 +00:00
parent 33fdb797f5
commit 75fd1bf1e6
2 changed files with 45 additions and 25 deletions

View file

@ -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 `+`.

View file

@ -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);