diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-06-16 12:40:51 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-06-16 12:40:51 +0100 |
commit | 4342b717158eeb9aff20d1958229ffcbca17f1c7 (patch) | |
tree | ddcbbfe6fcaaac83449fe612c971044e19680365 /crates/ra_ide/src/syntax_highlighting.rs | |
parent | 83a16e825da2767aaee1d62447eb94f4d7de8881 (diff) | |
parent | c4b3db0c2f307d1d782af88ded260e4c6593cae0 (diff) |
Merge #4876
4876: Syntactic highlighting of NAME_REF for injections r=matklad a=ltentrup
This commit adds a function that tries to determine the syntax highlighting class of NAME_REFs based on the usage.
It is used for highlighting injections (such as highlighting of doctests) as the semantic logic will most of the time result in unresolved references.
It also adds a color to unresolved references in HTML encoding.
Follow up of #4683.
Fixes #4809.
Co-authored-by: Leander Tentrup <[email protected]>
Diffstat (limited to 'crates/ra_ide/src/syntax_highlighting.rs')
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index bbcd52a1c..5a4de450c 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -44,6 +44,7 @@ pub(crate) fn highlight( | |||
44 | db: &RootDatabase, | 44 | db: &RootDatabase, |
45 | file_id: FileId, | 45 | file_id: FileId, |
46 | range_to_highlight: Option<TextRange>, | 46 | range_to_highlight: Option<TextRange>, |
47 | syntactic_name_ref_highlighting: bool, | ||
47 | ) -> Vec<HighlightedRange> { | 48 | ) -> Vec<HighlightedRange> { |
48 | let _p = profile("highlight"); | 49 | let _p = profile("highlight"); |
49 | let sema = Semantics::new(db); | 50 | let sema = Semantics::new(db); |
@@ -104,6 +105,7 @@ pub(crate) fn highlight( | |||
104 | if let Some((highlight, binding_hash)) = highlight_element( | 105 | if let Some((highlight, binding_hash)) = highlight_element( |
105 | &sema, | 106 | &sema, |
106 | &mut bindings_shadow_count, | 107 | &mut bindings_shadow_count, |
108 | syntactic_name_ref_highlighting, | ||
107 | name.syntax().clone().into(), | 109 | name.syntax().clone().into(), |
108 | ) { | 110 | ) { |
109 | stack.add(HighlightedRange { | 111 | stack.add(HighlightedRange { |
@@ -200,9 +202,12 @@ pub(crate) fn highlight( | |||
200 | 202 | ||
201 | let is_format_string = format_string.as_ref() == Some(&element_to_highlight); | 203 | let is_format_string = format_string.as_ref() == Some(&element_to_highlight); |
202 | 204 | ||
203 | if let Some((highlight, binding_hash)) = | 205 | if let Some((highlight, binding_hash)) = highlight_element( |
204 | highlight_element(&sema, &mut bindings_shadow_count, element_to_highlight.clone()) | 206 | &sema, |
205 | { | 207 | &mut bindings_shadow_count, |
208 | syntactic_name_ref_highlighting, | ||
209 | element_to_highlight.clone(), | ||
210 | ) { | ||
206 | stack.add(HighlightedRange { range, highlight, binding_hash }); | 211 | stack.add(HighlightedRange { range, highlight, binding_hash }); |
207 | if let Some(string) = | 212 | if let Some(string) = |
208 | element_to_highlight.as_token().cloned().and_then(ast::String::cast) | 213 | element_to_highlight.as_token().cloned().and_then(ast::String::cast) |
@@ -410,6 +415,7 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> { | |||
410 | fn highlight_element( | 415 | fn highlight_element( |
411 | sema: &Semantics<RootDatabase>, | 416 | sema: &Semantics<RootDatabase>, |
412 | bindings_shadow_count: &mut FxHashMap<Name, u32>, | 417 | bindings_shadow_count: &mut FxHashMap<Name, u32>, |
418 | syntactic_name_ref_highlighting: bool, | ||
413 | element: SyntaxElement, | 419 | element: SyntaxElement, |
414 | ) -> Option<(Highlight, Option<u64>)> { | 420 | ) -> Option<(Highlight, Option<u64>)> { |
415 | let db = sema.db; | 421 | let db = sema.db; |
@@ -463,6 +469,7 @@ fn highlight_element( | |||
463 | } | 469 | } |
464 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), | 470 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), |
465 | }, | 471 | }, |
472 | None if syntactic_name_ref_highlighting => highlight_name_ref_by_syntax(name_ref), | ||
466 | None => HighlightTag::UnresolvedReference.into(), | 473 | None => HighlightTag::UnresolvedReference.into(), |
467 | } | 474 | } |
468 | } | 475 | } |
@@ -614,3 +621,53 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | |||
614 | 621 | ||
615 | tag.into() | 622 | tag.into() |
616 | } | 623 | } |
624 | |||
625 | fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | ||
626 | let default = HighlightTag::UnresolvedReference; | ||
627 | |||
628 | let parent = match name.syntax().parent() { | ||
629 | Some(it) => it, | ||
630 | _ => return default.into(), | ||
631 | }; | ||
632 | |||
633 | let tag = match parent.kind() { | ||
634 | METHOD_CALL_EXPR => HighlightTag::Function, | ||
635 | FIELD_EXPR => HighlightTag::Field, | ||
636 | PATH_SEGMENT => { | ||
637 | let path = match parent.parent().and_then(ast::Path::cast) { | ||
638 | Some(it) => it, | ||
639 | _ => return default.into(), | ||
640 | }; | ||
641 | let expr = match path.syntax().parent().and_then(ast::PathExpr::cast) { | ||
642 | Some(it) => it, | ||
643 | _ => { | ||
644 | // within path, decide whether it is module or adt by checking for uppercase name | ||
645 | return if name.text().chars().next().unwrap_or_default().is_uppercase() { | ||
646 | HighlightTag::Struct | ||
647 | } else { | ||
648 | HighlightTag::Module | ||
649 | } | ||
650 | .into(); | ||
651 | } | ||
652 | }; | ||
653 | let parent = match expr.syntax().parent() { | ||
654 | Some(it) => it, | ||
655 | None => return default.into(), | ||
656 | }; | ||
657 | |||
658 | match parent.kind() { | ||
659 | CALL_EXPR => HighlightTag::Function, | ||
660 | _ => { | ||
661 | if name.text().chars().next().unwrap_or_default().is_uppercase() { | ||
662 | HighlightTag::Struct | ||
663 | } else { | ||
664 | HighlightTag::Constant | ||
665 | } | ||
666 | } | ||
667 | } | ||
668 | } | ||
669 | _ => default, | ||
670 | }; | ||
671 | |||
672 | tag.into() | ||
673 | } | ||