diff options
Diffstat (limited to 'crates/ra_ide_api/src/syntax_highlighting.rs')
-rw-r--r-- | crates/ra_ide_api/src/syntax_highlighting.rs | 82 |
1 files changed, 61 insertions, 21 deletions
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index d70ceb7d1..d84ae2cb2 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs | |||
@@ -1,9 +1,11 @@ | |||
1 | use rustc_hash::{FxHashMap, FxHashSet}; | 1 | use rustc_hash::{FxHashMap, FxHashSet}; |
2 | 2 | ||
3 | use hir::{Mutability, Ty}; | ||
3 | use ra_db::SourceDatabase; | 4 | use ra_db::SourceDatabase; |
4 | use ra_prof::profile; | 5 | use ra_prof::profile; |
5 | use ra_syntax::{ | 6 | use ra_syntax::{ |
6 | ast, AstNode, Direction, SmolStr, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T, | 7 | ast, AstNode, Direction, Pat, PatKind, SmolStr, SyntaxElement, SyntaxKind, SyntaxKind::*, |
8 | TextRange, T, | ||
7 | }; | 9 | }; |
8 | 10 | ||
9 | use crate::{db::RootDatabase, FileId}; | 11 | use crate::{db::RootDatabase, FileId}; |
@@ -30,6 +32,27 @@ fn is_control_keyword(kind: SyntaxKind) -> bool { | |||
30 | } | 32 | } |
31 | } | 33 | } |
32 | 34 | ||
35 | fn is_variable_mutable(db: &RootDatabase, analyzer: &hir::SourceAnalyzer, pat: &Pat) -> bool { | ||
36 | let ty = analyzer.type_of_pat(db, pat).unwrap_or(Ty::Unknown); | ||
37 | let is_ty_mut = { | ||
38 | if let Some((_, mutability)) = ty.as_reference() { | ||
39 | match mutability { | ||
40 | Mutability::Shared => false, | ||
41 | Mutability::Mut => true, | ||
42 | } | ||
43 | } else { | ||
44 | false | ||
45 | } | ||
46 | }; | ||
47 | |||
48 | let is_pat_mut = match pat.kind() { | ||
49 | PatKind::BindPat(bind_pat) => bind_pat.is_mutable(), | ||
50 | _ => false, | ||
51 | }; | ||
52 | |||
53 | is_ty_mut || is_pat_mut | ||
54 | } | ||
55 | |||
33 | pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { | 56 | pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { |
34 | let _p = profile("highlight"); | 57 | let _p = profile("highlight"); |
35 | let parse = db.parse(file_id); | 58 | let parse = db.parse(file_id); |
@@ -97,7 +120,11 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
97 | calc_binding_hash(file_id, &text, *shadow_count) | 120 | calc_binding_hash(file_id, &text, *shadow_count) |
98 | }); | 121 | }); |
99 | 122 | ||
100 | "variable" | 123 | if is_variable_mutable(db, &analyzer, ptr.to_node(root)) { |
124 | "variable.mut" | ||
125 | } else { | ||
126 | "variable" | ||
127 | } | ||
101 | } | 128 | } |
102 | Some(SelfParam(_)) => "type", | 129 | Some(SelfParam(_)) => "type", |
103 | Some(GenericParam(_)) => "type", | 130 | Some(GenericParam(_)) => "type", |
@@ -109,7 +136,8 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
109 | } | 136 | } |
110 | NAME => { | 137 | NAME => { |
111 | if let Some(name) = node.as_node().and_then(ast::Name::cast) { | 138 | if let Some(name) = node.as_node().and_then(ast::Name::cast) { |
112 | if name.syntax().ancestors().any(|x| ast::BindPat::cast(x).is_some()) { | 139 | let analyzer = hir::SourceAnalyzer::new(db, file_id, name.syntax(), None); |
140 | if let Some(pat) = name.syntax().ancestors().find_map(Pat::cast) { | ||
113 | binding_hash = Some({ | 141 | binding_hash = Some({ |
114 | let text = name.syntax().text().to_smol_string(); | 142 | let text = name.syntax().text().to_smol_string(); |
115 | let shadow_count = | 143 | let shadow_count = |
@@ -117,7 +145,12 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
117 | *shadow_count += 1; | 145 | *shadow_count += 1; |
118 | calc_binding_hash(file_id, &text, *shadow_count) | 146 | calc_binding_hash(file_id, &text, *shadow_count) |
119 | }); | 147 | }); |
120 | "variable" | 148 | |
149 | if is_variable_mutable(db, &analyzer, pat) { | ||
150 | "variable.mut" | ||
151 | } else { | ||
152 | "variable" | ||
153 | } | ||
121 | } else if name | 154 | } else if name |
122 | .syntax() | 155 | .syntax() |
123 | .parent() | 156 | .parent() |
@@ -241,22 +274,23 @@ fn html_escape(text: &str) -> String { | |||
241 | 274 | ||
242 | const STYLE: &str = " | 275 | const STYLE: &str = " |
243 | <style> | 276 | <style> |
244 | body { margin: 0; } | 277 | body { margin: 0; } |
245 | pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } | 278 | pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } |
246 | 279 | ||
247 | .comment { color: #7F9F7F; } | 280 | .comment { color: #7F9F7F; } |
248 | .string { color: #CC9393; } | 281 | .string { color: #CC9393; } |
249 | .function { color: #93E0E3; } | 282 | .function { color: #93E0E3; } |
250 | .parameter { color: #94BFF3; } | 283 | .parameter { color: #94BFF3; } |
251 | .builtin { color: #DD6718; } | 284 | .builtin { color: #DD6718; } |
252 | .text { color: #DCDCCC; } | 285 | .text { color: #DCDCCC; } |
253 | .attribute { color: #BFEBBF; } | 286 | .attribute { color: #BFEBBF; } |
254 | .literal { color: #DFAF8F; } | 287 | .literal { color: #DFAF8F; } |
255 | .macro { color: #DFAF8F; } | 288 | .macro { color: #DFAF8F; } |
256 | 289 | .variable\\.mut { color: #DFAF8F; } | |
257 | .keyword { color: #F0DFAF; } | 290 | |
258 | .keyword\\.unsafe { color: #F0DFAF; font-weight: bold; } | 291 | .keyword { color: #F0DFAF; } |
259 | .keyword\\.control { color: #DC8CC3; } | 292 | .keyword\\.unsafe { color: #F0DFAF; font-weight: bold; } |
293 | .keyword\\.control { color: #DC8CC3; } | ||
260 | </style> | 294 | </style> |
261 | "; | 295 | "; |
262 | 296 | ||
@@ -289,12 +323,18 @@ fn main() { | |||
289 | vec.push(Foo { x: 0, y: 1 }); | 323 | vec.push(Foo { x: 0, y: 1 }); |
290 | } | 324 | } |
291 | unsafe { vec.set_len(0); } | 325 | unsafe { vec.set_len(0); } |
326 | |||
327 | let mut x = 42; | ||
328 | let y = &mut x; | ||
329 | let z = &y; | ||
330 | |||
331 | y; | ||
292 | } | 332 | } |
293 | "# | 333 | "# |
294 | .trim(), | 334 | .trim(), |
295 | ); | 335 | ); |
296 | let dst_file = project_dir().join("crates/ra_ide_api/src/snapshots/highlighting.html"); | 336 | let dst_file = project_dir().join("crates/ra_ide_api/src/snapshots/highlighting.html"); |
297 | let actual_html = &analysis.highlight_as_html(file_id, true).unwrap(); | 337 | let actual_html = &analysis.highlight_as_html(file_id, false).unwrap(); |
298 | let expected_html = &read_text(&dst_file); | 338 | let expected_html = &read_text(&dst_file); |
299 | std::fs::write(dst_file, &actual_html).unwrap(); | 339 | std::fs::write(dst_file, &actual_html).unwrap(); |
300 | assert_eq_text!(expected_html, actual_html); | 340 | assert_eq_text!(expected_html, actual_html); |