aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/syntax_highlighting
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/syntax_highlighting')
-rw-r--r--crates/ra_ide/src/syntax_highlighting/html.rs4
-rw-r--r--crates/ra_ide/src/syntax_highlighting/injection.rs16
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tags.rs2
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs58
4 files changed, 61 insertions, 19 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting/html.rs b/crates/ra_ide/src/syntax_highlighting/html.rs
index 5bada6252..99b6b25ab 100644
--- a/crates/ra_ide/src/syntax_highlighting/html.rs
+++ b/crates/ra_ide/src/syntax_highlighting/html.rs
@@ -19,7 +19,7 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo
19 ) 19 )
20 } 20 }
21 21
22 let ranges = highlight(db, file_id, None); 22 let ranges = highlight(db, file_id, None, false);
23 let text = parse.tree().syntax().to_string(); 23 let text = parse.tree().syntax().to_string();
24 let mut prev_pos = TextSize::from(0); 24 let mut prev_pos = TextSize::from(0);
25 let mut buf = String::new(); 25 let mut buf = String::new();
@@ -84,6 +84,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
84.variable { color: #DCDCCC; } 84.variable { color: #DCDCCC; }
85.format_specifier { color: #CC696B; } 85.format_specifier { color: #CC696B; }
86.mutable { text-decoration: underline; } 86.mutable { text-decoration: underline; }
87.unresolved_reference { color: #FC5555; }
88.escape_sequence { color: #94BFF3; }
87 89
88.keyword { color: #F0DFAF; font-weight: bold; } 90.keyword { color: #F0DFAF; font-weight: bold; }
89.keyword.unsafe { color: #BC8383; font-weight: bold; } 91.keyword.unsafe { color: #BC8383; font-weight: bold; }
diff --git a/crates/ra_ide/src/syntax_highlighting/injection.rs b/crates/ra_ide/src/syntax_highlighting/injection.rs
index 3575a0fc6..929a5cc5c 100644
--- a/crates/ra_ide/src/syntax_highlighting/injection.rs
+++ b/crates/ra_ide/src/syntax_highlighting/injection.rs
@@ -53,6 +53,10 @@ pub(super) fn highlight_injection(
53/// Mapping from extracted documentation code to original code 53/// Mapping from extracted documentation code to original code
54type RangesMap = BTreeMap<TextSize, TextSize>; 54type RangesMap = BTreeMap<TextSize, TextSize>;
55 55
56const RUSTDOC_FENCE: &'static str = "```";
57const RUSTDOC_FENCE_TOKENS: &[&'static str] =
58 &["", "rust", "should_panic", "ignore", "no_run", "compile_fail", "edition2015", "edition2018"];
59
56/// Extracts Rust code from documentation comments as well as a mapping from 60/// Extracts Rust code from documentation comments as well as a mapping from
57/// the extracted source code back to the original source ranges. 61/// the extracted source code back to the original source ranges.
58/// Lastly, a vector of new comment highlight ranges (spanning only the 62/// Lastly, a vector of new comment highlight ranges (spanning only the
@@ -67,6 +71,7 @@ pub(super) fn extract_doc_comments(
67 // Mapping from extracted documentation code to original code 71 // Mapping from extracted documentation code to original code
68 let mut range_mapping: RangesMap = BTreeMap::new(); 72 let mut range_mapping: RangesMap = BTreeMap::new();
69 let mut line_start = TextSize::try_from(prefix.len()).unwrap(); 73 let mut line_start = TextSize::try_from(prefix.len()).unwrap();
74 let mut is_codeblock = false;
70 let mut is_doctest = false; 75 let mut is_doctest = false;
71 // Replace the original, line-spanning comment ranges by new, only comment-prefix 76 // Replace the original, line-spanning comment ranges by new, only comment-prefix
72 // spanning comment ranges. 77 // spanning comment ranges.
@@ -76,8 +81,13 @@ pub(super) fn extract_doc_comments(
76 .filter_map(|el| el.into_token().and_then(ast::Comment::cast)) 81 .filter_map(|el| el.into_token().and_then(ast::Comment::cast))
77 .filter(|comment| comment.kind().doc.is_some()) 82 .filter(|comment| comment.kind().doc.is_some())
78 .filter(|comment| { 83 .filter(|comment| {
79 if comment.text().contains("```") { 84 if let Some(idx) = comment.text().find(RUSTDOC_FENCE) {
80 is_doctest = !is_doctest; 85 is_codeblock = !is_codeblock;
86 // Check whether code is rust by inspecting fence guards
87 let guards = &comment.text()[idx + RUSTDOC_FENCE.len()..];
88 let is_rust =
89 guards.split(',').all(|sub| RUSTDOC_FENCE_TOKENS.contains(&sub.trim()));
90 is_doctest = is_codeblock && is_rust;
81 false 91 false
82 } else { 92 } else {
83 is_doctest 93 is_doctest
@@ -137,7 +147,7 @@ pub(super) fn highlight_doc_comment(
137 let (analysis, tmp_file_id) = Analysis::from_single_file(text); 147 let (analysis, tmp_file_id) = Analysis::from_single_file(text);
138 148
139 stack.push(); 149 stack.push();
140 for mut h in analysis.highlight(tmp_file_id).unwrap() { 150 for mut h in analysis.with_db(|db| super::highlight(db, tmp_file_id, None, true)).unwrap() {
141 // Determine start offset and end offset in case of multi-line ranges 151 // Determine start offset and end offset in case of multi-line ranges
142 let mut start_offset = None; 152 let mut start_offset = None;
143 let mut end_offset = None; 153 let mut end_offset = None;
diff --git a/crates/ra_ide/src/syntax_highlighting/tags.rs b/crates/ra_ide/src/syntax_highlighting/tags.rs
index 94f466966..400d22fb6 100644
--- a/crates/ra_ide/src/syntax_highlighting/tags.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tags.rs
@@ -23,6 +23,7 @@ pub enum HighlightTag {
23 Constant, 23 Constant,
24 Enum, 24 Enum,
25 EnumVariant, 25 EnumVariant,
26 EscapeSequence,
26 Field, 27 Field,
27 FormatSpecifier, 28 FormatSpecifier,
28 Function, 29 Function,
@@ -71,6 +72,7 @@ impl HighlightTag {
71 HighlightTag::Constant => "constant", 72 HighlightTag::Constant => "constant",
72 HighlightTag::Enum => "enum", 73 HighlightTag::Enum => "enum",
73 HighlightTag::EnumVariant => "enum_variant", 74 HighlightTag::EnumVariant => "enum_variant",
75 HighlightTag::EscapeSequence => "escape_sequence",
74 HighlightTag::Field => "field", 76 HighlightTag::Field => "field",
75 HighlightTag::FormatSpecifier => "format_specifier", 77 HighlightTag::FormatSpecifier => "format_specifier",
76 HighlightTag::Function => "function", 78 HighlightTag::Function => "function",
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs
index 021f8e7e2..b4d56a7a0 100644
--- a/crates/ra_ide/src/syntax_highlighting/tests.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tests.rs
@@ -7,18 +7,6 @@ use crate::{
7 FileRange, TextRange, 7 FileRange, TextRange,
8}; 8};
9 9
10/// Highlights the code given by the `ra_fixture` argument, renders the
11/// result as HTML, and compares it with the HTML file given as `snapshot`.
12/// Note that the `snapshot` file is overwritten by the rendered HTML.
13fn check_highlighting(ra_fixture: &str, snapshot: &str, rainbow: bool) {
14 let (analysis, file_id) = single_file(ra_fixture);
15 let dst_file = project_dir().join(snapshot);
16 let actual_html = &analysis.highlight_as_html(file_id, rainbow).unwrap();
17 let expected_html = &read_text(&dst_file);
18 fs::write(dst_file, &actual_html).unwrap();
19 assert_eq_text!(expected_html, actual_html);
20}
21
22#[test] 10#[test]
23fn test_highlighting() { 11fn test_highlighting() {
24 check_highlighting( 12 check_highlighting(
@@ -55,6 +43,12 @@ def_fn! {
55 } 43 }
56} 44}
57 45
46macro_rules! noop {
47 ($expr:expr) => {
48 $expr
49 }
50}
51
58// comment 52// comment
59fn main() { 53fn main() {
60 println!("Hello, {}!", 92); 54 println!("Hello, {}!", 92);
@@ -73,10 +67,14 @@ fn main() {
73 // Do nothing 67 // Do nothing
74 } 68 }
75 69
70 noop!(noop!(1));
71
76 let mut x = 42; 72 let mut x = 42;
77 let y = &mut x; 73 let y = &mut x;
78 let z = &y; 74 let z = &y;
79 75
76 let Foo { x: z, y } = Foo { x: z, y };
77
80 y; 78 y;
81} 79}
82 80
@@ -248,6 +246,10 @@ fn main() {
248 246
249 println!(r"Hello, {}!", "world"); 247 println!(r"Hello, {}!", "world");
250 248
249 // escape sequences
250 println!("Hello\nWorld");
251 println!("\u{48}\x65\x6C\x6C\x6F World");
252
251 println!("{\x41}", A = 92); 253 println!("{\x41}", A = 92);
252 println!("{ничоси}", ничоси = 92); 254 println!("{ничоси}", ничоси = 92);
253}"# 255}"#
@@ -289,7 +291,13 @@ fn main() {
289fn test_highlight_doctest() { 291fn test_highlight_doctest() {
290 check_highlighting( 292 check_highlighting(
291 r#" 293 r#"
294struct Foo {
295 bar: bool,
296}
297
292impl Foo { 298impl Foo {
299 pub const bar: bool = true;
300
293 /// Constructs a new `Foo`. 301 /// Constructs a new `Foo`.
294 /// 302 ///
295 /// # Examples 303 /// # Examples
@@ -299,7 +307,7 @@ impl Foo {
299 /// let mut foo: Foo = Foo::new(); 307 /// let mut foo: Foo = Foo::new();
300 /// ``` 308 /// ```
301 pub const fn new() -> Foo { 309 pub const fn new() -> Foo {
302 Foo { } 310 Foo { bar: true }
303 } 311 }
304 312
305 /// `bar` method on `Foo`. 313 /// `bar` method on `Foo`.
@@ -307,11 +315,15 @@ impl Foo {
307 /// # Examples 315 /// # Examples
308 /// 316 ///
309 /// ``` 317 /// ```
318 /// use x::y;
319 ///
310 /// let foo = Foo::new(); 320 /// let foo = Foo::new();
311 /// 321 ///
312 /// // calls bar on foo 322 /// // calls bar on foo
313 /// assert!(foo.bar()); 323 /// assert!(foo.bar());
314 /// 324 ///
325 /// let bar = foo.bar || Foo::bar;
326 ///
315 /// /* multi-line 327 /// /* multi-line
316 /// comment */ 328 /// comment */
317 /// 329 ///
@@ -321,9 +333,13 @@ impl Foo {
321 /// 333 ///
322 /// ``` 334 /// ```
323 /// 335 ///
324 /// ``` 336 /// ```rust,no_run
325 /// let foobar = Foo::new().bar(); 337 /// let foobar = Foo::new().bar();
326 /// ``` 338 /// ```
339 ///
340 /// ```sh
341 /// echo 1
342 /// ```
327 pub fn foo(&self) -> bool { 343 pub fn foo(&self) -> bool {
328 true 344 true
329 } 345 }
@@ -332,5 +348,17 @@ impl Foo {
332 .trim(), 348 .trim(),
333 "crates/ra_ide/src/snapshots/highlight_doctest.html", 349 "crates/ra_ide/src/snapshots/highlight_doctest.html",
334 false, 350 false,
335 ) 351 );
352}
353
354/// Highlights the code given by the `ra_fixture` argument, renders the
355/// result as HTML, and compares it with the HTML file given as `snapshot`.
356/// Note that the `snapshot` file is overwritten by the rendered HTML.
357fn check_highlighting(ra_fixture: &str, snapshot: &str, rainbow: bool) {
358 let (analysis, file_id) = single_file(ra_fixture);
359 let dst_file = project_dir().join(snapshot);
360 let actual_html = &analysis.highlight_as_html(file_id, rainbow).unwrap();
361 let expected_html = &read_text(&dst_file);
362 fs::write(dst_file, &actual_html).unwrap();
363 assert_eq_text!(expected_html, actual_html);
336} 364}