diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-27 10:56:06 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-27 10:56:06 +0100 |
commit | 0d1c6076073c73f57340e256dc25da9d37311ef0 (patch) | |
tree | 60ff1f4a42f8ef297c07d5716af67e3057c8e1bd /crates/ra_ide_api/src | |
parent | 4b48cff022a1606bde596f01fbf44361640b10d8 (diff) | |
parent | 1e6ba1901550fb1610a1a464c48ec358cd3c339c (diff) |
Merge #1319
1319: Rainbow highlighting spike 🌈 r=killercup a=killercup
Very simple approach: For each identifier, set the hash of the range
where it's defined as its 'id' and use it in the VSCode extension to
generate unique colors.
Thus, the generated colors are per-file. They are also quite fragile,
and I'm not entirely sure why. Looks like we need to make sure the
same ranges aren't overwritten by a later request?
Co-authored-by: Pascal Hertleif <[email protected]>
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r-- | crates/ra_ide_api/src/lib.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide_api/src/snapshots/highlighting.html | 20 | ||||
-rw-r--r-- | crates/ra_ide_api/src/snapshots/rainbow_highlighting.html | 27 | ||||
-rw-r--r-- | crates/ra_ide_api/src/syntax_highlighting.rs | 130 |
4 files changed, 145 insertions, 38 deletions
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index d3456d5b2..452407e8e 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -463,8 +463,8 @@ impl Analysis { | |||
463 | } | 463 | } |
464 | 464 | ||
465 | /// Computes syntax highlighting for the given file. | 465 | /// Computes syntax highlighting for the given file. |
466 | pub fn highlight_as_html(&self, file_id: FileId) -> Cancelable<String> { | 466 | pub fn highlight_as_html(&self, file_id: FileId, rainbow: bool) -> Cancelable<String> { |
467 | self.with_db(|db| syntax_highlighting::highlight_as_html(db, file_id)) | 467 | self.with_db(|db| syntax_highlighting::highlight_as_html(db, file_id, rainbow)) |
468 | } | 468 | } |
469 | 469 | ||
470 | /// Computes completions at the given position. | 470 | /// Computes completions at the given position. |
@@ -472,7 +472,7 @@ impl Analysis { | |||
472 | self.with_db(|db| completion::completions(db, position).map(Into::into)) | 472 | self.with_db(|db| completion::completions(db, position).map(Into::into)) |
473 | } | 473 | } |
474 | 474 | ||
475 | /// Computes assists (aks code actons aka intentions) for the given | 475 | /// Computes assists (aka code actions aka intentions) for the given |
476 | /// position. | 476 | /// position. |
477 | pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<Assist>> { | 477 | pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<Assist>> { |
478 | self.with_db(|db| assists::assists(db, frange)) | 478 | self.with_db(|db| assists::assists(db, frange)) |
diff --git a/crates/ra_ide_api/src/snapshots/highlighting.html b/crates/ra_ide_api/src/snapshots/highlighting.html index bfc0a67b1..ebd187a35 100644 --- a/crates/ra_ide_api/src/snapshots/highlighting.html +++ b/crates/ra_ide_api/src/snapshots/highlighting.html | |||
@@ -1,10 +1,7 @@ | |||
1 | 1 | ||
2 | <style> | 2 | <style> |
3 | pre { | 3 | body { margin: 0; } |
4 | color: #DCDCCC; | 4 | pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } |
5 | background-color: #3F3F3F; | ||
6 | font-size: 22px; | ||
7 | } | ||
8 | 5 | ||
9 | .comment { color: #7F9F7F; } | 6 | .comment { color: #7F9F7F; } |
10 | .string { color: #CC9393; } | 7 | .string { color: #CC9393; } |
@@ -19,10 +16,8 @@ pre { | |||
19 | .keyword { color: #F0DFAF; } | 16 | .keyword { color: #F0DFAF; } |
20 | .keyword\.unsafe { color: #F0DFAF; font-weight: bold; } | 17 | .keyword\.unsafe { color: #F0DFAF; font-weight: bold; } |
21 | .keyword\.control { color: #DC8CC3; } | 18 | .keyword\.control { color: #DC8CC3; } |
22 | |||
23 | </style> | 19 | </style> |
24 | <pre><code> | 20 | <pre><code><span class="attribute">#</span><span class="attribute">[</span><span class="attribute">derive</span><span class="attribute">(</span><span class="attribute">Clone</span><span class="attribute">,</span><span class="attribute"> </span><span class="attribute">Debug</span><span class="attribute">)</span><span class="attribute">]</span> |
25 | <span class="attribute">#</span><span class="attribute">[</span><span class="attribute">derive</span><span class="attribute">(</span><span class="attribute">Clone</span><span class="attribute">,</span><span class="attribute"> </span><span class="attribute">Debug</span><span class="attribute">)</span><span class="attribute">]</span> | ||
26 | <span class="keyword">struct</span> <span class="function">Foo</span> { | 21 | <span class="keyword">struct</span> <span class="function">Foo</span> { |
27 | <span class="keyword">pub</span> <span class="function">x</span>: <span class="text">i32</span>, | 22 | <span class="keyword">pub</span> <span class="function">x</span>: <span class="text">i32</span>, |
28 | <span class="keyword">pub</span> <span class="function">y</span>: <span class="text">i32</span>, | 23 | <span class="keyword">pub</span> <span class="function">y</span>: <span class="text">i32</span>, |
@@ -36,10 +31,9 @@ pre { | |||
36 | <span class="keyword">fn</span> <span class="function">main</span>() { | 31 | <span class="keyword">fn</span> <span class="function">main</span>() { |
37 | <span class="macro">println</span><span class="macro">!</span>(<span class="string">"Hello, {}!"</span>, <span class="literal">92</span>); | 32 | <span class="macro">println</span><span class="macro">!</span>(<span class="string">"Hello, {}!"</span>, <span class="literal">92</span>); |
38 | 33 | ||
39 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="function">vec</span> = <span class="text">Vec</span>::<span class="text">new</span>(); | 34 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable" data-binding-hash="9636295041291189729" style="color: hsl(51,57%,74%);">vec</span> = <span class="text">Vec</span>::<span class="text">new</span>(); |
40 | <span class="keyword.control">if</span> <span class="keyword">true</span> { | 35 | <span class="keyword.control">if</span> <span class="keyword">true</span> { |
41 | <span class="text">vec</span>.<span class="text">push</span>(<span class="type">Foo</span> { <span class="field">x</span>: <span class="literal">0</span>, <span class="field">y</span>: <span class="literal">1</span> }); | 36 | <span class="variable" data-binding-hash="8496027264380925433" style="color: hsl(18,48%,55%);">vec</span>.<span class="text">push</span>(<span class="type">Foo</span> { <span class="field">x</span>: <span class="literal">0</span>, <span class="field">y</span>: <span class="literal">1</span> }); |
42 | } | 37 | } |
43 | <span class="keyword.unsafe">unsafe</span> { <span class="text">vec</span>.<span class="text">set_len</span>(<span class="literal">0</span>); } | 38 | <span class="keyword.unsafe">unsafe</span> { <span class="variable" data-binding-hash="8496027264380925433" style="color: hsl(18,48%,55%);">vec</span>.<span class="text">set_len</span>(<span class="literal">0</span>); } |
44 | } | 39 | }</code></pre> \ No newline at end of file |
45 | </code></pre> \ No newline at end of file | ||
diff --git a/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html b/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html new file mode 100644 index 000000000..729d129d0 --- /dev/null +++ b/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html | |||
@@ -0,0 +1,27 @@ | |||
1 | |||
2 | <style> | ||
3 | body { margin: 0; } | ||
4 | pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } | ||
5 | |||
6 | .comment { color: #7F9F7F; } | ||
7 | .string { color: #CC9393; } | ||
8 | .function { color: #93E0E3; } | ||
9 | .parameter { color: #94BFF3; } | ||
10 | .builtin { color: #DD6718; } | ||
11 | .text { color: #DCDCCC; } | ||
12 | .attribute { color: #BFEBBF; } | ||
13 | .literal { color: #DFAF8F; } | ||
14 | .macro { color: #DFAF8F; } | ||
15 | |||
16 | .keyword { color: #F0DFAF; } | ||
17 | .keyword\.unsafe { color: #F0DFAF; font-weight: bold; } | ||
18 | .keyword\.control { color: #DC8CC3; } | ||
19 | </style> | ||
20 | <pre><code><span class="keyword">fn</span> <span class="function">main</span>() { | ||
21 | <span class="keyword">let</span> <span class="variable" data-binding-hash="3888301305669440875" style="color: hsl(242,59%,59%);">hello</span> = <span class="string">"hello"</span>; | ||
22 | <span class="keyword">let</span> <span class="variable" data-binding-hash="5695551762718493399" style="color: hsl(272,48%,45%);">x</span> = <span class="variable" data-binding-hash="3888301305669440875" style="color: hsl(242,59%,59%);">hello</span>.<span class="text">to_string</span>(); | ||
23 | <span class="keyword">let</span> <span class="variable" data-binding-hash="5435401749617022797" style="color: hsl(353,77%,74%);">y</span> = <span class="variable" data-binding-hash="3888301305669440875" style="color: hsl(242,59%,59%);">hello</span>.<span class="text">to_string</span>(); | ||
24 | |||
25 | <span class="keyword">let</span> <span class="variable" data-binding-hash="1903207544374197704" style="color: hsl(58,61%,61%);">x</span> = <span class="string">"other color please!"</span>; | ||
26 | <span class="keyword">let</span> <span class="variable" data-binding-hash="14878783531007968800" style="color: hsl(265,73%,83%);">y</span> = <span class="variable" data-binding-hash="1903207544374197704" style="color: hsl(58,61%,61%);">x</span>.<span class="text">to_string</span>(); | ||
27 | }</code></pre> \ No newline at end of file | ||
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 87e053364..dcefb0513 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use rustc_hash::FxHashSet; | 1 | use rustc_hash::{FxHashSet, FxHashMap}; |
2 | 2 | ||
3 | use ra_syntax::{ast, AstNode, TextRange, Direction, SyntaxKind, SyntaxKind::*, SyntaxElement, T}; | 3 | use ra_syntax::{ast, AstNode, TextRange, Direction, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxElement, T}; |
4 | use ra_db::SourceDatabase; | 4 | use ra_db::SourceDatabase; |
5 | use ra_prof::profile; | 5 | use ra_prof::profile; |
6 | 6 | ||
@@ -10,6 +10,7 @@ use crate::{FileId, db::RootDatabase}; | |||
10 | pub struct HighlightedRange { | 10 | pub struct HighlightedRange { |
11 | pub range: TextRange, | 11 | pub range: TextRange, |
12 | pub tag: &'static str, | 12 | pub tag: &'static str, |
13 | pub binding_hash: Option<u64>, | ||
13 | } | 14 | } |
14 | 15 | ||
15 | fn is_control_keyword(kind: SyntaxKind) -> bool { | 16 | fn is_control_keyword(kind: SyntaxKind) -> bool { |
@@ -29,22 +30,36 @@ fn is_control_keyword(kind: SyntaxKind) -> bool { | |||
29 | 30 | ||
30 | pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { | 31 | pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { |
31 | let _p = profile("highlight"); | 32 | let _p = profile("highlight"); |
32 | |||
33 | let source_file = db.parse(file_id); | 33 | let source_file = db.parse(file_id); |
34 | 34 | ||
35 | fn calc_binding_hash(file_id: FileId, text: &SmolStr, shadow_count: u32) -> u64 { | ||
36 | fn hash<T: std::hash::Hash + std::fmt::Debug>(x: T) -> u64 { | ||
37 | use std::{collections::hash_map::DefaultHasher, hash::Hasher}; | ||
38 | |||
39 | let mut hasher = DefaultHasher::new(); | ||
40 | x.hash(&mut hasher); | ||
41 | hasher.finish() | ||
42 | } | ||
43 | |||
44 | hash((file_id, text, shadow_count)) | ||
45 | } | ||
46 | |||
35 | // Visited nodes to handle highlighting priorities | 47 | // Visited nodes to handle highlighting priorities |
36 | let mut highlighted: FxHashSet<SyntaxElement> = FxHashSet::default(); | 48 | let mut highlighted: FxHashSet<SyntaxElement> = FxHashSet::default(); |
49 | let mut bindings_shadow_count: FxHashMap<SmolStr, u32> = FxHashMap::default(); | ||
50 | |||
37 | let mut res = Vec::new(); | 51 | let mut res = Vec::new(); |
38 | for node in source_file.syntax().descendants_with_tokens() { | 52 | for node in source_file.syntax().descendants_with_tokens() { |
39 | if highlighted.contains(&node) { | 53 | if highlighted.contains(&node) { |
40 | continue; | 54 | continue; |
41 | } | 55 | } |
56 | let mut binding_hash = None; | ||
42 | let tag = match node.kind() { | 57 | let tag = match node.kind() { |
43 | COMMENT => "comment", | 58 | COMMENT => "comment", |
44 | STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string", | 59 | STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string", |
45 | ATTR => "attribute", | 60 | ATTR => "attribute", |
46 | NAME_REF => { | 61 | NAME_REF => { |
47 | if let Some(name_ref) = node.as_node().and_then(|n| ast::NameRef::cast(n)) { | 62 | if let Some(name_ref) = node.as_node().and_then(ast::NameRef::cast) { |
48 | use crate::name_ref_kind::{classify_name_ref, NameRefKind::*}; | 63 | use crate::name_ref_kind::{classify_name_ref, NameRefKind::*}; |
49 | use hir::{ModuleDef, ImplItem}; | 64 | use hir::{ModuleDef, ImplItem}; |
50 | 65 | ||
@@ -68,7 +83,20 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
68 | Some(Def(ModuleDef::Trait(_))) => "type", | 83 | Some(Def(ModuleDef::Trait(_))) => "type", |
69 | Some(Def(ModuleDef::TypeAlias(_))) => "type", | 84 | Some(Def(ModuleDef::TypeAlias(_))) => "type", |
70 | Some(SelfType(_)) => "type", | 85 | Some(SelfType(_)) => "type", |
71 | Some(Pat(_)) => "text", | 86 | Some(Pat(ptr)) => { |
87 | binding_hash = Some({ | ||
88 | let text = ptr | ||
89 | .syntax_node_ptr() | ||
90 | .to_node(&source_file.syntax()) | ||
91 | .text() | ||
92 | .to_smol_string(); | ||
93 | let shadow_count = | ||
94 | bindings_shadow_count.entry(text.clone()).or_default(); | ||
95 | calc_binding_hash(file_id, &text, *shadow_count) | ||
96 | }); | ||
97 | |||
98 | "variable" | ||
99 | } | ||
72 | Some(SelfParam(_)) => "type", | 100 | Some(SelfParam(_)) => "type", |
73 | Some(GenericParam(_)) => "type", | 101 | Some(GenericParam(_)) => "type", |
74 | None => "text", | 102 | None => "text", |
@@ -77,7 +105,24 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
77 | "text" | 105 | "text" |
78 | } | 106 | } |
79 | } | 107 | } |
80 | NAME => "function", | 108 | NAME => { |
109 | if let Some(name) = node.as_node().and_then(ast::Name::cast) { | ||
110 | if name.syntax().ancestors().any(|x| ast::BindPat::cast(x).is_some()) { | ||
111 | binding_hash = Some({ | ||
112 | let text = name.syntax().text().to_smol_string(); | ||
113 | let shadow_count = | ||
114 | bindings_shadow_count.entry(text.clone()).or_insert(0); | ||
115 | *shadow_count += 1; | ||
116 | calc_binding_hash(file_id, &text, *shadow_count) | ||
117 | }); | ||
118 | "variable" | ||
119 | } else { | ||
120 | "function" | ||
121 | } | ||
122 | } else { | ||
123 | "text" | ||
124 | } | ||
125 | } | ||
81 | TYPE_ALIAS_DEF | TYPE_ARG | TYPE_PARAM => "type", | 126 | TYPE_ALIAS_DEF | TYPE_ARG | TYPE_PARAM => "type", |
82 | INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal", | 127 | INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal", |
83 | LIFETIME => "parameter", | 128 | LIFETIME => "parameter", |
@@ -85,6 +130,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
85 | k if is_control_keyword(k) => "keyword.control", | 130 | k if is_control_keyword(k) => "keyword.control", |
86 | k if k.is_keyword() => "keyword", | 131 | k if k.is_keyword() => "keyword", |
87 | _ => { | 132 | _ => { |
133 | // let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); | ||
88 | if let Some(macro_call) = node.as_node().and_then(ast::MacroCall::cast) { | 134 | if let Some(macro_call) = node.as_node().and_then(ast::MacroCall::cast) { |
89 | if let Some(path) = macro_call.path() { | 135 | if let Some(path) = macro_call.path() { |
90 | if let Some(segment) = path.segment() { | 136 | if let Some(segment) = path.segment() { |
@@ -101,6 +147,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
101 | res.push(HighlightedRange { | 147 | res.push(HighlightedRange { |
102 | range: TextRange::from_to(range_start, range_end), | 148 | range: TextRange::from_to(range_start, range_end), |
103 | tag: "macro", | 149 | tag: "macro", |
150 | binding_hash: None, | ||
104 | }) | 151 | }) |
105 | } | 152 | } |
106 | } | 153 | } |
@@ -109,14 +156,25 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
109 | continue; | 156 | continue; |
110 | } | 157 | } |
111 | }; | 158 | }; |
112 | res.push(HighlightedRange { range: node.range(), tag }) | 159 | res.push(HighlightedRange { range: node.range(), tag, binding_hash }) |
113 | } | 160 | } |
114 | res | 161 | res |
115 | } | 162 | } |
116 | 163 | ||
117 | pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId) -> String { | 164 | pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: bool) -> String { |
118 | let source_file = db.parse(file_id); | 165 | let source_file = db.parse(file_id); |
119 | 166 | ||
167 | fn rainbowify(seed: u64) -> String { | ||
168 | use rand::prelude::*; | ||
169 | let mut rng = SmallRng::seed_from_u64(seed); | ||
170 | format!( | ||
171 | "hsl({h},{s}%,{l}%)", | ||
172 | h = rng.gen_range::<u16, _, _>(0, 361), | ||
173 | s = rng.gen_range::<u16, _, _>(42, 99), | ||
174 | l = rng.gen_range::<u16, _, _>(40, 91), | ||
175 | ) | ||
176 | } | ||
177 | |||
120 | let mut ranges = highlight(db, file_id); | 178 | let mut ranges = highlight(db, file_id); |
121 | ranges.sort_by_key(|it| it.range.start()); | 179 | ranges.sort_by_key(|it| it.range.start()); |
122 | // quick non-optimal heuristic to intersect token ranges and highlighted ranges | 180 | // quick non-optimal heuristic to intersect token ranges and highlighted ranges |
@@ -138,16 +196,24 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId) -> String { | |||
138 | } | 196 | } |
139 | } | 197 | } |
140 | let text = html_escape(&token.text()); | 198 | let text = html_escape(&token.text()); |
141 | let classes = could_intersect | 199 | let ranges = could_intersect |
142 | .iter() | 200 | .iter() |
143 | .filter(|it| token.range().is_subrange(&it.range)) | 201 | .filter(|it| token.range().is_subrange(&it.range)) |
144 | .map(|it| it.tag) | ||
145 | .collect::<Vec<_>>(); | 202 | .collect::<Vec<_>>(); |
146 | if classes.is_empty() { | 203 | if ranges.is_empty() { |
147 | buf.push_str(&text); | 204 | buf.push_str(&text); |
148 | } else { | 205 | } else { |
149 | let classes = classes.join(" "); | 206 | let classes = ranges.iter().map(|x| x.tag).collect::<Vec<_>>().join(" "); |
150 | buf.push_str(&format!("<span class=\"{}\">{}</span>", classes, text)); | 207 | let binding_hash = ranges.first().and_then(|x| x.binding_hash); |
208 | let color = match (rainbow, binding_hash) { | ||
209 | (true, Some(hash)) => format!( | ||
210 | " data-binding-hash=\"{}\" style=\"color: {};\"", | ||
211 | hash, | ||
212 | rainbowify(hash) | ||
213 | ), | ||
214 | _ => "".into(), | ||
215 | }; | ||
216 | buf.push_str(&format!("<span class=\"{}\"{}>{}</span>", classes, color, text)); | ||
151 | } | 217 | } |
152 | } | 218 | } |
153 | buf.push_str("</code></pre>"); | 219 | buf.push_str("</code></pre>"); |
@@ -161,11 +227,8 @@ fn html_escape(text: &str) -> String { | |||
161 | 227 | ||
162 | const STYLE: &str = " | 228 | const STYLE: &str = " |
163 | <style> | 229 | <style> |
164 | pre { | 230 | body { margin: 0; } |
165 | color: #DCDCCC; | 231 | pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } |
166 | background-color: #3F3F3F; | ||
167 | font-size: 22px; | ||
168 | } | ||
169 | 232 | ||
170 | .comment { color: #7F9F7F; } | 233 | .comment { color: #7F9F7F; } |
171 | .string { color: #CC9393; } | 234 | .string { color: #CC9393; } |
@@ -180,7 +243,6 @@ pre { | |||
180 | .keyword { color: #F0DFAF; } | 243 | .keyword { color: #F0DFAF; } |
181 | .keyword\\.unsafe { color: #F0DFAF; font-weight: bold; } | 244 | .keyword\\.unsafe { color: #F0DFAF; font-weight: bold; } |
182 | .keyword\\.control { color: #DC8CC3; } | 245 | .keyword\\.control { color: #DC8CC3; } |
183 | |||
184 | </style> | 246 | </style> |
185 | "; | 247 | "; |
186 | 248 | ||
@@ -213,12 +275,36 @@ fn main() { | |||
213 | } | 275 | } |
214 | unsafe { vec.set_len(0); } | 276 | unsafe { vec.set_len(0); } |
215 | } | 277 | } |
216 | "#, | 278 | "# |
279 | .trim(), | ||
217 | ); | 280 | ); |
218 | let dst_file = project_dir().join("crates/ra_ide_api/src/snapshots/highlighting.html"); | 281 | let dst_file = project_dir().join("crates/ra_ide_api/src/snapshots/highlighting.html"); |
219 | let actual_html = &analysis.highlight_as_html(file_id).unwrap(); | 282 | let actual_html = &analysis.highlight_as_html(file_id, true).unwrap(); |
283 | let expected_html = &read_text(&dst_file); | ||
284 | std::fs::write(dst_file, &actual_html).unwrap(); | ||
285 | assert_eq_text!(expected_html, actual_html); | ||
286 | } | ||
287 | |||
288 | #[test] | ||
289 | fn test_rainbow_highlighting() { | ||
290 | let (analysis, file_id) = single_file( | ||
291 | r#" | ||
292 | fn main() { | ||
293 | let hello = "hello"; | ||
294 | let x = hello.to_string(); | ||
295 | let y = hello.to_string(); | ||
296 | |||
297 | let x = "other color please!"; | ||
298 | let y = x.to_string(); | ||
299 | } | ||
300 | "# | ||
301 | .trim(), | ||
302 | ); | ||
303 | let dst_file = | ||
304 | project_dir().join("crates/ra_ide_api/src/snapshots/rainbow_highlighting.html"); | ||
305 | let actual_html = &analysis.highlight_as_html(file_id, true).unwrap(); | ||
220 | let expected_html = &read_text(&dst_file); | 306 | let expected_html = &read_text(&dst_file); |
221 | // std::fs::write(dst_file, &actual_html).unwrap(); | 307 | std::fs::write(dst_file, &actual_html).unwrap(); |
222 | assert_eq_text!(expected_html, actual_html); | 308 | assert_eq_text!(expected_html, actual_html); |
223 | } | 309 | } |
224 | } | 310 | } |