From ca61356b01c8f0919443b3ccd5e543e06694466a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 18 Apr 2020 20:59:22 +0200 Subject: [PATCH] Add semantic tag for unresolved references This is a quick way to implement unresolved reference diagnostics. For example, adding to VS Code config "editor.tokenColorCustomizationsExperimental": { "unresolvedReference": "#FF0000" }, will highlight all unresolved refs in red. --- crates/ra_ide/src/snapshots/highlighting.html | 6 ++-- .../src/snapshots/rainbow_highlighting.html | 6 ++-- crates/ra_ide/src/syntax_highlighting.rs | 29 ++++++++++--------- crates/ra_ide/src/syntax_highlighting/tags.rs | 2 ++ crates/rust-analyzer/src/conv.rs | 5 +++- crates/rust-analyzer/src/semantic_tokens.rs | 3 ++ editors/code/package.json | 4 +++ 7 files changed, 34 insertions(+), 21 deletions(-) diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 214dcbb620..ccb1fc7516 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html @@ -50,12 +50,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd fn main() { println!("Hello, {}!", 92); - let mut vec = Vec::new(); + let mut vec = Vec::new(); if true { let x = 92; - vec.push(Foo { x, y: 1 }); + vec.push(Foo { x, y: 1 }); } - unsafe { vec.set_len(0); } + unsafe { vec.set_len(0); } let mut x = 42; let y = &mut x; diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index dddbfc0dd6..3df82c45fb 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html @@ -28,11 +28,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
fn main() {
     let hello = "hello";
-    let x = hello.to_string();
-    let y = hello.to_string();
+    let x = hello.to_string();
+    let y = hello.to_string();
 
     let x = "other color please!";
-    let y = x.to_string();
+    let y = x.to_string();
 }
 
 fn bar() {
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 7b15b82bdb..93d5028756 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -239,20 +239,21 @@ fn highlight_element(
         NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => return None,
         NAME_REF => {
             let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
-            let name_kind = classify_name_ref(sema, &name_ref)?;
-
-            match name_kind {
-                NameRefClass::Definition(def) => {
-                    if let Definition::Local(local) = &def {
-                        if let Some(name) = local.name(db) {
-                            let shadow_count =
-                                bindings_shadow_count.entry(name.clone()).or_default();
-                            binding_hash = Some(calc_binding_hash(&name, *shadow_count))
-                        }
-                    };
-                    highlight_name(db, def)
-                }
-                NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(),
+            match classify_name_ref(sema, &name_ref) {
+                Some(name_kind) => match name_kind {
+                    NameRefClass::Definition(def) => {
+                        if let Definition::Local(local) = &def {
+                            if let Some(name) = local.name(db) {
+                                let shadow_count =
+                                    bindings_shadow_count.entry(name.clone()).or_default();
+                                binding_hash = Some(calc_binding_hash(&name, *shadow_count))
+                            }
+                        };
+                        highlight_name(db, def)
+                    }
+                    NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(),
+                },
+                None => HighlightTag::UnresolvedReference.into(),
             }
         }
 
diff --git a/crates/ra_ide/src/syntax_highlighting/tags.rs b/crates/ra_ide/src/syntax_highlighting/tags.rs
index e8b138e1a7..f2c4216545 100644
--- a/crates/ra_ide/src/syntax_highlighting/tags.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tags.rs
@@ -38,6 +38,7 @@ pub enum HighlightTag {
     TypeParam,
     Union,
     Local,
+    UnresolvedReference,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -79,6 +80,7 @@ impl HighlightTag {
             HighlightTag::TypeParam => "type_param",
             HighlightTag::Union => "union",
             HighlightTag::Local => "variable",
+            HighlightTag::UnresolvedReference => "unresolved_reference",
         }
     }
 }
diff --git a/crates/rust-analyzer/src/conv.rs b/crates/rust-analyzer/src/conv.rs
index b2b1cb6258..8d2360cc8d 100644
--- a/crates/rust-analyzer/src/conv.rs
+++ b/crates/rust-analyzer/src/conv.rs
@@ -24,7 +24,9 @@ use crate::{
     world::WorldSnapshot,
     Result,
 };
-use semantic_tokens::{ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, LIFETIME, TYPE_ALIAS, UNION};
+use semantic_tokens::{
+    ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, LIFETIME, TYPE_ALIAS, UNION, UNRESOLVED_REFERENCE,
+};
 
 pub trait Conv {
     type Output;
@@ -373,6 +375,7 @@ impl Conv for Highlight {
             HighlightTag::Comment => SemanticTokenType::COMMENT,
             HighlightTag::Attribute => ATTRIBUTE,
             HighlightTag::Keyword => SemanticTokenType::KEYWORD,
+            HighlightTag::UnresolvedReference => UNRESOLVED_REFERENCE,
         };
 
         for modifier in self.modifiers.iter() {
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index 865fa3b1c5..10fe696f6f 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -10,6 +10,8 @@ pub(crate) const ENUM_MEMBER: SemanticTokenType = SemanticTokenType::new("enumMe
 pub(crate) const LIFETIME: SemanticTokenType = SemanticTokenType::new("lifetime");
 pub(crate) const TYPE_ALIAS: SemanticTokenType = SemanticTokenType::new("typeAlias");
 pub(crate) const UNION: SemanticTokenType = SemanticTokenType::new("union");
+pub(crate) const UNRESOLVED_REFERENCE: SemanticTokenType =
+    SemanticTokenType::new("unresolvedReference");
 
 pub(crate) const CONSTANT: SemanticTokenModifier = SemanticTokenModifier::new("constant");
 pub(crate) const CONTROL_FLOW: SemanticTokenModifier = SemanticTokenModifier::new("controlFlow");
@@ -43,6 +45,7 @@ pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[
     LIFETIME,
     TYPE_ALIAS,
     UNION,
+    UNRESOLVED_REFERENCE,
 ];
 
 pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
diff --git a/editors/code/package.json b/editors/code/package.json
index 5ce59e54a9..79410ad109 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -517,6 +517,10 @@
                 "id": "union",
                 "description": "Style for C-style untagged unions",
                 "superType": "type"
+            },
+            {
+                "id": "unresolvedReference",
+                "description": "Style for names which can not be resolved due to compilation errors"
             }
         ],
         "semanticTokenModifiers": [