Repository: rust-analyzer/rust-analyzer (rust)

Issue:
Highlighting of Parameters
Was going through highlighting grammars and noticed that semantic highlighting has `parameter` as a "standard" kind, and that RA doesn't support it in either textmate nor semantic (which was a slight bummer, I wanted to highlight my parameters slightly differently than locally declared variables)

Pull request:
Use dedicated semantic highlight tag for parameters
closes #5106



bors r+
🤖

Patch:
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 1b3525011d..04fd335fe8 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -33,7 +33,10 @@ use hir_ty::{
 };
 use ra_db::{CrateId, Edition, FileId};
 use ra_prof::profile;
-use ra_syntax::ast::{self, AttrsOwner, NameOwner};
+use ra_syntax::{
+    ast::{self, AttrsOwner, NameOwner},
+    AstNode,
+};
 use rustc_hash::FxHashSet;
 
 use crate::{
@@ -955,6 +958,16 @@ pub struct Local {
 }
 
 impl Local {
+    pub fn is_param(self, db: &dyn HirDatabase) -> bool {
+        let src = self.source(db);
+        match src.value {
+            Either::Left(bind_pat) => {
+                bind_pat.syntax().ancestors().any(|it| ast::Param::can_cast(it.kind()))
+            }
+            Either::Right(_self_param) => true,
+        }
+    }
+
     // FIXME: why is this an option? It shouldn't be?
     pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
         let body = db.body(self.parent.into());
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 028b559022..5bb6f96422 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -630,9 +630,10 @@ fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight {
         },
         Definition::SelfType(_) => HighlightTag::SelfType,
         Definition::TypeParam(_) => HighlightTag::TypeParam,
-        // FIXME: distinguish between locals and parameters
         Definition::Local(local) => {
-            let mut h = Highlight::new(HighlightTag::Local);
+            let tag =
+                if local.is_param(db) { HighlightTag::ValueParam } else { HighlightTag::Local };
+            let mut h = Highlight::new(tag);
             if local.is_mut(db) || local.ty(db).is_mutable_reference() {
                 h |= HighlightModifier::Mutable;
             }
diff --git a/crates/ra_ide/src/syntax_highlighting/html.rs b/crates/ra_ide/src/syntax_highlighting/html.rs
index 0c74f73701..0be55bca98 100644
--- a/crates/ra_ide/src/syntax_highlighting/html.rs
+++ b/crates/ra_ide/src/syntax_highlighting/html.rs
@@ -83,14 +83,15 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .bool_literal       { color: #BFE6EB; }
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
 .variable           { color: #DCDCCC; }
 .format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
-.unresolved_reference { color: #FC5555; }
 .escape_sequence    { color: #94BFF3; }
-
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .keyword.unsafe     { color: #BC8383; font-weight: bold; }
 .control            { font-style: italic; }
+
+.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
 ";
diff --git a/crates/ra_ide/src/syntax_highlighting/tags.rs b/crates/ra_ide/src/syntax_highlighting/tags.rs
index 13d9dd195a..719c6ed3cb 100644
--- a/crates/ra_ide/src/syntax_highlighting/tags.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tags.rs
@@ -41,6 +41,7 @@ pub enum HighlightTag {
     TypeAlias,
     TypeParam,
     Union,
+    ValueParam,
     Local,
     UnresolvedReference,
     FormatSpecifier,
@@ -95,6 +96,7 @@ impl HighlightTag {
             HighlightTag::TypeAlias => "type_alias",
             HighlightTag::TypeParam => "type_param",
             HighlightTag::Union => "union",
+            HighlightTag::ValueParam => "value_param",
             HighlightTag::Local => "variable",
             HighlightTag::UnresolvedReference => "unresolved_reference",
         }
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index f6dff16844..f6d2f4fc4a 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -309,6 +309,7 @@ fn semantic_token_type_and_modifiers(
         }
         HighlightTag::EnumVariant => semantic_tokens::ENUM_MEMBER,
         HighlightTag::Macro => lsp_types::SemanticTokenType::MACRO,
+        HighlightTag::ValueParam => lsp_types::SemanticTokenType::PARAMETER,
         HighlightTag::Local => lsp_types::SemanticTokenType::VARIABLE,
         HighlightTag::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER,
         HighlightTag::Lifetime => semantic_tokens::LIFETIME,


Test patch:
diff --git a/crates/ra_ide/test_data/highlight_doctest.html b/crates/ra_ide/test_data/highlight_doctest.html
index e8155def75..a77fabb68d 100644
--- a/crates/ra_ide/test_data/highlight_doctest.html
+++ b/crates/ra_ide/test_data/highlight_doctest.html
@@ -24,15 +24,16 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .bool_literal       { color: #BFE6EB; }
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
 .variable           { color: #DCDCCC; }
 .format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
-.unresolved_reference { color: #FC5555; }
 .escape_sequence    { color: #94BFF3; }
-
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .keyword.unsafe     { color: #BC8383; font-weight: bold; }
 .control            { font-style: italic; }
+
+.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="comment documentation">/// ```</span>
 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> _ = </span><span class="string_literal injected">"early doctests should not go boom"</span><span class="generic injected">;</span>
diff --git a/crates/ra_ide/test_data/highlight_injection.html b/crates/ra_ide/test_data/highlight_injection.html
index 1b0349bae2..e15234936c 100644
--- a/crates/ra_ide/test_data/highlight_injection.html
+++ b/crates/ra_ide/test_data/highlight_injection.html
@@ -24,17 +24,18 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .bool_literal       { color: #BFE6EB; }
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
 .variable           { color: #DCDCCC; }
 .format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
-.unresolved_reference { color: #FC5555; }
 .escape_sequence    { color: #94BFF3; }
-
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .keyword.unsafe     { color: #BC8383; font-weight: bold; }
 .control            { font-style: italic; }
+
+.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
-<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span>(<span class="variable declaration">ra_fixture</span>: &<span class="builtin_type">str</span>) {}
+<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span>(<span class="value_param declaration">ra_fixture</span>: &<span class="builtin_type">str</span>) {}
 
 <span class="keyword">fn</span> <span class="function declaration">main</span>() {
     <span class="function">fixture</span>(<span class="string_literal">r#"</span>
diff --git a/crates/ra_ide/test_data/highlight_strings.html b/crates/ra_ide/test_data/highlight_strings.html
index d184b56910..4238133661 100644
--- a/crates/ra_ide/test_data/highlight_strings.html
+++ b/crates/ra_ide/test_data/highlight_strings.html
@@ -24,15 +24,16 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .bool_literal       { color: #BFE6EB; }
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
 .variable           { color: #DCDCCC; }
 .format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
-.unresolved_reference { color: #FC5555; }
 .escape_sequence    { color: #94BFF3; }
-
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .keyword.unsafe     { color: #BC8383; font-weight: bold; }
 .control            { font-style: italic; }
+
+.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="macro">macro_rules!</span> <span class="macro declaration">println</span> {
     ($($arg:tt)*) =&gt; ({
diff --git a/crates/ra_ide/test_data/highlight_unsafe.html b/crates/ra_ide/test_data/highlight_unsafe.html
index 6936e949fe..7585fbb426 100644
--- a/crates/ra_ide/test_data/highlight_unsafe.html
+++ b/crates/ra_ide/test_data/highlight_unsafe.html
@@ -24,15 +24,16 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .bool_literal       { color: #BFE6EB; }
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
 .variable           { color: #DCDCCC; }
 .format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
-.unresolved_reference { color: #FC5555; }
 .escape_sequence    { color: #94BFF3; }
-
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .keyword.unsafe     { color: #BC8383; font-weight: bold; }
 .control            { font-style: italic; }
+
+.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span>() {}
 
diff --git a/crates/ra_ide/test_data/highlighting.html b/crates/ra_ide/test_data/highlighting.html
index 8d0b38f958..134743c72c 100644
--- a/crates/ra_ide/test_data/highlighting.html
+++ b/crates/ra_ide/test_data/highlighting.html
@@ -24,15 +24,16 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .bool_literal       { color: #BFE6EB; }
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
 .variable           { color: #DCDCCC; }
 .format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
-.unresolved_reference { color: #FC5555; }
 .escape_sequence    { color: #94BFF3; }
-
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .keyword.unsafe     { color: #BC8383; font-weight: bold; }
 .control            { font-style: italic; }
+
+.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="attribute">#[</span><span class="function attribute">derive</span><span class="attribute">(Clone, Debug)]</span>
 <span class="keyword">struct</span> <span class="struct declaration">Foo</span> {
@@ -108,8 +109,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword">use</span> <span class="enum">Option</span>::*;
 
 <span class="keyword">impl</span>&lt;<span class="type_param declaration">T</span>&gt; <span class="enum">Option</span>&lt;<span class="type_param">T</span>&gt; {
-    <span class="keyword">fn</span> <span class="function declaration">and</span>&lt;<span class="type_param declaration">U</span>&gt;(<span class="self_keyword">self</span>, <span class="variable declaration">other</span>: <span class="enum">Option</span>&lt;<span class="type_param">U</span>&gt;) -&gt; <span class="enum">Option</span>&lt;(<span class="type_param">T</span>, <span class="type_param">U</span>)&gt; {
-        <span class="keyword control">match</span> <span class="variable">other</span> {
+    <span class="keyword">fn</span> <span class="function declaration">and</span>&lt;<span class="type_param declaration">U</span>&gt;(<span class="self_keyword">self</span>, <span class="value_param declaration">other</span>: <span class="enum">Option</span>&lt;<span class="type_param">U</span>&gt;) -&gt; <span class="enum">Option</span>&lt;(<span class="type_param">T</span>, <span class="type_param">U</span>)&gt; {
+        <span class="keyword control">match</span> <span class="value_param">other</span> {
             <span class="enum_variant">None</span> =&gt; <span class="macro">unimplemented!</span>(),
             <span class="variable declaration">Nope</span> =&gt; <span class="variable">Nope</span>,
         }
diff --git a/crates/ra_ide/test_data/rainbow_highlighting.html b/crates/ra_ide/test_data/rainbow_highlighting.html
index 9516c74410..84a7686b27 100644
--- a/crates/ra_ide/test_data/rainbow_highlighting.html
+++ b/crates/ra_ide/test_data/rainbow_highlighting.html
@@ -24,15 +24,16 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .bool_literal       { color: #BFE6EB; }
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
 .variable           { color: #DCDCCC; }
 .format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
-.unresolved_reference { color: #FC5555; }
 .escape_sequence    { color: #94BFF3; }
-
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .keyword.unsafe     { color: #BC8383; font-weight: bold; }
 .control            { font-style: italic; }
+
+.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span>() {
     <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> = <span class="string_literal">"hello"</span>;