Skip to content

Commit 3537bd8

Browse files
committed
Replace tabs earlier in diagnostics
This replaces tabs earlier in the diagnostics emitting process, which allows various margin calculations to ignore the existence of tabs. It does add a string copy for the source lines that are emitted.
1 parent 8ca8b77 commit 3537bd8

File tree

2 files changed

+23
-29
lines changed

2 files changed

+23
-29
lines changed

compiler/rustc_errors/src/emitter.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,8 @@ impl EmitterWriter {
644644
code_offset: usize,
645645
margin: Margin,
646646
) {
647+
// Tabs are assumed to have been replaced by spaces in calling code.
648+
assert!(!source_string.contains('\t'));
647649
let line_len = source_string.len();
648650
// Create the source line we will highlight.
649651
let left = margin.left(line_len);
@@ -707,7 +709,7 @@ impl EmitterWriter {
707709
}
708710

709711
let source_string = match file.get_line(line.line_index - 1) {
710-
Some(s) => s,
712+
Some(s) => replace_tabs(&*s),
711713
None => return Vec::new(),
712714
};
713715

@@ -1376,8 +1378,17 @@ impl EmitterWriter {
13761378
let file = annotated_file.file.clone();
13771379
let line = &annotated_file.lines[line_idx];
13781380
if let Some(source_string) = file.get_line(line.line_index - 1) {
1379-
let leading_whitespace =
1380-
source_string.chars().take_while(|c| c.is_whitespace()).count();
1381+
let leading_whitespace = source_string
1382+
.chars()
1383+
.take_while(|c| c.is_whitespace())
1384+
.map(|c| {
1385+
match c {
1386+
// Tabs are displayed as 4 spaces
1387+
'\t' => 4,
1388+
_ => 1,
1389+
}
1390+
})
1391+
.sum();
13811392
if source_string.chars().any(|c| !c.is_whitespace()) {
13821393
whitespace_margin = min(whitespace_margin, leading_whitespace);
13831394
}
@@ -1502,7 +1513,7 @@ impl EmitterWriter {
15021513

15031514
self.draw_line(
15041515
&mut buffer,
1505-
&unannotated_line,
1516+
&replace_tabs(&unannotated_line),
15061517
annotated_file.lines[line_idx + 1].line_index - 1,
15071518
last_buffer_line_num,
15081519
width_offset,
@@ -1598,7 +1609,7 @@ impl EmitterWriter {
15981609
);
15991610
// print the suggestion
16001611
draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
1601-
buffer.append(row_num, line, Style::NoStyle);
1612+
buffer.append(row_num, &replace_tabs(line), Style::NoStyle);
16021613
row_num += 1;
16031614
}
16041615

@@ -1930,6 +1941,10 @@ impl FileWithAnnotatedLines {
19301941
}
19311942
}
19321943

1944+
fn replace_tabs(str: &str) -> String {
1945+
str.replace('\t', " ")
1946+
}
1947+
19331948
fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
19341949
buffer.puts(line, col, "| ", Style::LineNumber);
19351950
}

compiler/rustc_errors/src/styled_buffer.rs

+3-24
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,13 @@ impl StyledBuffer {
1313
StyledBuffer { text: vec![], styles: vec![] }
1414
}
1515

16-
fn replace_tabs(&mut self) {
17-
for (line_pos, line) in self.text.iter_mut().enumerate() {
18-
let mut tab_pos = vec![];
19-
for (pos, c) in line.iter().enumerate() {
20-
if *c == '\t' {
21-
tab_pos.push(pos);
22-
}
23-
}
24-
// start with the tabs at the end of the line to replace them with 4 space chars
25-
for pos in tab_pos.iter().rev() {
26-
assert_eq!(line.remove(*pos), '\t');
27-
// fix the position of the style to match up after replacing the tabs
28-
let s = self.styles[line_pos].remove(*pos);
29-
for _ in 0..4 {
30-
line.insert(*pos, ' ');
31-
self.styles[line_pos].insert(*pos, s);
32-
}
33-
}
34-
}
35-
}
16+
pub fn render(&self) -> Vec<Vec<StyledString>> {
17+
// Tabs are assumed to have been replaced by spaces in calling code.
18+
assert!(self.text.iter().all(|r| !r.contains(&'\t')));
3619

37-
pub fn render(&mut self) -> Vec<Vec<StyledString>> {
3820
let mut output: Vec<Vec<StyledString>> = vec![];
3921
let mut styled_vec: Vec<StyledString> = vec![];
4022

41-
// before we render, replace tabs with spaces
42-
self.replace_tabs();
43-
4423
for (row, row_style) in self.text.iter().zip(&self.styles) {
4524
let mut current_style = Style::NoStyle;
4625
let mut current_text = String::new();

0 commit comments

Comments
 (0)