@@ -2216,6 +2216,11 @@ impl HumanEmitter {
2216
2216
show_code_change
2217
2217
{
2218
2218
for part in parts {
2219
+ let snippet = if let Ok ( snippet) = sm. span_to_snippet ( part. span ) {
2220
+ snippet
2221
+ } else {
2222
+ String :: new ( )
2223
+ } ;
2219
2224
let span_start_pos = sm. lookup_char_pos ( part. span . lo ( ) ) . col_display ;
2220
2225
let span_end_pos = sm. lookup_char_pos ( part. span . hi ( ) ) . col_display ;
2221
2226
@@ -2263,13 +2268,80 @@ impl HumanEmitter {
2263
2268
}
2264
2269
if let DisplaySuggestion :: Diff = show_code_change {
2265
2270
// Colorize removal with red in diff format.
2266
- buffer. set_style_range (
2267
- row_num - 2 ,
2268
- ( padding as isize + span_start_pos as isize ) as usize ,
2269
- ( padding as isize + span_end_pos as isize ) as usize ,
2270
- Style :: Removal ,
2271
- true ,
2272
- ) ;
2271
+
2272
+ // Below, there's some tricky buffer indexing going on. `row_num` at this
2273
+ // point corresponds to:
2274
+ //
2275
+ // |
2276
+ // LL | CODE
2277
+ // | ++++ <- `row_num`
2278
+ //
2279
+ // in the buffer. When we have a diff format output, we end up with
2280
+ //
2281
+ // |
2282
+ // LL - OLDER <- row_num - 2
2283
+ // LL + NEWER
2284
+ // | <- row_num
2285
+ //
2286
+ // The `row_num - 2` is to select the buffer line that has the "old version
2287
+ // of the diff" at that point. When the removal is a single line, `i` is
2288
+ // `0`, `newlines` is `1` so `(newlines - i - 1)` ends up being `0`, so row
2289
+ // points at `LL - OLDER`. When the removal corresponds to multiple lines,
2290
+ // we end up with `newlines > 1` and `i` being `0..newlines - 1`.
2291
+ //
2292
+ // |
2293
+ // LL - OLDER <- row_num - 2 - (newlines - last_i - 1)
2294
+ // LL - CODE
2295
+ // LL - BEING
2296
+ // LL - REMOVED <- row_num - 2 - (newlines - first_i - 1)
2297
+ // LL + NEWER
2298
+ // | <- row_num
2299
+
2300
+ let newlines = snippet. lines ( ) . count ( ) ;
2301
+ if newlines > 0 && row_num > newlines {
2302
+ // Account for removals where the part being removed spans multiple
2303
+ // lines.
2304
+ // FIXME: We check the number of rows because in some cases, like in
2305
+ // `tests/ui/lint/invalid-nan-comparison-suggestion.rs`, the rendered
2306
+ // suggestion will only show the first line of code being replaced. The
2307
+ // proper way of doing this would be to change the suggestion rendering
2308
+ // logic to show the whole prior snippet, but the current output is not
2309
+ // too bad to begin with, so we side-step that issue here.
2310
+ for ( i, line) in snippet. lines ( ) . enumerate ( ) {
2311
+ let line = normalize_whitespace ( line) ;
2312
+ let row = row_num - 2 - ( newlines - i - 1 ) ;
2313
+ // On the first line, we highlight between the start of the part
2314
+ // span, and the end of that line.
2315
+ // On the last line, we highlight between the start of the line, and
2316
+ // the column of the part span end.
2317
+ // On all others, we highlight the whole line.
2318
+ let start = if i == 0 {
2319
+ ( padding as isize + span_start_pos as isize ) as usize
2320
+ } else {
2321
+ padding
2322
+ } ;
2323
+ let end = if i == 0 {
2324
+ ( padding as isize
2325
+ + span_start_pos as isize
2326
+ + line. len ( ) as isize )
2327
+ as usize
2328
+ } else if i == newlines - 1 {
2329
+ ( padding as isize + span_end_pos as isize ) as usize
2330
+ } else {
2331
+ ( padding as isize + line. len ( ) as isize ) as usize
2332
+ } ;
2333
+ buffer. set_style_range ( row, start, end, Style :: Removal , true ) ;
2334
+ }
2335
+ } else {
2336
+ // The removed code fits all in one line.
2337
+ buffer. set_style_range (
2338
+ row_num - 2 ,
2339
+ ( padding as isize + span_start_pos as isize ) as usize ,
2340
+ ( padding as isize + span_end_pos as isize ) as usize ,
2341
+ Style :: Removal ,
2342
+ true ,
2343
+ ) ;
2344
+ }
2273
2345
}
2274
2346
2275
2347
// length of the code after substitution
0 commit comments