@@ -1723,64 +1723,42 @@ fn emit_suggestion_default(
17231723 // logic to show the whole prior snippet, but the current output is not
17241724 // too bad to begin with, so we side-step that issue here.
17251725 for ( i, line) in snippet. lines ( ) . enumerate ( ) {
1726- let full_line = if i == 0 {
1727- // `snippet` starts at the first character that must be edited,
1728- // which often does not contain the indent of the line. Retrieve
1729- // the full line in order to avoid missing leading tabs.
1730- sm. get_line ( span_start. line ) . unwrap_or_default ( )
1731- } else {
1732- line
1733- } ;
1734-
1735- let tabs: usize = full_line
1736- . chars ( )
1737- . take ( span_start. char )
1738- . map ( |ch| match ch {
1739- '\t' => 3 ,
1740- _ => 0 ,
1741- } )
1742- . sum ( ) ;
1743- let line = normalize_whitespace ( line) ;
1726+ let norm_line = normalize_whitespace ( line) ;
17441727 // Going lower than buffer_offset (+ 1) would mean
17451728 // overwriting existing content in the buffer
17461729 let min_row = buffer_offset + usize:: from ( !matches_previous_suggestion) ;
17471730 let row = ( row_num - 2 - ( offset - i - 1 ) ) . max ( min_row) ;
1748- // On the first line, we highlight between the start of the part
1749- // span, and the end of that line.
1750- // On the last line, we highlight between the start of the line, and
1751- // the column of the part span end.
1752- // On all others, we highlight the whole line.
1753- let start = if i == 0 {
1754- ( padding as isize + ( span_start. char + tabs) as isize ) as usize
1755- } else {
1756- padding
1757- } ;
1758- let end = if i == 0 {
1759- ( padding as isize
1760- + ( span_start. char + tabs) as isize
1761- + line. chars ( ) . count ( ) as isize )
1762- as usize
1731+ let ( start, end) = if i == 0 {
1732+ // On the first line, we highlight between the start of the part
1733+ // span, and the end of that line.
1734+ let full_line = sm. get_line ( span_start. line ) . unwrap_or_default ( ) ;
1735+ let extra_width = extra_width_from_tabs ( full_line, span_start. char ) ;
1736+ let start = span_start. char + extra_width;
1737+ ( start, start + norm_line. chars ( ) . count ( ) )
17631738 } else if i == newlines - 1 {
1764- ( padding as isize + ( span_end. char + tabs) as isize ) as usize
1739+ // On the last line, we highlight between the start of the line, and
1740+ // the column of the part span end.
1741+ let extra_width = extra_width_from_tabs ( line, span_end. char ) ;
1742+ ( 0 , span_end. char + extra_width)
17651743 } else {
1766- ( padding as isize + line. chars ( ) . count ( ) as isize ) as usize
1744+ // On all others, we highlight the whole line.
1745+ ( 0 , norm_line. chars ( ) . count ( ) )
17671746 } ;
1768- buffer. set_style_range ( row, start, end, ElementStyle :: Removal , true ) ;
1747+ buffer. set_style_range (
1748+ row,
1749+ padding + start,
1750+ padding + end,
1751+ ElementStyle :: Removal ,
1752+ true ,
1753+ ) ;
17691754 }
17701755 } else {
1771- let tabs: usize = snippet
1772- . chars ( )
1773- . take ( span_start. char )
1774- . map ( |ch| match ch {
1775- '\t' => 3 ,
1776- _ => 0 ,
1777- } )
1778- . sum ( ) ;
1756+ let extra_width: usize = extra_width_from_tabs ( snippet, span_start. char ) ;
17791757 // The removed code fits all in one line.
17801758 buffer. set_style_range (
17811759 row_num - 2 ,
1782- ( padding as isize + ( span_start. char + tabs ) as isize ) as usize ,
1783- ( padding as isize + ( span_end. char + tabs ) as isize ) as usize ,
1760+ span_start. char + extra_width ,
1761+ span_end. char + extra_width ,
17841762 ElementStyle :: Removal ,
17851763 true ,
17861764 ) ;
@@ -1992,18 +1970,11 @@ fn draw_code_line(
19921970 // This is a no-op for empty ranges
19931971 if start != end {
19941972 // Account for tabs when highlighting (#87972).
1995- let tabs: usize = line_to_add
1996- . chars ( )
1997- . take ( start)
1998- . map ( |ch| match ch {
1999- '\t' => 3 ,
2000- _ => 0 ,
2001- } )
2002- . sum ( ) ;
1973+ let extra_width: usize = extra_width_from_tabs ( line_to_add, start) ;
20031974 buffer. set_style_range (
20041975 * row_num,
2005- max_line_num_len + 3 + start + tabs ,
2006- max_line_num_len + 3 + end + tabs ,
1976+ max_line_num_len + 3 + start + extra_width ,
1977+ max_line_num_len + 3 + end + extra_width ,
20071978 ElementStyle :: Addition ,
20081979 true ,
20091980 ) ;
@@ -2311,6 +2282,12 @@ impl MessageOrTitle for Message<'_> {
23112282 }
23122283}
23132284
2285+ /// Count extra display columns from tabs in the first `n` chars of `s`.
2286+ /// Each tab is displayed as 4 spaces, so the extra width per tab is 3.
2287+ fn extra_width_from_tabs ( s : & str , n : usize ) -> usize {
2288+ s. chars ( ) . take ( n) . filter ( |& ch| ch == '\t' ) . count ( ) * 3
2289+ }
2290+
23142291// instead of taking the String length or dividing by 10 while > 0, we multiply a limit by 10 until
23152292// we're higher. If the loop isn't exited by the `return`, the last multiplication will wrap, which
23162293// is OK, because while we cannot fit a higher power of 10 in a usize, the loop will end anyway.
0 commit comments