@@ -1832,6 +1832,12 @@ impl EmitterWriter {
18321832 }
18331833 let show_code_change = if has_deletion && !is_multiline {
18341834 DisplaySuggestion :: Diff
1835+ } else if let [ part] = & parts[ ..]
1836+ && part. snippet . ends_with ( '\n' )
1837+ && part. snippet . trim ( ) == complete. trim ( )
1838+ {
1839+ // We are adding a line(s) of code before code that was already there.
1840+ DisplaySuggestion :: Add
18351841 } else if ( parts. len ( ) != 1 || parts[ 0 ] . snippet . trim ( ) != complete. trim ( ) )
18361842 && !is_multiline
18371843 {
@@ -1879,14 +1885,23 @@ impl EmitterWriter {
18791885 row_num += line_end - line_start;
18801886 }
18811887 let mut unhighlighted_lines = Vec :: new ( ) ;
1888+ let mut last_pos = 0 ;
1889+ let mut is_item_attribute = false ;
18821890 for ( line_pos, ( line, highlight_parts) ) in lines. by_ref ( ) . zip ( highlights) . enumerate ( ) {
1891+ last_pos = line_pos;
18831892 debug ! ( %line_pos, %line, ?highlight_parts) ;
18841893
18851894 // Remember lines that are not highlighted to hide them if needed
18861895 if highlight_parts. is_empty ( ) {
18871896 unhighlighted_lines. push ( ( line_pos, line) ) ;
18881897 continue ;
18891898 }
1899+ if highlight_parts. len ( ) == 1
1900+ && line. trim ( ) . starts_with ( "#[" )
1901+ && line. trim ( ) . ends_with ( ']' )
1902+ {
1903+ is_item_attribute = true ;
1904+ }
18901905
18911906 match unhighlighted_lines. len ( ) {
18921907 0 => ( ) ,
@@ -1963,13 +1978,41 @@ impl EmitterWriter {
19631978 is_multiline,
19641979 )
19651980 }
1981+ if let DisplaySuggestion :: Add = show_code_change && is_item_attribute {
1982+ // The suggestion adds an entire line of code, ending on a newline, so we'll also
1983+ // print the *following* line, to provide context of what we're advicing people to
1984+ // do. Otherwise you would only see contextless code that can be confused for
1985+ // already existing code, despite the colors and UI elements.
1986+ // We special case `#[derive(_)]\n` and other attribute suggestions, because those
1987+ // are the ones where context is most useful.
1988+ let file_lines = sm
1989+ . span_to_lines ( span. primary_span ( ) . unwrap ( ) . shrink_to_hi ( ) )
1990+ . expect ( "span_to_lines failed when emitting suggestion" ) ;
1991+ let line_num = sm. lookup_char_pos ( parts[ 0 ] . span . lo ( ) ) . line ;
1992+ if let Some ( line) = file_lines. file . get_line ( line_num - 1 ) {
1993+ let line = normalize_whitespace ( & line) ;
1994+ self . draw_code_line (
1995+ & mut buffer,
1996+ & mut row_num,
1997+ & [ ] ,
1998+ line_num + last_pos + 1 ,
1999+ & line,
2000+ DisplaySuggestion :: None ,
2001+ max_line_num_len,
2002+ & file_lines,
2003+ is_multiline,
2004+ )
2005+ }
2006+ }
19662007
19672008 // This offset and the ones below need to be signed to account for replacement code
19682009 // that is shorter than the original code.
19692010 let mut offsets: Vec < ( usize , isize ) > = Vec :: new ( ) ;
19702011 // Only show an underline in the suggestions if the suggestion is not the
19712012 // entirety of the code being shown and the displayed code is not multiline.
1972- if let DisplaySuggestion :: Diff | DisplaySuggestion :: Underline = show_code_change {
2013+ if let DisplaySuggestion :: Diff | DisplaySuggestion :: Underline | DisplaySuggestion :: Add =
2014+ show_code_change
2015+ {
19732016 draw_col_separator_no_space ( & mut buffer, row_num, max_line_num_len + 1 ) ;
19742017 for part in parts {
19752018 let span_start_pos = sm. lookup_char_pos ( part. span . lo ( ) ) . col_display ;
@@ -2247,6 +2290,10 @@ impl EmitterWriter {
22472290 }
22482291 }
22492292 buffer. append ( * row_num, & normalize_whitespace ( line_to_add) , Style :: NoStyle ) ;
2293+ } else if let DisplaySuggestion :: Add = show_code_change {
2294+ buffer. puts ( * row_num, 0 , & self . maybe_anonymized ( line_num) , Style :: LineNumber ) ;
2295+ buffer. puts ( * row_num, max_line_num_len + 1 , "+ " , Style :: Addition ) ;
2296+ buffer. append ( * row_num, & normalize_whitespace ( line_to_add) , Style :: NoStyle ) ;
22502297 } else {
22512298 buffer. puts ( * row_num, 0 , & self . maybe_anonymized ( line_num) , Style :: LineNumber ) ;
22522299 draw_col_separator ( buffer, * row_num, max_line_num_len + 1 ) ;
@@ -2281,6 +2328,7 @@ enum DisplaySuggestion {
22812328 Underline ,
22822329 Diff ,
22832330 None ,
2331+ Add ,
22842332}
22852333
22862334impl FileWithAnnotatedLines {
0 commit comments