diff options
Diffstat (limited to 'crates/ra_ide/src/syntax_highlighting')
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/html.rs | 14 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tests.rs | 72 |
2 files changed, 77 insertions, 9 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting/html.rs b/crates/ra_ide/src/syntax_highlighting/html.rs index 4496529a1..010db4017 100644 --- a/crates/ra_ide/src/syntax_highlighting/html.rs +++ b/crates/ra_ide/src/syntax_highlighting/html.rs | |||
@@ -1,11 +1,9 @@ | |||
1 | //! Renders a bit of code as HTML. | 1 | //! Renders a bit of code as HTML. |
2 | 2 | ||
3 | use ra_db::SourceDatabase; | 3 | use ra_db::SourceDatabase; |
4 | use ra_syntax::{AstNode, TextUnit}; | 4 | use ra_syntax::{AstNode, TextRange, TextSize}; |
5 | 5 | ||
6 | use crate::{FileId, RootDatabase}; | 6 | use crate::{syntax_highlighting::highlight, FileId, RootDatabase}; |
7 | |||
8 | use super::highlight; | ||
9 | 7 | ||
10 | pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: bool) -> String { | 8 | pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: bool) -> String { |
11 | let parse = db.parse(file_id); | 9 | let parse = db.parse(file_id); |
@@ -23,17 +21,17 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo | |||
23 | 21 | ||
24 | let ranges = highlight(db, file_id, None); | 22 | let ranges = highlight(db, file_id, None); |
25 | let text = parse.tree().syntax().to_string(); | 23 | let text = parse.tree().syntax().to_string(); |
26 | let mut prev_pos = TextUnit::from(0); | 24 | let mut prev_pos = TextSize::from(0); |
27 | let mut buf = String::new(); | 25 | let mut buf = String::new(); |
28 | buf.push_str(&STYLE); | 26 | buf.push_str(&STYLE); |
29 | buf.push_str("<pre><code>"); | 27 | buf.push_str("<pre><code>"); |
30 | for range in &ranges { | 28 | for range in &ranges { |
31 | if range.range.start() > prev_pos { | 29 | if range.range.start() > prev_pos { |
32 | let curr = &text[prev_pos.to_usize()..range.range.start().to_usize()]; | 30 | let curr = &text[TextRange::new(prev_pos, range.range.start())]; |
33 | let text = html_escape(curr); | 31 | let text = html_escape(curr); |
34 | buf.push_str(&text); | 32 | buf.push_str(&text); |
35 | } | 33 | } |
36 | let curr = &text[range.range.start().to_usize()..range.range.end().to_usize()]; | 34 | let curr = &text[TextRange::new(range.range.start(), range.range.end())]; |
37 | 35 | ||
38 | let class = range.highlight.to_string().replace('.', " "); | 36 | let class = range.highlight.to_string().replace('.', " "); |
39 | let color = match (rainbow, range.binding_hash) { | 37 | let color = match (rainbow, range.binding_hash) { |
@@ -47,7 +45,7 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo | |||
47 | prev_pos = range.range.end(); | 45 | prev_pos = range.range.end(); |
48 | } | 46 | } |
49 | // Add the remaining (non-highlighted) text | 47 | // Add the remaining (non-highlighted) text |
50 | let curr = &text[prev_pos.to_usize()..]; | 48 | let curr = &text[TextRange::new(prev_pos, TextSize::of(&text))]; |
51 | let text = html_escape(curr); | 49 | let text = html_escape(curr); |
52 | buf.push_str(&text); | 50 | buf.push_str(&text); |
53 | buf.push_str("</code></pre>"); | 51 | buf.push_str("</code></pre>"); |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index 73611e23a..d2926ba78 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -126,7 +126,7 @@ fn test_ranges() { | |||
126 | 126 | ||
127 | // The "x" | 127 | // The "x" |
128 | let highlights = &analysis | 128 | let highlights = &analysis |
129 | .highlight_range(FileRange { file_id, range: TextRange::offset_len(82.into(), 1.into()) }) | 129 | .highlight_range(FileRange { file_id, range: TextRange::at(82.into(), 1.into()) }) |
130 | .unwrap(); | 130 | .unwrap(); |
131 | 131 | ||
132 | assert_eq!(&highlights[0].highlight.to_string(), "field.declaration"); | 132 | assert_eq!(&highlights[0].highlight.to_string(), "field.declaration"); |
@@ -168,3 +168,73 @@ macro_rules! test {} | |||
168 | ); | 168 | ); |
169 | let _ = analysis.highlight(file_id).unwrap(); | 169 | let _ = analysis.highlight(file_id).unwrap(); |
170 | } | 170 | } |
171 | |||
172 | #[test] | ||
173 | fn test_string_highlighting() { | ||
174 | // The format string detection is based on macro-expansion, | ||
175 | // thus, we have to copy the macro definition from `std` | ||
176 | let (analysis, file_id) = single_file( | ||
177 | r#" | ||
178 | macro_rules! println { | ||
179 | ($($arg:tt)*) => ({ | ||
180 | $crate::io::_print($crate::format_args_nl!($($arg)*)); | ||
181 | }) | ||
182 | } | ||
183 | #[rustc_builtin_macro] | ||
184 | macro_rules! format_args_nl { | ||
185 | ($fmt:expr) => {{ /* compiler built-in */ }}; | ||
186 | ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }}; | ||
187 | } | ||
188 | |||
189 | fn main() { | ||
190 | // from https://doc.rust-lang.org/std/fmt/index.html | ||
191 | println!("Hello"); // => "Hello" | ||
192 | println!("Hello, {}!", "world"); // => "Hello, world!" | ||
193 | println!("The number is {}", 1); // => "The number is 1" | ||
194 | println!("{:?}", (3, 4)); // => "(3, 4)" | ||
195 | println!("{value}", value=4); // => "4" | ||
196 | println!("{} {}", 1, 2); // => "1 2" | ||
197 | println!("{:04}", 42); // => "0042" with leading zerosV | ||
198 | println!("{1} {} {0} {}", 1, 2); // => "2 1 1 2" | ||
199 | println!("{argument}", argument = "test"); // => "test" | ||
200 | println!("{name} {}", 1, name = 2); // => "2 1" | ||
201 | println!("{a} {c} {b}", a="a", b='b', c=3); // => "a 3 b" | ||
202 | println!("Hello {:5}!", "x"); | ||
203 | println!("Hello {:1$}!", "x", 5); | ||
204 | println!("Hello {1:0$}!", 5, "x"); | ||
205 | println!("Hello {:width$}!", "x", width = 5); | ||
206 | println!("Hello {:<5}!", "x"); | ||
207 | println!("Hello {:-<5}!", "x"); | ||
208 | println!("Hello {:^5}!", "x"); | ||
209 | println!("Hello {:>5}!", "x"); | ||
210 | println!("Hello {:+}!", 5); | ||
211 | println!("{:#x}!", 27); | ||
212 | println!("Hello {:05}!", 5); | ||
213 | println!("Hello {:05}!", -5); | ||
214 | println!("{:#010x}!", 27); | ||
215 | println!("Hello {0} is {1:.5}", "x", 0.01); | ||
216 | println!("Hello {1} is {2:.0$}", 5, "x", 0.01); | ||
217 | println!("Hello {0} is {2:.1$}", "x", 5, 0.01); | ||
218 | println!("Hello {} is {:.*}", "x", 5, 0.01); | ||
219 | println!("Hello {} is {2:.*}", "x", 5, 0.01); | ||
220 | println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01); | ||
221 | println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56); | ||
222 | println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56"); | ||
223 | println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56"); | ||
224 | println!("Hello {{}}"); | ||
225 | println!("{{ Hello"); | ||
226 | |||
227 | println!(r"Hello, {}!", "world"); | ||
228 | |||
229 | println!("{\x41}", A = 92); | ||
230 | println!("{ничоси}", ничоси = 92); | ||
231 | }"# | ||
232 | .trim(), | ||
233 | ); | ||
234 | |||
235 | let dst_file = project_dir().join("crates/ra_ide/src/snapshots/highlight_strings.html"); | ||
236 | let actual_html = &analysis.highlight_as_html(file_id, false).unwrap(); | ||
237 | let expected_html = &read_text(&dst_file); | ||
238 | fs::write(dst_file, &actual_html).unwrap(); | ||
239 | assert_eq_text!(expected_html, actual_html); | ||
240 | } | ||