Auto merge of #45953 - estebank:tab-4, r=nikomatsakis

Display `\t` in diagnostics code as four spaces

Follow up to #44386 using the unicode variable width machinery from #45711 to replace tabs in the source code when displaying a diagnostic error with four spaces (instead of only one), while properly accounting for this when calculating underlines.

Partly addresses #44618.
This commit is contained in:
bors 2017-12-06 21:05:53 +00:00
commit 5a2465e2b4
5 changed files with 37 additions and 17 deletions

View file

@ -27,10 +27,21 @@ impl StyledBuffer {
} }
fn replace_tabs(&mut self) { fn replace_tabs(&mut self) {
for line in self.text.iter_mut() { for (line_pos, line) in self.text.iter_mut().enumerate() {
for c in line.iter_mut() { let mut tab_pos = vec![];
for (pos, c) in line.iter().enumerate() {
if *c == '\t' { if *c == '\t' {
*c = ' '; tab_pos.push(pos);
}
}
// start with the tabs at the end of the line to replace them with 4 space chars
for pos in tab_pos.iter().rev() {
assert_eq!(line.remove(*pos), '\t');
// fix the position of the style to match up after replacing the tabs
let s = self.styles[line_pos].remove(*pos);
for _ in 0..4 {
line.insert(*pos, ' ');
self.styles[line_pos].insert(*pos, s);
} }
} }
} }

View file

@ -503,6 +503,8 @@ pub enum NonNarrowChar {
ZeroWidth(BytePos), ZeroWidth(BytePos),
/// Represents a wide (fullwidth) character /// Represents a wide (fullwidth) character
Wide(BytePos), Wide(BytePos),
/// Represents a tab character, represented visually with a width of 4 characters
Tab(BytePos),
} }
impl NonNarrowChar { impl NonNarrowChar {
@ -510,6 +512,7 @@ impl NonNarrowChar {
match width { match width {
0 => NonNarrowChar::ZeroWidth(pos), 0 => NonNarrowChar::ZeroWidth(pos),
2 => NonNarrowChar::Wide(pos), 2 => NonNarrowChar::Wide(pos),
4 => NonNarrowChar::Tab(pos),
_ => panic!("width {} given for non-narrow character", width), _ => panic!("width {} given for non-narrow character", width),
} }
} }
@ -518,7 +521,8 @@ impl NonNarrowChar {
pub fn pos(&self) -> BytePos { pub fn pos(&self) -> BytePos {
match *self { match *self {
NonNarrowChar::ZeroWidth(p) | NonNarrowChar::ZeroWidth(p) |
NonNarrowChar::Wide(p) => p, NonNarrowChar::Wide(p) |
NonNarrowChar::Tab(p) => p,
} }
} }
@ -527,6 +531,7 @@ impl NonNarrowChar {
match *self { match *self {
NonNarrowChar::ZeroWidth(_) => 0, NonNarrowChar::ZeroWidth(_) => 0,
NonNarrowChar::Wide(_) => 2, NonNarrowChar::Wide(_) => 2,
NonNarrowChar::Tab(_) => 4,
} }
} }
} }
@ -538,6 +543,7 @@ impl Add<BytePos> for NonNarrowChar {
match self { match self {
NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs), NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs),
NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs), NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs),
NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos + rhs),
} }
} }
} }
@ -549,6 +555,7 @@ impl Sub<BytePos> for NonNarrowChar {
match self { match self {
NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs), NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs),
NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs), NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs),
NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos - rhs),
} }
} }
} }
@ -868,8 +875,10 @@ impl FileMap {
pub fn record_width(&self, pos: BytePos, ch: char) { pub fn record_width(&self, pos: BytePos, ch: char) {
let width = match ch { let width = match ch {
'\t' | '\n' => '\t' =>
// Tabs will consume one column. // Tabs will consume 4 columns.
4,
'\n' =>
// Make newlines take one column so that displayed spans can point them. // Make newlines take one column so that displayed spans can point them.
1, 1,
ch => ch =>

View file

@ -1,16 +1,16 @@
error[E0425]: cannot find value `bar` in this scope error[E0425]: cannot find value `bar` in this scope
--> $DIR/tab.rs:14:2 --> $DIR/tab.rs:14:2
| |
14 | bar; //~ ERROR cannot find value `bar` 14 | bar; //~ ERROR cannot find value `bar`
| ^^^ not found in this scope | ^^^ not found in this scope
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/tab.rs:18:2 --> $DIR/tab.rs:18:2
| |
17 | fn foo() { 17 | fn foo() {
| - help: try adding a return type: `-> &'static str ` | - help: try adding a return type: `-> &'static str `
18 | "bar boo" //~ ERROR mismatched types 18 | "bar boo" //~ ERROR mismatched types
| ^^^^^^^^^^^ expected (), found reference | ^^^^^^^^^^^^^^^^^^^^ expected (), found reference
| |
= note: expected type `()` = note: expected type `()`
found type `&'static str` found type `&'static str`

View file

@ -1,8 +1,8 @@
error: unterminated double quote string error: unterminated double quote string
--> $DIR/tab_2.rs:14:7 --> $DIR/tab_2.rs:14:7
| |
14 | """; //~ ERROR unterminated double quote 14 | """; //~ ERROR unterminated double quote
| _______^ | ___________________^
15 | | } 15 | | }
| |__^ | |__^

View file

@ -1,11 +1,11 @@
error[E0382]: use of moved value: `some_vec` error[E0382]: use of moved value: `some_vec`
--> $DIR/tab_3.rs:17:20 --> $DIR/tab_3.rs:17:20
| |
15 | some_vec.into_iter(); 15 | some_vec.into_iter();
| -------- value moved here | -------- value moved here
16 | { 16 | {
17 | println!("{:?}", some_vec); //~ ERROR use of moved 17 | println!("{:?}", some_vec); //~ ERROR use of moved
| ^^^^^^^^ value used here after move | ^^^^^^^^ value used here after move
| |
= note: move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait = note: move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait