]> git.lizzy.rs Git - rust.git/blob - src/librustc_errors/styled_buffer.rs
Don't run MIR passes on constructor shims
[rust.git] / src / librustc_errors / styled_buffer.rs
1 // Code for creating styled buffers
2
3 use crate::snippet::{Style, StyledString};
4
5 #[derive(Debug)]
6 pub struct StyledBuffer {
7     text: Vec<Vec<char>>,
8     styles: Vec<Vec<Style>>,
9 }
10
11 impl StyledBuffer {
12     pub fn new() -> StyledBuffer {
13         StyledBuffer {
14             text: vec![],
15             styles: vec![],
16         }
17     }
18
19     fn replace_tabs(&mut self) {
20         for (line_pos, line) in self.text.iter_mut().enumerate() {
21             let mut tab_pos = vec![];
22             for (pos, c) in line.iter().enumerate() {
23                 if *c == '\t' {
24                     tab_pos.push(pos);
25                 }
26             }
27             // start with the tabs at the end of the line to replace them with 4 space chars
28             for pos in tab_pos.iter().rev() {
29                 assert_eq!(line.remove(*pos), '\t');
30                 // fix the position of the style to match up after replacing the tabs
31                 let s = self.styles[line_pos].remove(*pos);
32                 for _ in 0..4 {
33                     line.insert(*pos, ' ');
34                     self.styles[line_pos].insert(*pos, s);
35                 }
36             }
37         }
38     }
39
40     pub fn render(&mut self) -> Vec<Vec<StyledString>> {
41         let mut output: Vec<Vec<StyledString>> = vec![];
42         let mut styled_vec: Vec<StyledString> = vec![];
43
44         // before we render, replace tabs with spaces
45         self.replace_tabs();
46
47         for (row, row_style) in self.text.iter().zip(&self.styles) {
48             let mut current_style = Style::NoStyle;
49             let mut current_text = String::new();
50
51             for (&c, &s) in row.iter().zip(row_style) {
52                 if s != current_style {
53                     if !current_text.is_empty() {
54                         styled_vec.push(StyledString {
55                             text: current_text,
56                             style: current_style,
57                         });
58                     }
59                     current_style = s;
60                     current_text = String::new();
61                 }
62                 current_text.push(c);
63             }
64             if !current_text.is_empty() {
65                 styled_vec.push(StyledString {
66                     text: current_text,
67                     style: current_style,
68                 });
69             }
70
71             // We're done with the row, push and keep going
72             output.push(styled_vec);
73
74             styled_vec = vec![];
75         }
76
77         output
78     }
79
80     fn ensure_lines(&mut self, line: usize) {
81         while line >= self.text.len() {
82             self.text.push(vec![]);
83             self.styles.push(vec![]);
84         }
85     }
86
87     pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
88         self.ensure_lines(line);
89         if col < self.text[line].len() {
90             self.text[line][col] = chr;
91             self.styles[line][col] = style;
92         } else {
93             let mut i = self.text[line].len();
94             while i < col {
95                 self.text[line].push(' ');
96                 self.styles[line].push(Style::NoStyle);
97                 i += 1;
98             }
99             self.text[line].push(chr);
100             self.styles[line].push(style);
101         }
102     }
103
104     pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
105         let mut n = col;
106         for c in string.chars() {
107             self.putc(line, n, c, style);
108             n += 1;
109         }
110     }
111
112     pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
113         self.ensure_lines(line);
114         let string_len = string.len();
115
116         // Push the old content over to make room for new content
117         for _ in 0..string_len {
118             self.styles[line].insert(0, Style::NoStyle);
119             self.text[line].insert(0, ' ');
120         }
121
122         self.puts(line, 0, string, style);
123     }
124
125     pub fn append(&mut self, line: usize, string: &str, style: Style) {
126         if line >= self.text.len() {
127             self.puts(line, 0, string, style);
128         } else {
129             let col = self.text[line].len();
130             self.puts(line, col, string, style);
131         }
132     }
133
134     pub fn num_lines(&self) -> usize {
135         self.text.len()
136     }
137
138     pub fn set_style_range(&mut self,
139                            line: usize,
140                            col_start: usize,
141                            col_end: usize,
142                            style: Style,
143                            overwrite: bool) {
144         for col in col_start..col_end {
145             self.set_style(line, col, style, overwrite);
146         }
147     }
148
149     pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
150         if let Some(ref mut line) = self.styles.get_mut(line) {
151             if let Some(s) = line.get_mut(col) {
152                 if *s == Style::NoStyle || *s == Style::Quotation || overwrite {
153                     *s = style;
154                 }
155             }
156         }
157     }
158 }