Skip to content

Commit

Permalink
Replace tabs earlier in diagnostics
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jryans committed Dec 9, 2020
1 parent 8ca8b77 commit 3537bd8
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 29 deletions.
25 changes: 20 additions & 5 deletions compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,8 @@ impl EmitterWriter {
code_offset: usize,
margin: Margin,
) {
// Tabs are assumed to have been replaced by spaces in calling code.
assert!(!source_string.contains('\t'));
let line_len = source_string.len();
// Create the source line we will highlight.
let left = margin.left(line_len);
Expand Down Expand Up @@ -707,7 +709,7 @@ impl EmitterWriter {
}

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

Expand Down Expand Up @@ -1376,8 +1378,17 @@ impl EmitterWriter {
let file = annotated_file.file.clone();
let line = &annotated_file.lines[line_idx];
if let Some(source_string) = file.get_line(line.line_index - 1) {
let leading_whitespace =
source_string.chars().take_while(|c| c.is_whitespace()).count();
let leading_whitespace = source_string
.chars()
.take_while(|c| c.is_whitespace())
.map(|c| {
match c {
// Tabs are displayed as 4 spaces
'\t' => 4,
_ => 1,
}
})
.sum();
if source_string.chars().any(|c| !c.is_whitespace()) {
whitespace_margin = min(whitespace_margin, leading_whitespace);
}
Expand Down Expand Up @@ -1502,7 +1513,7 @@ impl EmitterWriter {

self.draw_line(
&mut buffer,
&unannotated_line,
&replace_tabs(&unannotated_line),
annotated_file.lines[line_idx + 1].line_index - 1,
last_buffer_line_num,
width_offset,
Expand Down Expand Up @@ -1598,7 +1609,7 @@ impl EmitterWriter {
);
// print the suggestion
draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
buffer.append(row_num, line, Style::NoStyle);
buffer.append(row_num, &replace_tabs(line), Style::NoStyle);
row_num += 1;
}

Expand Down Expand Up @@ -1930,6 +1941,10 @@ impl FileWithAnnotatedLines {
}
}

fn replace_tabs(str: &str) -> String {
str.replace('\t', " ")
}

fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
buffer.puts(line, col, "| ", Style::LineNumber);
}
Expand Down
27 changes: 3 additions & 24 deletions compiler/rustc_errors/src/styled_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,13 @@ impl StyledBuffer {
StyledBuffer { text: vec![], styles: vec![] }
}

fn replace_tabs(&mut self) {
for (line_pos, line) in self.text.iter_mut().enumerate() {
let mut tab_pos = vec![];
for (pos, c) in line.iter().enumerate() {
if *c == '\t' {
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);
}
}
}
}
pub fn render(&self) -> Vec<Vec<StyledString>> {
// Tabs are assumed to have been replaced by spaces in calling code.
assert!(self.text.iter().all(|r| !r.contains(&'\t')));

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

// before we render, replace tabs with spaces
self.replace_tabs();

for (row, row_style) in self.text.iter().zip(&self.styles) {
let mut current_style = Style::NoStyle;
let mut current_text = String::new();
Expand Down

0 comments on commit 3537bd8

Please sign in to comment.