1010use Destination :: * ;
1111
1212use rustc_span:: source_map:: SourceMap ;
13- use rustc_span:: { SourceFile , Span } ;
13+ use rustc_span:: { FileLines , SourceFile , Span } ;
1414
1515use crate :: snippet:: { Annotation , AnnotationType , Line , MultilineAnnotation , Style , StyledString } ;
1616use crate :: styled_buffer:: StyledBuffer ;
@@ -1756,12 +1756,6 @@ impl EmitterWriter {
17561756 let has_deletion = parts. iter ( ) . any ( |p| p. is_deletion ( ) ) ;
17571757 let is_multiline = complete. lines ( ) . count ( ) > 1 ;
17581758
1759- enum DisplaySuggestion {
1760- Underline ,
1761- Diff ,
1762- None ,
1763- }
1764-
17651759 if let Some ( span) = span. primary_span ( ) {
17661760 // Compare the primary span of the diagnostic with the span of the suggestion
17671761 // being emitted. If they belong to the same file, we don't *need* to show the
@@ -1838,83 +1832,7 @@ impl EmitterWriter {
18381832 for ( line_pos, ( line, highlight_parts) ) in lines. by_ref ( ) . zip ( highlights) . enumerate ( ) {
18391833 debug ! ( %line_pos, %line, ?highlight_parts) ;
18401834
1841- let print_line = |line_pos : usize ,
1842- line : & str ,
1843- highlight_parts : & Vec < SubstitutionHighlight > ,
1844- buffer : & mut StyledBuffer ,
1845- row_num : & mut usize | {
1846- // Print the span column to avoid confusion
1847- buffer. puts (
1848- * row_num,
1849- 0 ,
1850- & self . maybe_anonymized ( line_start + line_pos) ,
1851- Style :: LineNumber ,
1852- ) ;
1853- if let DisplaySuggestion :: Diff = show_code_change {
1854- // Add the line number for both addition and removal to drive the point home.
1855- //
1856- // N - fn foo<A: T>(bar: A) {
1857- // N + fn foo(bar: impl T) {
1858- buffer. puts (
1859- * row_num - 1 ,
1860- 0 ,
1861- & self . maybe_anonymized ( line_start + line_pos) ,
1862- Style :: LineNumber ,
1863- ) ;
1864- buffer. puts ( * row_num - 1 , max_line_num_len + 1 , "- " , Style :: Removal ) ;
1865- buffer. puts (
1866- * row_num - 1 ,
1867- max_line_num_len + 3 ,
1868- & normalize_whitespace (
1869- & * file_lines
1870- . file
1871- . get_line ( file_lines. lines [ line_pos] . line_index )
1872- . unwrap ( ) ,
1873- ) ,
1874- Style :: NoStyle ,
1875- ) ;
1876- buffer. puts ( * row_num, max_line_num_len + 1 , "+ " , Style :: Addition ) ;
1877- } else if is_multiline {
1878- match & highlight_parts[ ..] {
1879- [ SubstitutionHighlight { start : 0 , end } ] if * end == line. len ( ) => {
1880- buffer. puts ( * row_num, max_line_num_len + 1 , "+ " , Style :: Addition ) ;
1881- }
1882- [ ] => {
1883- draw_col_separator ( buffer, * row_num, max_line_num_len + 1 ) ;
1884- }
1885- _ => {
1886- buffer. puts ( * row_num, max_line_num_len + 1 , "~ " , Style :: Addition ) ;
1887- }
1888- }
1889- } else {
1890- draw_col_separator ( buffer, * row_num, max_line_num_len + 1 ) ;
1891- }
1892-
1893- // print the suggestion
1894- buffer. append ( * row_num, & normalize_whitespace ( line) , Style :: NoStyle ) ;
1895-
1896- // Colorize addition/replacements with green.
1897- for & SubstitutionHighlight { start, end } in highlight_parts {
1898- // Account for tabs when highlighting (#87972).
1899- let tabs: usize = line
1900- . chars ( )
1901- . take ( start)
1902- . map ( |ch| match ch {
1903- '\t' => 3 ,
1904- _ => 0 ,
1905- } )
1906- . sum ( ) ;
1907- buffer. set_style_range (
1908- * row_num,
1909- max_line_num_len + 3 + start + tabs,
1910- max_line_num_len + 3 + end + tabs,
1911- Style :: Addition ,
1912- true ,
1913- ) ;
1914- }
1915- * row_num += 1 ;
1916- } ;
1917-
1835+ // Remember lines that are not highlighted to hide them if needed
19181836 if highlight_parts. is_empty ( ) {
19191837 unhighlighted_lines. push ( ( line_pos, line) ) ;
19201838 continue ;
@@ -1927,22 +1845,77 @@ impl EmitterWriter {
19271845 // (because then we just replace a line with ... which is
19281846 // not helpful)
19291847 n if n <= 3 => unhighlighted_lines. drain ( ..) . for_each ( |( p, l) | {
1930- print_line ( p, l, & Vec :: new ( ) , & mut buffer, & mut row_num)
1848+ self . draw_code_line (
1849+ & mut buffer,
1850+ & mut row_num,
1851+ & Vec :: new ( ) ,
1852+ p,
1853+ l,
1854+ line_start,
1855+ show_code_change,
1856+ max_line_num_len,
1857+ & file_lines,
1858+ is_multiline,
1859+ )
19311860 } ) ,
1861+ // Print first unhighlighted line, "..." and last unhighlighted line, like so:
1862+ //
1863+ // LL | this line was highlighted
1864+ // LL | this line is just for context
1865+ // ...
1866+ // LL | this line is just for context
1867+ // LL | this line was highlighted
19321868 _ => {
1933- unhighlighted_lines
1934- . drain ( ..1 )
1935- . next ( )
1936- . map ( |( p, l) | print_line ( p, l, & Vec :: new ( ) , & mut buffer, & mut row_num) ) ;
1869+ let last_line = unhighlighted_lines. pop ( ) ;
1870+ let first_line = unhighlighted_lines. drain ( ..) . next ( ) ;
1871+
1872+ first_line. map ( |( p, l) | {
1873+ self . draw_code_line (
1874+ & mut buffer,
1875+ & mut row_num,
1876+ & Vec :: new ( ) ,
1877+ p,
1878+ l,
1879+ line_start,
1880+ show_code_change,
1881+ max_line_num_len,
1882+ & file_lines,
1883+ is_multiline,
1884+ )
1885+ } ) ;
1886+
19371887 buffer. puts ( row_num, max_line_num_len - 1 , "..." , Style :: LineNumber ) ;
19381888 row_num += 1 ;
1939- unhighlighted_lines
1940- . pop ( )
1941- . map ( |( p, l) | print_line ( p, l, & Vec :: new ( ) , & mut buffer, & mut row_num) ) ;
1889+
1890+ last_line. map ( |( p, l) | {
1891+ self . draw_code_line (
1892+ & mut buffer,
1893+ & mut row_num,
1894+ & Vec :: new ( ) ,
1895+ p,
1896+ l,
1897+ line_start,
1898+ show_code_change,
1899+ max_line_num_len,
1900+ & file_lines,
1901+ is_multiline,
1902+ )
1903+ } ) ;
19421904 }
19431905 }
19441906
1945- print_line ( line_pos, line, highlight_parts, & mut buffer, & mut row_num)
1907+ self . draw_code_line (
1908+ & mut buffer,
1909+ & mut row_num,
1910+ highlight_parts,
1911+ line_pos,
1912+ line,
1913+ line_start,
1914+ show_code_change,
1915+ max_line_num_len,
1916+ & file_lines,
1917+ is_multiline,
1918+ )
19461919 }
19471920
19481921 // This offset and the ones below need to be signed to account for replacement code
@@ -2127,6 +2100,90 @@ impl EmitterWriter {
21272100 }
21282101 }
21292102 }
2103+
2104+ fn draw_code_line (
2105+ & self ,
2106+ buffer : & mut StyledBuffer ,
2107+ row_num : & mut usize ,
2108+ highlight_parts : & Vec < SubstitutionHighlight > ,
2109+ line_pos : usize ,
2110+ line : & str ,
2111+ line_start : usize ,
2112+ show_code_change : DisplaySuggestion ,
2113+ max_line_num_len : usize ,
2114+ file_lines : & FileLines ,
2115+ is_multiline : bool ,
2116+ ) {
2117+ // Print the span column to avoid confusion
2118+ buffer. puts ( * row_num, 0 , & self . maybe_anonymized ( line_start + line_pos) , Style :: LineNumber ) ;
2119+ if let DisplaySuggestion :: Diff = show_code_change {
2120+ // Add the line number for both addition and removal to drive the point home.
2121+ //
2122+ // N - fn foo<A: T>(bar: A) {
2123+ // N + fn foo(bar: impl T) {
2124+ buffer. puts (
2125+ * row_num - 1 ,
2126+ 0 ,
2127+ & self . maybe_anonymized ( line_start + line_pos) ,
2128+ Style :: LineNumber ,
2129+ ) ;
2130+ buffer. puts ( * row_num - 1 , max_line_num_len + 1 , "- " , Style :: Removal ) ;
2131+ buffer. puts (
2132+ * row_num - 1 ,
2133+ max_line_num_len + 3 ,
2134+ & normalize_whitespace (
2135+ & * file_lines. file . get_line ( file_lines. lines [ line_pos] . line_index ) . unwrap ( ) ,
2136+ ) ,
2137+ Style :: NoStyle ,
2138+ ) ;
2139+ buffer. puts ( * row_num, max_line_num_len + 1 , "+ " , Style :: Addition ) ;
2140+ } else if is_multiline {
2141+ match & highlight_parts[ ..] {
2142+ [ SubstitutionHighlight { start : 0 , end } ] if * end == line. len ( ) => {
2143+ buffer. puts ( * row_num, max_line_num_len + 1 , "+ " , Style :: Addition ) ;
2144+ }
2145+ [ ] => {
2146+ draw_col_separator ( buffer, * row_num, max_line_num_len + 1 ) ;
2147+ }
2148+ _ => {
2149+ buffer. puts ( * row_num, max_line_num_len + 1 , "~ " , Style :: Addition ) ;
2150+ }
2151+ }
2152+ } else {
2153+ draw_col_separator ( buffer, * row_num, max_line_num_len + 1 ) ;
2154+ }
2155+
2156+ // print the suggestion
2157+ buffer. append ( * row_num, & normalize_whitespace ( line) , Style :: NoStyle ) ;
2158+
2159+ // Colorize addition/replacements with green.
2160+ for & SubstitutionHighlight { start, end } in highlight_parts {
2161+ // Account for tabs when highlighting (#87972).
2162+ let tabs: usize = line
2163+ . chars ( )
2164+ . take ( start)
2165+ . map ( |ch| match ch {
2166+ '\t' => 3 ,
2167+ _ => 0 ,
2168+ } )
2169+ . sum ( ) ;
2170+ buffer. set_style_range (
2171+ * row_num,
2172+ max_line_num_len + 3 + start + tabs,
2173+ max_line_num_len + 3 + end + tabs,
2174+ Style :: Addition ,
2175+ true ,
2176+ ) ;
2177+ }
2178+ * row_num += 1 ;
2179+ }
2180+ }
2181+
2182+ #[ derive( Clone , Copy ) ]
2183+ enum DisplaySuggestion {
2184+ Underline ,
2185+ Diff ,
2186+ None ,
21302187}
21312188
21322189impl FileWithAnnotatedLines {
0 commit comments