diff options
-rw-r--r-- | crates/ra_ide_api/src/syntax_highlighting.rs | 145 |
1 files changed, 73 insertions, 72 deletions
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 33f3caceb..1ee68abe2 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs | |||
@@ -9,12 +9,15 @@ use ra_syntax::{ | |||
9 | ast::{self, NameOwner}, | 9 | ast::{self, NameOwner}, |
10 | AstNode, Direction, SmolStr, SyntaxElement, SyntaxKind, | 10 | AstNode, Direction, SmolStr, SyntaxElement, SyntaxKind, |
11 | SyntaxKind::*, | 11 | SyntaxKind::*, |
12 | TextRange, T, | 12 | SyntaxNode, TextRange, T, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | db::RootDatabase, | 16 | db::RootDatabase, |
17 | references::{classify_name_ref, NameKind::*}, | 17 | references::{ |
18 | classify_name, classify_name_ref, | ||
19 | NameKind::{self, *}, | ||
20 | }, | ||
18 | FileId, | 21 | FileId, |
19 | }; | 22 | }; |
20 | 23 | ||
@@ -100,81 +103,43 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
100 | if node.ancestors().any(|it| it.kind() == ATTR) { | 103 | if node.ancestors().any(|it| it.kind() == ATTR) { |
101 | continue; | 104 | continue; |
102 | } | 105 | } |
103 | if let Some(name_ref) = node.as_node().cloned().and_then(ast::NameRef::cast) { | ||
104 | let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind); | ||
105 | match name_kind { | ||
106 | Some(Macro(_)) => "macro", | ||
107 | Some(Field(_)) => "field", | ||
108 | Some(AssocItem(hir::AssocItem::Function(_))) => "function", | ||
109 | Some(AssocItem(hir::AssocItem::Const(_))) => "constant", | ||
110 | Some(AssocItem(hir::AssocItem::TypeAlias(_))) => "type", | ||
111 | Some(Def(hir::ModuleDef::Module(_))) => "module", | ||
112 | Some(Def(hir::ModuleDef::Function(_))) => "function", | ||
113 | Some(Def(hir::ModuleDef::Adt(_))) => "type", | ||
114 | Some(Def(hir::ModuleDef::EnumVariant(_))) => "constant", | ||
115 | Some(Def(hir::ModuleDef::Const(_))) => "constant", | ||
116 | Some(Def(hir::ModuleDef::Static(_))) => "constant", | ||
117 | Some(Def(hir::ModuleDef::Trait(_))) => "type", | ||
118 | Some(Def(hir::ModuleDef::TypeAlias(_))) => "type", | ||
119 | Some(Def(hir::ModuleDef::BuiltinType(_))) => "type", | ||
120 | Some(SelfType(_)) => "type", | ||
121 | Some(Pat((_, ptr))) => { | ||
122 | let pat = ptr.to_node(&root); | ||
123 | if let Some(name) = pat.name() { | ||
124 | let text = name.text(); | ||
125 | let shadow_count = | ||
126 | bindings_shadow_count.entry(text.clone()).or_default(); | ||
127 | binding_hash = | ||
128 | Some(calc_binding_hash(file_id, &text, *shadow_count)) | ||
129 | } | ||
130 | 106 | ||
131 | let analyzer = | 107 | let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); |
132 | hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); | 108 | let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind); |
133 | if is_variable_mutable(db, &analyzer, ptr.to_node(&root)) { | 109 | |
134 | "variable.mut" | 110 | if let Some(Pat((_, ptr))) = &name_kind { |
135 | } else { | 111 | let pat = ptr.to_node(&root); |
136 | "variable" | 112 | if let Some(name) = pat.name() { |
137 | } | 113 | let text = name.text(); |
138 | } | 114 | let shadow_count = bindings_shadow_count.entry(text.clone()).or_default(); |
139 | Some(SelfParam(_)) => "type", | 115 | binding_hash = Some(calc_binding_hash(file_id, &text, *shadow_count)) |
140 | Some(GenericParam(_)) => "type", | ||
141 | None => "text", | ||
142 | } | 116 | } |
143 | } else { | 117 | }; |
144 | "text" | 118 | |
145 | } | 119 | name_kind |
120 | .map_or("text", |it| highlight_name(db, file_id, name_ref.syntax(), &root, it)) | ||
146 | } | 121 | } |
147 | NAME => { | 122 | NAME => { |
148 | if let Some(name) = node.as_node().cloned().and_then(ast::Name::cast) { | 123 | let name = node.as_node().cloned().and_then(ast::Name::cast).unwrap(); |
149 | let analyzer = hir::SourceAnalyzer::new(db, file_id, name.syntax(), None); | 124 | let name_kind = classify_name(db, file_id, &name).map(|d| d.kind); |
150 | if let Some(pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { | 125 | |
151 | if let Some(name) = pat.name() { | 126 | if let Some(Pat((_, ptr))) = &name_kind { |
152 | let text = name.text(); | 127 | let pat = ptr.to_node(&root); |
153 | let shadow_count = | 128 | if let Some(name) = pat.name() { |
154 | bindings_shadow_count.entry(text.clone()).or_default(); | 129 | let text = name.text(); |
155 | *shadow_count += 1; | 130 | let shadow_count = bindings_shadow_count.entry(text.clone()).or_default(); |
156 | binding_hash = Some(calc_binding_hash(file_id, &text, *shadow_count)) | 131 | *shadow_count += 1; |
157 | } | 132 | binding_hash = Some(calc_binding_hash(file_id, &text, *shadow_count)) |
158 | |||
159 | if is_variable_mutable(db, &analyzer, pat) { | ||
160 | "variable.mut" | ||
161 | } else { | ||
162 | "variable" | ||
163 | } | ||
164 | } else { | ||
165 | name.syntax() | ||
166 | .parent() | ||
167 | .map(|x| match x.kind() { | ||
168 | TYPE_PARAM | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => { | ||
169 | "type" | ||
170 | } | ||
171 | RECORD_FIELD_DEF => "field", | ||
172 | _ => "function", | ||
173 | }) | ||
174 | .unwrap_or("function") | ||
175 | } | 133 | } |
176 | } else { | 134 | }; |
177 | "text" | 135 | |
136 | match name_kind { | ||
137 | Some(name_kind) => highlight_name(db, file_id, name.syntax(), &root, name_kind), | ||
138 | None => name.syntax().parent().map_or("function", |x| match x.kind() { | ||
139 | TYPE_PARAM | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => "type", | ||
140 | RECORD_FIELD_DEF => "field", | ||
141 | _ => "function", | ||
142 | }), | ||
178 | } | 143 | } |
179 | } | 144 | } |
180 | INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal", | 145 | INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal", |
@@ -272,6 +237,42 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo | |||
272 | buf | 237 | buf |
273 | } | 238 | } |
274 | 239 | ||
240 | fn highlight_name( | ||
241 | db: &RootDatabase, | ||
242 | file_id: FileId, | ||
243 | node: &SyntaxNode, | ||
244 | root: &SyntaxNode, | ||
245 | name_kind: NameKind, | ||
246 | ) -> &'static str { | ||
247 | match name_kind { | ||
248 | Macro(_) => "macro", | ||
249 | Field(_) => "field", | ||
250 | AssocItem(hir::AssocItem::Function(_)) => "function", | ||
251 | AssocItem(hir::AssocItem::Const(_)) => "constant", | ||
252 | AssocItem(hir::AssocItem::TypeAlias(_)) => "type", | ||
253 | Def(hir::ModuleDef::Module(_)) => "module", | ||
254 | Def(hir::ModuleDef::Function(_)) => "function", | ||
255 | Def(hir::ModuleDef::Adt(_)) => "type", | ||
256 | Def(hir::ModuleDef::EnumVariant(_)) => "constant", | ||
257 | Def(hir::ModuleDef::Const(_)) => "constant", | ||
258 | Def(hir::ModuleDef::Static(_)) => "constant", | ||
259 | Def(hir::ModuleDef::Trait(_)) => "type", | ||
260 | Def(hir::ModuleDef::TypeAlias(_)) => "type", | ||
261 | Def(hir::ModuleDef::BuiltinType(_)) => "type", | ||
262 | SelfType(_) => "type", | ||
263 | SelfParam(_) => "type", | ||
264 | GenericParam(_) => "type", | ||
265 | Pat((_, ptr)) => { | ||
266 | let analyzer = hir::SourceAnalyzer::new(db, file_id, node, None); | ||
267 | if is_variable_mutable(db, &analyzer, ptr.to_node(&root)) { | ||
268 | "variable.mut" | ||
269 | } else { | ||
270 | "variable" | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | |||
275 | //FIXME: like, real html escaping | 276 | //FIXME: like, real html escaping |
276 | fn html_escape(text: &str) -> String { | 277 | fn html_escape(text: &str) -> String { |
277 | text.replace("<", "<").replace(">", ">") | 278 | text.replace("<", "<").replace(">", ">") |