|
10 | 10 | use Destination::*; |
11 | 11 |
|
12 | 12 | use rustc_span::source_map::SourceMap; |
13 | | -use rustc_span::{SourceFile, Span}; |
| 13 | +use rustc_span::{FileLines, SourceFile, Span}; |
14 | 14 |
|
15 | 15 | use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString}; |
16 | 16 | use crate::styled_buffer::StyledBuffer; |
@@ -1761,12 +1761,6 @@ impl EmitterWriter { |
1761 | 1761 | let has_deletion = parts.iter().any(|p| p.is_deletion()); |
1762 | 1762 | let is_multiline = complete.lines().count() > 1; |
1763 | 1763 |
|
1764 | | - enum DisplaySuggestion { |
1765 | | - Underline, |
1766 | | - Diff, |
1767 | | - None, |
1768 | | - } |
1769 | | - |
1770 | 1764 | if let Some(span) = span.primary_span() { |
1771 | 1765 | // Compare the primary span of the diagnostic with the span of the suggestion |
1772 | 1766 | // being emitted. If they belong to the same file, we don't *need* to show the |
@@ -1839,79 +1833,94 @@ impl EmitterWriter { |
1839 | 1833 | } |
1840 | 1834 | row_num += line_end - line_start; |
1841 | 1835 | } |
1842 | | - for (line_pos, (line, highlight_parts)) in |
1843 | | - lines.by_ref().zip(highlights).take(MAX_SUGGESTION_HIGHLIGHT_LINES).enumerate() |
1844 | | - { |
1845 | | - // Print the span column to avoid confusion |
1846 | | - buffer.puts( |
1847 | | - row_num, |
1848 | | - 0, |
1849 | | - &self.maybe_anonymized(line_start + line_pos), |
1850 | | - Style::LineNumber, |
1851 | | - ); |
1852 | | - if let DisplaySuggestion::Diff = show_code_change { |
1853 | | - // Add the line number for both addition and removal to drive the point home. |
1854 | | - // |
1855 | | - // N - fn foo<A: T>(bar: A) { |
1856 | | - // N + fn foo(bar: impl T) { |
1857 | | - buffer.puts( |
1858 | | - row_num - 1, |
1859 | | - 0, |
1860 | | - &self.maybe_anonymized(line_start + line_pos), |
1861 | | - Style::LineNumber, |
1862 | | - ); |
1863 | | - buffer.puts(row_num - 1, max_line_num_len + 1, "- ", Style::Removal); |
1864 | | - buffer.puts( |
1865 | | - row_num - 1, |
1866 | | - max_line_num_len + 3, |
1867 | | - &normalize_whitespace( |
1868 | | - &*file_lines |
1869 | | - .file |
1870 | | - .get_line(file_lines.lines[line_pos].line_index) |
1871 | | - .unwrap(), |
1872 | | - ), |
1873 | | - Style::NoStyle, |
1874 | | - ); |
1875 | | - buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition); |
1876 | | - } else if is_multiline { |
1877 | | - match &highlight_parts[..] { |
1878 | | - [SubstitutionHighlight { start: 0, end }] if *end == line.len() => { |
1879 | | - buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition); |
1880 | | - } |
1881 | | - [] => { |
1882 | | - draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); |
1883 | | - } |
1884 | | - _ => { |
1885 | | - buffer.puts(row_num, max_line_num_len + 1, "~ ", Style::Addition); |
1886 | | - } |
1887 | | - } |
1888 | | - } else { |
1889 | | - draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); |
| 1836 | + let mut unhighlighted_lines = Vec::new(); |
| 1837 | + for (line_pos, (line, highlight_parts)) in lines.by_ref().zip(highlights).enumerate() { |
| 1838 | + debug!(%line_pos, %line, ?highlight_parts); |
| 1839 | + |
| 1840 | + // Remember lines that are not highlighted to hide them if needed |
| 1841 | + if highlight_parts.is_empty() { |
| 1842 | + unhighlighted_lines.push((line_pos, line)); |
| 1843 | + continue; |
1890 | 1844 | } |
1891 | 1845 |
|
1892 | | - // print the suggestion |
1893 | | - buffer.append(row_num, &normalize_whitespace(line), Style::NoStyle); |
| 1846 | + match unhighlighted_lines.len() { |
| 1847 | + 0 => (), |
| 1848 | + // Since we show first line, "..." line and last line, |
| 1849 | + // There is no reason to hide if there are 3 or less lines |
| 1850 | + // (because then we just replace a line with ... which is |
| 1851 | + // not helpful) |
| 1852 | + n if n <= 3 => unhighlighted_lines.drain(..).for_each(|(p, l)| { |
| 1853 | + self.draw_code_line( |
| 1854 | + &mut buffer, |
| 1855 | + &mut row_num, |
| 1856 | + &Vec::new(), |
| 1857 | + p, |
| 1858 | + l, |
| 1859 | + line_start, |
| 1860 | + show_code_change, |
| 1861 | + max_line_num_len, |
| 1862 | + &file_lines, |
| 1863 | + is_multiline, |
| 1864 | + ) |
| 1865 | + }), |
| 1866 | + // Print first unhighlighted line, "..." and last unhighlighted line, like so: |
| 1867 | + // |
| 1868 | + // LL | this line was highlighted |
| 1869 | + // LL | this line is just for context |
| 1870 | + // ... |
| 1871 | + // LL | this line is just for context |
| 1872 | + // LL | this line was highlighted |
| 1873 | + _ => { |
| 1874 | + let last_line = unhighlighted_lines.pop(); |
| 1875 | + let first_line = unhighlighted_lines.drain(..).next(); |
| 1876 | + |
| 1877 | + first_line.map(|(p, l)| { |
| 1878 | + self.draw_code_line( |
| 1879 | + &mut buffer, |
| 1880 | + &mut row_num, |
| 1881 | + &Vec::new(), |
| 1882 | + p, |
| 1883 | + l, |
| 1884 | + line_start, |
| 1885 | + show_code_change, |
| 1886 | + max_line_num_len, |
| 1887 | + &file_lines, |
| 1888 | + is_multiline, |
| 1889 | + ) |
| 1890 | + }); |
1894 | 1891 |
|
1895 | | - // Colorize addition/replacements with green. |
1896 | | - for &SubstitutionHighlight { start, end } in highlight_parts { |
1897 | | - // Account for tabs when highlighting (#87972). |
1898 | | - let tabs: usize = line |
1899 | | - .chars() |
1900 | | - .take(start) |
1901 | | - .map(|ch| match ch { |
1902 | | - '\t' => 3, |
1903 | | - _ => 0, |
1904 | | - }) |
1905 | | - .sum(); |
1906 | | - buffer.set_style_range( |
1907 | | - row_num, |
1908 | | - max_line_num_len + 3 + start + tabs, |
1909 | | - max_line_num_len + 3 + end + tabs, |
1910 | | - Style::Addition, |
1911 | | - true, |
1912 | | - ); |
| 1892 | + buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); |
| 1893 | + row_num += 1; |
| 1894 | + |
| 1895 | + last_line.map(|(p, l)| { |
| 1896 | + self.draw_code_line( |
| 1897 | + &mut buffer, |
| 1898 | + &mut row_num, |
| 1899 | + &Vec::new(), |
| 1900 | + p, |
| 1901 | + l, |
| 1902 | + line_start, |
| 1903 | + show_code_change, |
| 1904 | + max_line_num_len, |
| 1905 | + &file_lines, |
| 1906 | + is_multiline, |
| 1907 | + ) |
| 1908 | + }); |
| 1909 | + } |
1913 | 1910 | } |
1914 | | - row_num += 1; |
| 1911 | + |
| 1912 | + self.draw_code_line( |
| 1913 | + &mut buffer, |
| 1914 | + &mut row_num, |
| 1915 | + highlight_parts, |
| 1916 | + line_pos, |
| 1917 | + line, |
| 1918 | + line_start, |
| 1919 | + show_code_change, |
| 1920 | + max_line_num_len, |
| 1921 | + &file_lines, |
| 1922 | + is_multiline, |
| 1923 | + ) |
1915 | 1924 | } |
1916 | 1925 |
|
1917 | 1926 | // This offset and the ones below need to be signed to account for replacement code |
@@ -2096,6 +2105,90 @@ impl EmitterWriter { |
2096 | 2105 | } |
2097 | 2106 | } |
2098 | 2107 | } |
| 2108 | + |
| 2109 | + fn draw_code_line( |
| 2110 | + &self, |
| 2111 | + buffer: &mut StyledBuffer, |
| 2112 | + row_num: &mut usize, |
| 2113 | + highlight_parts: &Vec<SubstitutionHighlight>, |
| 2114 | + line_pos: usize, |
| 2115 | + line: &str, |
| 2116 | + line_start: usize, |
| 2117 | + show_code_change: DisplaySuggestion, |
| 2118 | + max_line_num_len: usize, |
| 2119 | + file_lines: &FileLines, |
| 2120 | + is_multiline: bool, |
| 2121 | + ) { |
| 2122 | + // Print the span column to avoid confusion |
| 2123 | + buffer.puts(*row_num, 0, &self.maybe_anonymized(line_start + line_pos), Style::LineNumber); |
| 2124 | + if let DisplaySuggestion::Diff = show_code_change { |
| 2125 | + // Add the line number for both addition and removal to drive the point home. |
| 2126 | + // |
| 2127 | + // N - fn foo<A: T>(bar: A) { |
| 2128 | + // N + fn foo(bar: impl T) { |
| 2129 | + buffer.puts( |
| 2130 | + *row_num - 1, |
| 2131 | + 0, |
| 2132 | + &self.maybe_anonymized(line_start + line_pos), |
| 2133 | + Style::LineNumber, |
| 2134 | + ); |
| 2135 | + buffer.puts(*row_num - 1, max_line_num_len + 1, "- ", Style::Removal); |
| 2136 | + buffer.puts( |
| 2137 | + *row_num - 1, |
| 2138 | + max_line_num_len + 3, |
| 2139 | + &normalize_whitespace( |
| 2140 | + &*file_lines.file.get_line(file_lines.lines[line_pos].line_index).unwrap(), |
| 2141 | + ), |
| 2142 | + Style::NoStyle, |
| 2143 | + ); |
| 2144 | + buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition); |
| 2145 | + } else if is_multiline { |
| 2146 | + match &highlight_parts[..] { |
| 2147 | + [SubstitutionHighlight { start: 0, end }] if *end == line.len() => { |
| 2148 | + buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition); |
| 2149 | + } |
| 2150 | + [] => { |
| 2151 | + draw_col_separator(buffer, *row_num, max_line_num_len + 1); |
| 2152 | + } |
| 2153 | + _ => { |
| 2154 | + buffer.puts(*row_num, max_line_num_len + 1, "~ ", Style::Addition); |
| 2155 | + } |
| 2156 | + } |
| 2157 | + } else { |
| 2158 | + draw_col_separator(buffer, *row_num, max_line_num_len + 1); |
| 2159 | + } |
| 2160 | + |
| 2161 | + // print the suggestion |
| 2162 | + buffer.append(*row_num, &normalize_whitespace(line), Style::NoStyle); |
| 2163 | + |
| 2164 | + // Colorize addition/replacements with green. |
| 2165 | + for &SubstitutionHighlight { start, end } in highlight_parts { |
| 2166 | + // Account for tabs when highlighting (#87972). |
| 2167 | + let tabs: usize = line |
| 2168 | + .chars() |
| 2169 | + .take(start) |
| 2170 | + .map(|ch| match ch { |
| 2171 | + '\t' => 3, |
| 2172 | + _ => 0, |
| 2173 | + }) |
| 2174 | + .sum(); |
| 2175 | + buffer.set_style_range( |
| 2176 | + *row_num, |
| 2177 | + max_line_num_len + 3 + start + tabs, |
| 2178 | + max_line_num_len + 3 + end + tabs, |
| 2179 | + Style::Addition, |
| 2180 | + true, |
| 2181 | + ); |
| 2182 | + } |
| 2183 | + *row_num += 1; |
| 2184 | + } |
| 2185 | +} |
| 2186 | + |
| 2187 | +#[derive(Clone, Copy)] |
| 2188 | +enum DisplaySuggestion { |
| 2189 | + Underline, |
| 2190 | + Diff, |
| 2191 | + None, |
2099 | 2192 | } |
2100 | 2193 |
|
2101 | 2194 | impl FileWithAnnotatedLines { |
|
0 commit comments