aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/syntax_highlighting.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-02-26 18:39:32 +0000
committerAleksey Kladov <[email protected]>2020-02-27 08:32:00 +0000
commitf7db49bfc6dd77471865c8591fdf7d5d00992830 (patch)
tree68600a30d47e3f4b632d9c42fb8b29297b3f4eef /crates/ra_ide/src/syntax_highlighting.rs
parent05388b4ea46c886fa4ec8a1d49b71eb816cf7c6d (diff)
Better highlightign API
Diffstat (limited to 'crates/ra_ide/src/syntax_highlighting.rs')
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs107
1 files changed, 60 insertions, 47 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index d422930bf..18980dc20 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3mod highlight_tag; 3mod highlight;
4 4
5use hir::{Name, Semantics}; 5use hir::{Name, Semantics};
6use ra_db::SourceDatabase; 6use ra_db::SourceDatabase;
@@ -17,12 +17,12 @@ use rustc_hash::FxHashMap;
17 17
18use crate::{references::classify_name_ref, FileId}; 18use crate::{references::classify_name_ref, FileId};
19 19
20pub use highlight_tag::HighlightTag; 20pub use highlight::{Highlight, HighlightModifier, HighlightModifiers, HighlightTag};
21 21
22#[derive(Debug)] 22#[derive(Debug)]
23pub struct HighlightedRange { 23pub struct HighlightedRange {
24 pub range: TextRange, 24 pub range: TextRange,
25 pub tag: HighlightTag, 25 pub highlight: Highlight,
26 pub binding_hash: Option<u64>, 26 pub binding_hash: Option<u64>,
27} 27}
28 28
@@ -79,33 +79,33 @@ pub(crate) fn highlight(
79 if let Some(range) = highlight_macro(node) { 79 if let Some(range) = highlight_macro(node) {
80 res.push(HighlightedRange { 80 res.push(HighlightedRange {
81 range, 81 range,
82 tag: HighlightTag::MACRO, 82 highlight: HighlightTag::Macro.into(),
83 binding_hash: None, 83 binding_hash: None,
84 }); 84 });
85 } 85 }
86 } 86 }
87 _ if in_macro_call.is_some() => { 87 _ if in_macro_call.is_some() => {
88 if let Some(token) = node.as_token() { 88 if let Some(token) = node.as_token() {
89 if let Some((tag, binding_hash)) = highlight_token_tree( 89 if let Some((highlight, binding_hash)) = highlight_token_tree(
90 &sema, 90 &sema,
91 &mut bindings_shadow_count, 91 &mut bindings_shadow_count,
92 token.clone(), 92 token.clone(),
93 ) { 93 ) {
94 res.push(HighlightedRange { 94 res.push(HighlightedRange {
95 range: node.text_range(), 95 range: node.text_range(),
96 tag, 96 highlight,
97 binding_hash, 97 binding_hash,
98 }); 98 });
99 } 99 }
100 } 100 }
101 } 101 }
102 _ => { 102 _ => {
103 if let Some((tag, binding_hash)) = 103 if let Some((highlight, binding_hash)) =
104 highlight_node(&sema, &mut bindings_shadow_count, node.clone()) 104 highlight_node(&sema, &mut bindings_shadow_count, node.clone())
105 { 105 {
106 res.push(HighlightedRange { 106 res.push(HighlightedRange {
107 range: node.text_range(), 107 range: node.text_range(),
108 tag, 108 highlight,
109 binding_hash, 109 binding_hash,
110 }); 110 });
111 } 111 }
@@ -150,7 +150,7 @@ fn highlight_token_tree(
150 sema: &Semantics<RootDatabase>, 150 sema: &Semantics<RootDatabase>,
151 bindings_shadow_count: &mut FxHashMap<Name, u32>, 151 bindings_shadow_count: &mut FxHashMap<Name, u32>,
152 token: SyntaxToken, 152 token: SyntaxToken,
153) -> Option<(HighlightTag, Option<u64>)> { 153) -> Option<(Highlight, Option<u64>)> {
154 if token.parent().kind() != TOKEN_TREE { 154 if token.parent().kind() != TOKEN_TREE {
155 return None; 155 return None;
156 } 156 }
@@ -171,19 +171,21 @@ fn highlight_node(
171 sema: &Semantics<RootDatabase>, 171 sema: &Semantics<RootDatabase>,
172 bindings_shadow_count: &mut FxHashMap<Name, u32>, 172 bindings_shadow_count: &mut FxHashMap<Name, u32>,
173 node: SyntaxElement, 173 node: SyntaxElement,
174) -> Option<(HighlightTag, Option<u64>)> { 174) -> Option<(Highlight, Option<u64>)> {
175 let db = sema.db; 175 let db = sema.db;
176 let mut binding_hash = None; 176 let mut binding_hash = None;
177 let tag = match node.kind() { 177 let highlight: Highlight = match node.kind() {
178 FN_DEF => { 178 FN_DEF => {
179 bindings_shadow_count.clear(); 179 bindings_shadow_count.clear();
180 return None; 180 return None;
181 } 181 }
182 COMMENT => HighlightTag::LITERAL_COMMENT, 182 COMMENT => HighlightTag::Comment.into(),
183 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => HighlightTag::LITERAL_STRING, 183 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => HighlightTag::LiteralString.into(),
184 ATTR => HighlightTag::LITERAL_ATTRIBUTE, 184 ATTR => HighlightTag::Attribute.into(),
185 // Special-case field init shorthand 185 // Special-case field init shorthand
186 NAME_REF if node.parent().and_then(ast::RecordField::cast).is_some() => HighlightTag::FIELD, 186 NAME_REF if node.parent().and_then(ast::RecordField::cast).is_some() => {
187 HighlightTag::Field.into()
188 }
187 NAME_REF if node.ancestors().any(|it| it.kind() == ATTR) => return None, 189 NAME_REF if node.ancestors().any(|it| it.kind() == ATTR) => return None,
188 NAME_REF => { 190 NAME_REF => {
189 let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); 191 let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap();
@@ -217,26 +219,30 @@ fn highlight_node(
217 219
218 match name_kind { 220 match name_kind {
219 Some(name_kind) => highlight_name(db, name_kind), 221 Some(name_kind) => highlight_name(db, name_kind),
220 None => name.syntax().parent().map_or(HighlightTag::FUNCTION, |x| match x.kind() { 222 None => name.syntax().parent().map_or(HighlightTag::Function.into(), |x| {
221 STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => HighlightTag::TYPE, 223 match x.kind() {
222 TYPE_PARAM => HighlightTag::TYPE_PARAM, 224 STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => {
223 RECORD_FIELD_DEF => HighlightTag::FIELD, 225 HighlightTag::Type.into()
224 _ => HighlightTag::FUNCTION, 226 }
227 TYPE_PARAM => HighlightTag::TypeParam.into(),
228 RECORD_FIELD_DEF => HighlightTag::Field.into(),
229 _ => HighlightTag::Function.into(),
230 }
225 }), 231 }),
226 } 232 }
227 } 233 }
228 INT_NUMBER | FLOAT_NUMBER => HighlightTag::LITERAL_NUMERIC, 234 INT_NUMBER | FLOAT_NUMBER => HighlightTag::LiteralNumeric.into(),
229 BYTE => HighlightTag::LITERAL_BYTE, 235 BYTE => HighlightTag::LiteralByte.into(),
230 CHAR => HighlightTag::LITERAL_CHAR, 236 CHAR => HighlightTag::LiteralChar.into(),
231 LIFETIME => HighlightTag::TYPE_LIFETIME, 237 LIFETIME => HighlightTag::TypeLifetime.into(),
232 T![unsafe] => HighlightTag::KEYWORD_UNSAFE, 238 T![unsafe] => HighlightTag::Keyword | HighlightModifier::Unsafe,
233 k if is_control_keyword(k) => HighlightTag::KEYWORD_CONTROL, 239 k if is_control_keyword(k) => HighlightTag::Keyword | HighlightModifier::Control,
234 k if k.is_keyword() => HighlightTag::KEYWORD, 240 k if k.is_keyword() => HighlightTag::Keyword.into(),
235 241
236 _ => return None, 242 _ => return None,
237 }; 243 };
238 244
239 return Some((tag, binding_hash)); 245 return Some((highlight, binding_hash));
240 246
241 fn calc_binding_hash(name: &Name, shadow_count: u32) -> u64 { 247 fn calc_binding_hash(name: &Name, shadow_count: u32) -> u64 {
242 fn hash<T: std::hash::Hash + std::fmt::Debug>(x: T) -> u64 { 248 fn hash<T: std::hash::Hash + std::fmt::Debug>(x: T) -> u64 {
@@ -293,7 +299,11 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo
293 if ranges.is_empty() { 299 if ranges.is_empty() {
294 buf.push_str(&text); 300 buf.push_str(&text);
295 } else { 301 } else {
296 let classes = ranges.iter().map(|x| x.tag.to_string()).collect::<Vec<_>>().join(" "); 302 let classes = ranges
303 .iter()
304 .map(|it| it.highlight.to_string().replace('.', " "))
305 .collect::<Vec<_>>()
306 .join(" ");
297 let binding_hash = ranges.first().and_then(|x| x.binding_hash); 307 let binding_hash = ranges.first().and_then(|x| x.binding_hash);
298 let color = match (rainbow, binding_hash) { 308 let color = match (rainbow, binding_hash) {
299 (true, Some(hash)) => format!( 309 (true, Some(hash)) => format!(
@@ -310,29 +320,32 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo
310 buf 320 buf
311} 321}
312 322
313fn highlight_name(db: &RootDatabase, def: NameDefinition) -> HighlightTag { 323fn highlight_name(db: &RootDatabase, def: NameDefinition) -> Highlight {
314 match def { 324 match def {
315 NameDefinition::Macro(_) => HighlightTag::MACRO, 325 NameDefinition::Macro(_) => HighlightTag::Macro,
316 NameDefinition::StructField(_) => HighlightTag::FIELD, 326 NameDefinition::StructField(_) => HighlightTag::Field,
317 NameDefinition::ModuleDef(hir::ModuleDef::Module(_)) => HighlightTag::MODULE, 327 NameDefinition::ModuleDef(hir::ModuleDef::Module(_)) => HighlightTag::Module,
318 NameDefinition::ModuleDef(hir::ModuleDef::Function(_)) => HighlightTag::FUNCTION, 328 NameDefinition::ModuleDef(hir::ModuleDef::Function(_)) => HighlightTag::Function,
319 NameDefinition::ModuleDef(hir::ModuleDef::Adt(_)) => HighlightTag::TYPE, 329 NameDefinition::ModuleDef(hir::ModuleDef::Adt(_)) => HighlightTag::Type,
320 NameDefinition::ModuleDef(hir::ModuleDef::EnumVariant(_)) => HighlightTag::CONSTANT, 330 NameDefinition::ModuleDef(hir::ModuleDef::EnumVariant(_)) => HighlightTag::Constant,
321 NameDefinition::ModuleDef(hir::ModuleDef::Const(_)) => HighlightTag::CONSTANT, 331 NameDefinition::ModuleDef(hir::ModuleDef::Const(_)) => HighlightTag::Constant,
322 NameDefinition::ModuleDef(hir::ModuleDef::Static(_)) => HighlightTag::CONSTANT, 332 NameDefinition::ModuleDef(hir::ModuleDef::Static(_)) => HighlightTag::Constant,
323 NameDefinition::ModuleDef(hir::ModuleDef::Trait(_)) => HighlightTag::TYPE, 333 NameDefinition::ModuleDef(hir::ModuleDef::Trait(_)) => HighlightTag::Type,
324 NameDefinition::ModuleDef(hir::ModuleDef::TypeAlias(_)) => HighlightTag::TYPE, 334 NameDefinition::ModuleDef(hir::ModuleDef::TypeAlias(_)) => HighlightTag::Type,
325 NameDefinition::ModuleDef(hir::ModuleDef::BuiltinType(_)) => HighlightTag::TYPE_BUILTIN, 335 NameDefinition::ModuleDef(hir::ModuleDef::BuiltinType(_)) => {
326 NameDefinition::SelfType(_) => HighlightTag::TYPE_SELF, 336 return HighlightTag::Type | HighlightModifier::Builtin
327 NameDefinition::TypeParam(_) => HighlightTag::TYPE_PARAM, 337 }
338 NameDefinition::SelfType(_) => HighlightTag::TypeSelf,
339 NameDefinition::TypeParam(_) => HighlightTag::TypeParam,
328 NameDefinition::Local(local) => { 340 NameDefinition::Local(local) => {
341 let mut h = Highlight::new(HighlightTag::Variable);
329 if local.is_mut(db) || local.ty(db).is_mutable_reference() { 342 if local.is_mut(db) || local.ty(db).is_mutable_reference() {
330 HighlightTag::VARIABLE_MUT 343 h |= HighlightModifier::Mutable;
331 } else {
332 HighlightTag::VARIABLE
333 } 344 }
345 return h;
334 } 346 }
335 } 347 }
348 .into()
336} 349}
337 350
338//FIXME: like, real html escaping 351//FIXME: like, real html escaping
@@ -498,6 +511,6 @@ fn bar() {
498 }) 511 })
499 .unwrap(); 512 .unwrap();
500 513
501 assert_eq!(&highlights[0].tag.to_string(), "field"); 514 assert_eq!(&highlights[0].highlight.to_string(), "field");
502 } 515 }
503} 516}