@@ -1215,19 +1215,20 @@ impl EmitterWriter {
12151215
12161216 let mut row_num = 2 ;
12171217 for & ( ref complete, ref parts) in suggestions. iter ( ) . take ( MAX_SUGGESTIONS ) {
1218- let show_underline = parts. len ( ) == 1
1219- && complete. lines ( ) . count ( ) == 1
1220- && parts[ 0 ] . snippet . trim ( ) != complete. trim ( ) ;
1218+ // Only show underline if the suggestion spans a single line and doesn't cover the
1219+ // entirety of the code output. If you have multiple replacements in the same line
1220+ // of code, show the underline.
1221+ let show_underline = !( parts. len ( ) == 1
1222+ && parts[ 0 ] . snippet . trim ( ) == complete. trim ( ) )
1223+ && complete. lines ( ) . count ( ) == 1 ;
12211224
12221225 let lines = cm. span_to_lines ( parts[ 0 ] . span ) . unwrap ( ) ;
12231226
12241227 assert ! ( !lines. lines. is_empty( ) ) ;
12251228
1226- let span_start_pos = cm. lookup_char_pos ( parts[ 0 ] . span . lo ( ) ) ;
1227- let line_start = span_start_pos. line ;
1229+ let line_start = cm. lookup_char_pos ( parts[ 0 ] . span . lo ( ) ) . line ;
12281230 draw_col_separator_no_space ( & mut buffer, 1 , max_line_num_len + 1 ) ;
12291231 let mut line_pos = 0 ;
1230- // Only show underline if there's a single suggestion and it is a single line
12311232 let mut lines = complete. lines ( ) ;
12321233 for line in lines. by_ref ( ) . take ( MAX_HIGHLIGHT_LINES ) {
12331234 // Print the span column to avoid confusion
@@ -1241,22 +1242,55 @@ impl EmitterWriter {
12411242 line_pos += 1 ;
12421243 row_num += 1 ;
12431244 }
1245+
1246+ // This offset and the ones below need to be signed to account for replacement code
1247+ // that is shorter than the original code.
1248+ let mut offset: isize = 0 ;
12441249 // Only show an underline in the suggestions if the suggestion is not the
12451250 // entirety of the code being shown and the displayed code is not multiline.
12461251 if show_underline {
12471252 draw_col_separator ( & mut buffer, row_num, max_line_num_len + 1 ) ;
1248- let start = parts[ 0 ] . snippet . len ( ) - parts[ 0 ] . snippet . trim_left ( ) . len ( ) ;
1249- // account for substitutions containing unicode characters
1250- let sub_len = parts[ 0 ] . snippet . trim ( ) . chars ( ) . fold ( 0 , |acc, ch| {
1251- acc + unicode_width:: UnicodeWidthChar :: width ( ch) . unwrap_or ( 0 )
1252- } ) ;
1253- let underline_start = span_start_pos. col_display + start;
1254- let underline_end = span_start_pos. col_display + start + sub_len;
1255- for p in underline_start..underline_end {
1256- buffer. putc ( row_num,
1257- max_line_num_len + 3 + p,
1258- '^' ,
1259- Style :: UnderlinePrimary ) ;
1253+ for part in parts {
1254+ let span_start_pos = cm. lookup_char_pos ( part. span . lo ( ) ) . col_display ;
1255+ let span_end_pos = cm. lookup_char_pos ( part. span . hi ( ) ) . col_display ;
1256+
1257+ // Do not underline the leading...
1258+ let start = part. snippet . len ( )
1259+ . saturating_sub ( part. snippet . trim_left ( ) . len ( ) ) ;
1260+ // ...or trailing spaces. Account for substitutions containing unicode
1261+ // characters.
1262+ let sub_len = part. snippet . trim ( ) . chars ( ) . fold ( 0 , |acc, ch| {
1263+ acc + unicode_width:: UnicodeWidthChar :: width ( ch) . unwrap_or ( 0 )
1264+ } ) ;
1265+
1266+ let underline_start = ( span_start_pos + start) as isize + offset;
1267+ let underline_end = ( span_start_pos + start + sub_len) as isize + offset;
1268+ for p in underline_start..underline_end {
1269+ buffer. putc ( row_num,
1270+ max_line_num_len + 3 + p as usize ,
1271+ '^' ,
1272+ Style :: UnderlinePrimary ) ;
1273+ }
1274+ // underline removals too
1275+ if underline_start == underline_end {
1276+ for p in underline_start-1 ..underline_start+1 {
1277+ buffer. putc ( row_num,
1278+ max_line_num_len + 3 + p as usize ,
1279+ '-' ,
1280+ Style :: UnderlineSecondary ) ;
1281+ }
1282+ }
1283+
1284+ // length of the code after substitution
1285+ let full_sub_len = part. snippet . chars ( ) . fold ( 0 , |acc, ch| {
1286+ acc + unicode_width:: UnicodeWidthChar :: width ( ch) . unwrap_or ( 0 ) as isize
1287+ } ) ;
1288+
1289+ // length of the code to be substituted
1290+ let snippet_len = ( span_end_pos - span_start_pos) as isize ;
1291+ // For multiple substitutions, use the position *after* the previous
1292+ // substitutions have happened.
1293+ offset += full_sub_len - snippet_len;
12601294 }
12611295 row_num += 1 ;
12621296 }
0 commit comments