aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs145
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
15use crate::{ 15use 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
240fn 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
276fn html_escape(text: &str) -> String { 277fn html_escape(text: &str) -> String {
277 text.replace("<", "&lt;").replace(">", "&gt;") 278 text.replace("<", "&lt;").replace(">", "&gt;")