From 642c1eb720051907036e017e612f615932ea457e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 4 Dec 2021 18:01:22 +0100 Subject: [PATCH 1/3] Introduce SymbolKind::Attribute --- .../ide/src/syntax_highlighting/highlight.rs | 4 ++-- crates/ide/src/syntax_highlighting/tags.rs | 5 ++-- .../test_data/highlight_doctest.html | 10 ++++---- .../test_data/highlight_strings.html | 20 ++++++++-------- .../test_data/highlight_unsafe.html | 2 +- .../test_data/highlighting.html | 12 +++++----- .../src/completions/attribute.rs | 24 ++++++++----------- .../src/completions/attribute/cfg.rs | 13 ++++------ .../src/completions/attribute/derive.rs | 16 ++++++------- .../src/completions/attribute/lint.rs | 11 +++------ .../src/completions/attribute/repr.rs | 10 +++----- crates/ide_completion/src/item.rs | 3 +-- crates/ide_db/src/lib.rs | 1 + crates/rust-analyzer/src/semantic_tokens.rs | 1 + crates/rust-analyzer/src/to_proto.rs | 11 +++++---- 15 files changed, 66 insertions(+), 77 deletions(-) diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index 34c4ccd4c7..8481f41437 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs @@ -133,7 +133,7 @@ fn token( _ if parent_matches::(&token) => HlOperator::Other.into(), _ if parent_matches::(&token) => HlOperator::Other.into(), _ if parent_matches::(&token) => HlOperator::Other.into(), - _ if parent_matches::(&token) => HlTag::Attribute.into(), + _ if parent_matches::(&token) => HlTag::AttributeBracket.into(), kind => match kind { T!['['] | T![']'] => HlPunct::Bracket, T!['{'] | T!['}'] => HlPunct::Brace, @@ -200,7 +200,7 @@ fn node( return None; }, ast::Attr(__) => { - HlTag::Attribute.into() + HlTag::AttributeBracket.into() }, // Highlight definitions depending on the "type" of the definition. ast::Name(name) => { diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index 3e0a78392a..8c796a3bfb 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs @@ -18,7 +18,7 @@ pub struct HlMods(u32); pub enum HlTag { Symbol(SymbolKind), - Attribute, + AttributeBracket, BoolLiteral, BuiltinType, ByteLiteral, @@ -124,6 +124,7 @@ impl HlTag { fn as_str(self) -> &'static str { match self { HlTag::Symbol(symbol) => match symbol { + SymbolKind::Attribute => "attribute", SymbolKind::BuiltinAttr => "builtin_attr", SymbolKind::Const => "constant", SymbolKind::ConstParam => "const_param", @@ -147,7 +148,7 @@ impl HlTag { SymbolKind::ValueParam => "value_param", SymbolKind::Variant => "enum_variant", }, - HlTag::Attribute => "attribute", + HlTag::AttributeBracket => "attribute_bracket", HlTag::BoolLiteral => "bool_literal", HlTag::BuiltinType => "builtin_type", HlTag::ByteLiteral => "byte_literal", diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index 1e778cc619..0b1c5470ee 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -72,7 +72,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd /// # Examples /// /// ``` - /// # #![allow(unused_mut)] + /// # #![allow(unused_mut)] /// let mut foo: Foo = Foo::new(); /// ``` pub const fn new() -> Foo { @@ -143,12 +143,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd /// /// ``` /// loop {} -#[cfg_attr(not(feature = "false"), doc = "loop {}")] -#[doc = "loop {}"] +#[cfg_attr(not(feature = "false"), doc = "loop {}")] +#[doc = "loop {}"] /// ``` /// -#[cfg_attr(feature = "alloc", doc = "```rust")] -#[cfg_attr(not(feature = "alloc"), doc = "```ignore")] +#[cfg_attr(feature = "alloc", doc = "```rust")] +#[cfg_attr(not(feature = "alloc"), doc = "```ignore")] /// let _ = example(&alloc::vec![1, 2, 3]); /// ``` pub fn mix_and_match() {} diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index b44fc817c7..e457069e1f 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -45,14 +45,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd $crate::io::_print($crate::format_args_nl!($($arg)*)); }) } -#[rustc_builtin_macro] -#[macro_export] +#[rustc_builtin_macro] +#[macro_export] macro_rules! format_args {} -#[rustc_builtin_macro] -#[macro_export] +#[rustc_builtin_macro] +#[macro_export] macro_rules! const_format_args {} -#[rustc_builtin_macro] -#[macro_export] +#[rustc_builtin_macro] +#[macro_export] macro_rules! format_args_nl {} mod panic { @@ -77,12 +77,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd } } -#[rustc_builtin_macro(std_panic)] -#[macro_export] +#[rustc_builtin_macro(std_panic)] +#[macro_export] macro_rules! panic {} -#[rustc_builtin_macro] +#[rustc_builtin_macro] macro_rules! assert {} -#[rustc_builtin_macro] +#[rustc_builtin_macro] macro_rules! asm {} macro_rules! toho { diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html index 65dfbdf211..04494283d5 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html @@ -54,7 +54,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd unsafe fn unsafe_method(&self) {} } -#[repr(packed)] +#[repr(packed)] struct Packed { a: u16, } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 370f58080e..8c9deac005 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html @@ -43,16 +43,16 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
use inner::{self as inner_mod};
 mod inner {}
 
-#[allow()]
-#[proc_macros::identity]
+#[allow()]
+#[proc_macros::identity]
 pub mod ops {
-    #[lang = "fn_once"]
+    #[lang = "fn_once"]
     pub trait FnOnce<Args> {}
 
-    #[lang = "fn_mut"]
+    #[lang = "fn_mut"]
     pub trait FnMut<Args>: FnOnce<Args> {}
 
-    #[lang = "fn"]
+    #[lang = "fn"]
     pub trait Fn<Args>: FnMut<Args> {}
 }
 
@@ -87,7 +87,7 @@ proc_macros::mirror! {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy)]
 struct FooCopy {
     x: u32,
 }
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs
index 8740db326b..f09015efb6 100644
--- a/crates/ide_completion/src/completions/attribute.rs
+++ b/crates/ide_completion/src/completions/attribute.rs
@@ -4,20 +4,19 @@
 //! for built-in attributes.
 
 use hir::HasAttrs;
-use ide_db::helpers::{
-    generated_lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES, RUSTDOC_LINTS},
-    parse_tt_as_comma_sep_paths,
+use ide_db::{
+    helpers::{
+        generated_lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES, RUSTDOC_LINTS},
+        parse_tt_as_comma_sep_paths,
+    },
+    SymbolKind,
 };
 use itertools::Itertools;
 use once_cell::sync::Lazy;
 use rustc_hash::FxHashMap;
 use syntax::{algo::non_trivia_sibling, ast, AstNode, Direction, SyntaxKind, T};
 
-use crate::{
-    context::CompletionContext,
-    item::{CompletionItem, CompletionItemKind},
-    Completions,
-};
+use crate::{context::CompletionContext, item::CompletionItem, Completions};
 
 mod cfg;
 mod derive;
@@ -73,11 +72,8 @@ fn complete_new_attribute(acc: &mut Completions, ctx: &CompletionContext, attrib
     });
 
     let add_completion = |attr_completion: &AttrCompletion| {
-        let mut item = CompletionItem::new(
-            CompletionItemKind::Attribute,
-            ctx.source_range(),
-            attr_completion.label,
-        );
+        let mut item =
+            CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), attr_completion.label);
 
         if let Some(lookup) = attr_completion.lookup {
             item.lookup_by(lookup);
@@ -107,7 +103,7 @@ fn complete_new_attribute(acc: &mut Completions, ctx: &CompletionContext, attrib
         if let hir::ScopeDef::MacroDef(mac) = scope_def {
             if mac.kind() == hir::MacroKind::Attr {
                 let mut item = CompletionItem::new(
-                    CompletionItemKind::Attribute,
+                    SymbolKind::Attribute,
                     ctx.source_range(),
                     name.to_smol_str(),
                 );
diff --git a/crates/ide_completion/src/completions/attribute/cfg.rs b/crates/ide_completion/src/completions/attribute/cfg.rs
index 1a10531a1b..d1a4722b30 100644
--- a/crates/ide_completion/src/completions/attribute/cfg.rs
+++ b/crates/ide_completion/src/completions/attribute/cfg.rs
@@ -2,16 +2,14 @@
 
 use std::iter;
 
+use ide_db::SymbolKind;
 use syntax::SyntaxKind;
 
-use crate::{
-    completions::Completions, context::CompletionContext, CompletionItem, CompletionItemKind,
-};
+use crate::{completions::Completions, context::CompletionContext, CompletionItem};
 
 pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
     let add_completion = |item: &str| {
-        let mut completion =
-            CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), item);
+        let mut completion = CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), item);
         completion.insert_text(format!(r#""{}""#, item));
         acc.add(completion.build());
     };
@@ -34,7 +32,7 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
                 krate.potential_cfg(ctx.db).get_cfg_values(&name).cloned().for_each(|s| {
                     let insert_text = format!(r#""{}""#, s);
                     let mut item =
-                        CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), s);
+                        CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), s);
                     item.insert_text(insert_text);
 
                     acc.add(item.build());
@@ -44,8 +42,7 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
         None => {
             if let Some(krate) = ctx.krate {
                 krate.potential_cfg(ctx.db).get_cfg_keys().cloned().for_each(|s| {
-                    let item =
-                        CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), s);
+                    let item = CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), s);
                     acc.add(item.build());
                 })
             }
diff --git a/crates/ide_completion/src/completions/attribute/derive.rs b/crates/ide_completion/src/completions/attribute/derive.rs
index b9032318ec..b71ee21d3c 100644
--- a/crates/ide_completion/src/completions/attribute/derive.rs
+++ b/crates/ide_completion/src/completions/attribute/derive.rs
@@ -1,15 +1,16 @@
 //! Completion for derives
 use hir::{HasAttrs, MacroDef, MacroKind};
-use ide_db::helpers::{import_assets::ImportAssets, insert_use::ImportScope, FamousDefs};
+use ide_db::{
+    helpers::{import_assets::ImportAssets, insert_use::ImportScope, FamousDefs},
+    SymbolKind,
+};
 use itertools::Itertools;
 use rustc_hash::FxHashSet;
 use syntax::{ast, SmolStr, SyntaxKind};
 
 use crate::{
-    completions::flyimport::compute_fuzzy_completion_order_key,
-    context::CompletionContext,
-    item::{CompletionItem, CompletionItemKind},
-    Completions, ImportEdit,
+    completions::flyimport::compute_fuzzy_completion_order_key, context::CompletionContext,
+    item::CompletionItem, Completions, ImportEdit,
 };
 
 pub(super) fn complete_derive(
@@ -56,8 +57,7 @@ pub(super) fn complete_derive(
             _ => (name, None),
         };
 
-        let mut item =
-            CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), label);
+        let mut item = CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), label);
         if let Some(docs) = mac.docs(ctx.db) {
             item.documentation(docs);
         }
@@ -112,7 +112,7 @@ fn flyimport_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option
             })
             .filter_map(|(import, mac)| {
                 let mut item = CompletionItem::new(
-                    CompletionItemKind::Attribute,
+                    SymbolKind::Attribute,
                     ctx.source_range(),
                     mac.name(ctx.db)?.to_smol_str(),
                 );
diff --git a/crates/ide_completion/src/completions/attribute/lint.rs b/crates/ide_completion/src/completions/attribute/lint.rs
index 05a29dd0ae..e2477423a2 100644
--- a/crates/ide_completion/src/completions/attribute/lint.rs
+++ b/crates/ide_completion/src/completions/attribute/lint.rs
@@ -1,12 +1,8 @@
 //! Completion for lints
-use ide_db::helpers::generated_lints::Lint;
+use ide_db::{helpers::generated_lints::Lint, SymbolKind};
 use syntax::{ast, T};
 
-use crate::{
-    context::CompletionContext,
-    item::{CompletionItem, CompletionItemKind},
-    Completions,
-};
+use crate::{context::CompletionContext, item::CompletionItem, Completions};
 
 pub(super) fn complete_lint(
     acc: &mut Completions,
@@ -58,8 +54,7 @@ pub(super) fn complete_lint(
             Some(qual) if !is_qualified => format!("{}::{}", qual, name),
             _ => name.to_owned(),
         };
-        let mut item =
-            CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), label);
+        let mut item = CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), label);
         item.documentation(hir::Documentation::new(description.to_owned()));
         item.add_to(acc)
     }
diff --git a/crates/ide_completion/src/completions/attribute/repr.rs b/crates/ide_completion/src/completions/attribute/repr.rs
index c240912f02..4c4a37fb5e 100644
--- a/crates/ide_completion/src/completions/attribute/repr.rs
+++ b/crates/ide_completion/src/completions/attribute/repr.rs
@@ -1,12 +1,9 @@
 //! Completion for representations.
 
+use ide_db::SymbolKind;
 use syntax::ast;
 
-use crate::{
-    context::CompletionContext,
-    item::{CompletionItem, CompletionItemKind},
-    Completions,
-};
+use crate::{context::CompletionContext, item::CompletionItem, Completions};
 
 pub(super) fn complete_repr(acc: &mut Completions, ctx: &CompletionContext, input: ast::TokenTree) {
     if let Some(existing_reprs) = super::parse_comma_sep_expr(input) {
@@ -29,8 +26,7 @@ pub(super) fn complete_repr(acc: &mut Completions, ctx: &CompletionContext, inpu
                 continue;
             }
 
-            let mut item =
-                CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), label);
+            let mut item = CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), label);
             if let Some(lookup) = lookup {
                 item.lookup_by(lookup);
             }
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs
index b3f404d905..7ff16adce1 100644
--- a/crates/ide_completion/src/item.rs
+++ b/crates/ide_completion/src/item.rs
@@ -216,7 +216,6 @@ impl CompletionRelevance {
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub enum CompletionItemKind {
     SymbolKind(SymbolKind),
-    Attribute,
     Binding,
     BuiltinType,
     Keyword,
@@ -232,6 +231,7 @@ impl CompletionItemKind {
     pub(crate) fn tag(&self) -> &'static str {
         match self {
             CompletionItemKind::SymbolKind(kind) => match kind {
+                SymbolKind::Attribute => "at",
                 SymbolKind::BuiltinAttr => "ba",
                 SymbolKind::Const => "ct",
                 SymbolKind::ConstParam => "cp",
@@ -255,7 +255,6 @@ impl CompletionItemKind {
                 SymbolKind::ValueParam => "vp",
                 SymbolKind::Variant => "ev",
             },
-            CompletionItemKind::Attribute => "at",
             CompletionItemKind::Binding => "bn",
             CompletionItemKind::BuiltinType => "bt",
             CompletionItemKind::Keyword => "kw",
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs
index 67f23536bd..99b64821fc 100644
--- a/crates/ide_db/src/lib.rs
+++ b/crates/ide_db/src/lib.rs
@@ -145,6 +145,7 @@ fn line_index(db: &dyn LineIndexDatabase, file_id: FileId) -> Arc {
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub enum SymbolKind {
+    Attribute,
     BuiltinAttr,
     Const,
     ConstParam,
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index 8e1ccfb397..61a8159278 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -41,6 +41,7 @@ define_semantic_token_types![
     (ANGLE, "angle"),
     (ARITHMETIC, "arithmetic"),
     (ATTRIBUTE, "attribute"),
+    (ATTRIBUTE_BRACKET, "attributeBracket"),
     (BITWISE, "bitwise"),
     (BOOLEAN, "boolean"),
     (BRACE, "brace"),
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 579ad22bac..91245ace7b 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -50,7 +50,9 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
         SymbolKind::Enum => lsp_types::SymbolKind::ENUM,
         SymbolKind::Variant => lsp_types::SymbolKind::ENUM_MEMBER,
         SymbolKind::Trait => lsp_types::SymbolKind::INTERFACE,
-        SymbolKind::Macro | SymbolKind::BuiltinAttr => lsp_types::SymbolKind::FUNCTION,
+        SymbolKind::Macro | SymbolKind::BuiltinAttr | SymbolKind::Attribute => {
+            lsp_types::SymbolKind::FUNCTION
+        }
         SymbolKind::Module | SymbolKind::ToolModule => lsp_types::SymbolKind::MODULE,
         SymbolKind::TypeAlias | SymbolKind::TypeParam => lsp_types::SymbolKind::TYPE_PARAMETER,
         SymbolKind::Field => lsp_types::SymbolKind::FIELD,
@@ -100,7 +102,6 @@ pub(crate) fn completion_item_kind(
     completion_item_kind: CompletionItemKind,
 ) -> lsp_types::CompletionItemKind {
     match completion_item_kind {
-        CompletionItemKind::Attribute => lsp_types::CompletionItemKind::ENUM_MEMBER,
         CompletionItemKind::Binding => lsp_types::CompletionItemKind::VARIABLE,
         CompletionItemKind::BuiltinType => lsp_types::CompletionItemKind::STRUCT,
         CompletionItemKind::Keyword => lsp_types::CompletionItemKind::KEYWORD,
@@ -108,6 +109,7 @@ pub(crate) fn completion_item_kind(
         CompletionItemKind::Snippet => lsp_types::CompletionItemKind::SNIPPET,
         CompletionItemKind::UnresolvedReference => lsp_types::CompletionItemKind::REFERENCE,
         CompletionItemKind::SymbolKind(symbol) => match symbol {
+            SymbolKind::Attribute => lsp_types::CompletionItemKind::FUNCTION,
             SymbolKind::Const => lsp_types::CompletionItemKind::CONSTANT,
             SymbolKind::ConstParam => lsp_types::CompletionItemKind::TYPE_PARAMETER,
             SymbolKind::Enum => lsp_types::CompletionItemKind::ENUM,
@@ -117,7 +119,7 @@ pub(crate) fn completion_item_kind(
             SymbolKind::Label => lsp_types::CompletionItemKind::VARIABLE,
             SymbolKind::LifetimeParam => lsp_types::CompletionItemKind::TYPE_PARAMETER,
             SymbolKind::Local => lsp_types::CompletionItemKind::VARIABLE,
-            SymbolKind::Macro => lsp_types::CompletionItemKind::METHOD,
+            SymbolKind::Macro => lsp_types::CompletionItemKind::FUNCTION,
             SymbolKind::Module => lsp_types::CompletionItemKind::MODULE,
             SymbolKind::SelfParam => lsp_types::CompletionItemKind::VALUE,
             SymbolKind::Static => lsp_types::CompletionItemKind::VALUE,
@@ -468,6 +470,7 @@ fn semantic_token_type_and_modifiers(
     let mut mods = semantic_tokens::ModifierSet::default();
     let type_ = match highlight.tag {
         HlTag::Symbol(symbol) => match symbol {
+            SymbolKind::Attribute => semantic_tokens::ATTRIBUTE,
             SymbolKind::Module => lsp_types::SemanticTokenType::NAMESPACE,
             SymbolKind::Impl => semantic_tokens::TYPE_ALIAS,
             SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY,
@@ -504,7 +507,7 @@ fn semantic_token_type_and_modifiers(
             SymbolKind::BuiltinAttr => semantic_tokens::BUILTIN_ATTRIBUTE,
             SymbolKind::ToolModule => semantic_tokens::TOOL_MODULE,
         },
-        HlTag::Attribute => semantic_tokens::ATTRIBUTE,
+        HlTag::AttributeBracket => semantic_tokens::ATTRIBUTE_BRACKET,
         HlTag::BoolLiteral => semantic_tokens::BOOLEAN,
         HlTag::BuiltinType => semantic_tokens::BUILTIN_TYPE,
         HlTag::ByteLiteral | HlTag::NumericLiteral => lsp_types::SemanticTokenType::NUMBER,

From e4f2d0e3a820474b4de1bf2dc5c7734637cadd10 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Sat, 4 Dec 2021 18:18:09 +0100
Subject: [PATCH 2/3] Introduce SymbolKind::Derive

---
 crates/ide/src/navigation_target.rs           |   8 +-
 .../ide/src/syntax_highlighting/highlight.rs  |   8 +-
 crates/ide/src/syntax_highlighting/tags.rs    |   1 +
 .../test_data/highlighting.html               |   4 +-
 .../src/completions/attribute/cfg.rs          |   6 +-
 .../src/completions/attribute/derive.rs       |   9 +-
 .../src/completions/attribute/repr.rs         |   2 +-
 crates/ide_completion/src/item.rs             |   1 +
 crates/ide_completion/src/tests/attribute.rs  | 180 +++++++++---------
 crates/ide_db/src/lib.rs                      |   1 +
 crates/rust-analyzer/src/semantic_tokens.rs   |   1 +
 crates/rust-analyzer/src/to_proto.rs          |   9 +-
 12 files changed, 125 insertions(+), 105 deletions(-)

diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs
index 49ff3625ca..d97e52200d 100644
--- a/crates/ide/src/navigation_target.rs
+++ b/crates/ide/src/navigation_target.rs
@@ -363,7 +363,13 @@ impl TryToNav for hir::MacroDef {
         let mut res = NavigationTarget::from_named(
             db,
             src.as_ref().with_value(name_owner),
-            SymbolKind::Macro,
+            match self.kind() {
+                hir::MacroKind::Declarative
+                | hir::MacroKind::BuiltIn
+                | hir::MacroKind::ProcMacro => SymbolKind::Macro,
+                hir::MacroKind::Derive => SymbolKind::Derive,
+                hir::MacroKind::Attr => SymbolKind::Attribute,
+            },
         );
         res.docs = self.docs(db);
         Some(res)
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 8481f41437..a5be905983 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -374,7 +374,13 @@ fn highlight_def(
 ) -> Highlight {
     let db = sema.db;
     let mut h = match def {
-        Definition::Macro(_) => Highlight::new(HlTag::Symbol(SymbolKind::Macro)),
+        Definition::Macro(m) => Highlight::new(HlTag::Symbol(match m.kind() {
+            hir::MacroKind::Declarative | hir::MacroKind::BuiltIn | hir::MacroKind::ProcMacro => {
+                SymbolKind::Macro
+            }
+            hir::MacroKind::Derive => SymbolKind::Derive,
+            hir::MacroKind::Attr => SymbolKind::Attribute,
+        })),
         Definition::Field(_) => Highlight::new(HlTag::Symbol(SymbolKind::Field)),
         Definition::Module(module) => {
             let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Module));
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs
index 8c796a3bfb..7216eae0eb 100644
--- a/crates/ide/src/syntax_highlighting/tags.rs
+++ b/crates/ide/src/syntax_highlighting/tags.rs
@@ -128,6 +128,7 @@ impl HlTag {
                 SymbolKind::BuiltinAttr => "builtin_attr",
                 SymbolKind::Const => "constant",
                 SymbolKind::ConstParam => "const_param",
+                SymbolKind::Derive => "derive",
                 SymbolKind::Enum => "enum",
                 SymbolKind::Field => "field",
                 SymbolKind::Function => "function",
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 8c9deac005..b0fbbfda2a 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -44,7 +44,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 mod inner {}
 
 #[allow()]
-#[proc_macros::identity]
+#[proc_macros::identity]
 pub mod ops {
     #[lang = "fn_once"]
     pub trait FnOnce<Args> {}
@@ -87,7 +87,7 @@ proc_macros::mirror! {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy)]
 struct FooCopy {
     x: u32,
 }
diff --git a/crates/ide_completion/src/completions/attribute/cfg.rs b/crates/ide_completion/src/completions/attribute/cfg.rs
index d1a4722b30..e53bf49174 100644
--- a/crates/ide_completion/src/completions/attribute/cfg.rs
+++ b/crates/ide_completion/src/completions/attribute/cfg.rs
@@ -9,7 +9,7 @@ use crate::{completions::Completions, context::CompletionContext, CompletionItem
 
 pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
     let add_completion = |item: &str| {
-        let mut completion = CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), item);
+        let mut completion = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), item);
         completion.insert_text(format!(r#""{}""#, item));
         acc.add(completion.build());
     };
@@ -32,7 +32,7 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
                 krate.potential_cfg(ctx.db).get_cfg_values(&name).cloned().for_each(|s| {
                     let insert_text = format!(r#""{}""#, s);
                     let mut item =
-                        CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), s);
+                        CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
                     item.insert_text(insert_text);
 
                     acc.add(item.build());
@@ -42,7 +42,7 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
         None => {
             if let Some(krate) = ctx.krate {
                 krate.potential_cfg(ctx.db).get_cfg_keys().cloned().for_each(|s| {
-                    let item = CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), s);
+                    let item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
                     acc.add(item.build());
                 })
             }
diff --git a/crates/ide_completion/src/completions/attribute/derive.rs b/crates/ide_completion/src/completions/attribute/derive.rs
index b71ee21d3c..0daf114788 100644
--- a/crates/ide_completion/src/completions/attribute/derive.rs
+++ b/crates/ide_completion/src/completions/attribute/derive.rs
@@ -57,7 +57,7 @@ pub(super) fn complete_derive(
             _ => (name, None),
         };
 
-        let mut item = CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), label);
+        let mut item = CompletionItem::new(SymbolKind::Derive, ctx.source_range(), label);
         if let Some(docs) = mac.docs(ctx.db) {
             item.documentation(docs);
         }
@@ -67,7 +67,7 @@ pub(super) fn complete_derive(
         item.add_to(acc);
     }
 
-    flyimport_attribute(acc, ctx);
+    flyimport_derive(acc, ctx);
 }
 
 fn get_derives_in_scope(ctx: &CompletionContext) -> Vec<(hir::Name, MacroDef)> {
@@ -82,7 +82,7 @@ fn get_derives_in_scope(ctx: &CompletionContext) -> Vec<(hir::Name, MacroDef)> {
     result
 }
 
-fn flyimport_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
+fn flyimport_derive(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
     if ctx.token.kind() != SyntaxKind::IDENT {
         return None;
     };
@@ -106,13 +106,14 @@ fn flyimport_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option
                 hir::ItemInNs::Macros(mac) => Some((import, mac)),
                 _ => None,
             })
+            .filter(|&(_, mac)| mac.kind() == MacroKind::Derive)
             .filter(|&(_, mac)| !ctx.is_item_hidden(&hir::ItemInNs::Macros(mac)))
             .sorted_by_key(|(import, _)| {
                 compute_fuzzy_completion_order_key(&import.import_path, &user_input_lowercased)
             })
             .filter_map(|(import, mac)| {
                 let mut item = CompletionItem::new(
-                    SymbolKind::Attribute,
+                    SymbolKind::Derive,
                     ctx.source_range(),
                     mac.name(ctx.db)?.to_smol_str(),
                 );
diff --git a/crates/ide_completion/src/completions/attribute/repr.rs b/crates/ide_completion/src/completions/attribute/repr.rs
index 4c4a37fb5e..805038091c 100644
--- a/crates/ide_completion/src/completions/attribute/repr.rs
+++ b/crates/ide_completion/src/completions/attribute/repr.rs
@@ -26,7 +26,7 @@ pub(super) fn complete_repr(acc: &mut Completions, ctx: &CompletionContext, inpu
                 continue;
             }
 
-            let mut item = CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), label);
+            let mut item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), label);
             if let Some(lookup) = lookup {
                 item.lookup_by(lookup);
             }
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs
index 7ff16adce1..4a6e034dc9 100644
--- a/crates/ide_completion/src/item.rs
+++ b/crates/ide_completion/src/item.rs
@@ -235,6 +235,7 @@ impl CompletionItemKind {
                 SymbolKind::BuiltinAttr => "ba",
                 SymbolKind::Const => "ct",
                 SymbolKind::ConstParam => "cp",
+                SymbolKind::Derive => "de",
                 SymbolKind::Enum => "en",
                 SymbolKind::Field => "fd",
                 SymbolKind::Function => "fn",
diff --git a/crates/ide_completion/src/tests/attribute.rs b/crates/ide_completion/src/tests/attribute.rs
index 45979d4828..8141fab299 100644
--- a/crates/ide_completion/src/tests/attribute.rs
+++ b/crates/ide_completion/src/tests/attribute.rs
@@ -560,9 +560,9 @@ mod cfg {
         check(
             r#"#[cfg(target_endian = $0"#,
             expect![[r#"
-            at little
-            at big
-"#]],
+                ba little
+                ba big
+            "#]],
         );
     }
 }
@@ -594,13 +594,13 @@ mod derive {
 #[derive($0)] struct Test;
 "#,
             expect![[r#"
-                at Default
-                at Clone, Copy
-                at PartialEq
-                at PartialEq, Eq
-                at PartialEq, Eq, PartialOrd, Ord
-                at Clone
-                at PartialEq, PartialOrd
+                de Default
+                de Clone, Copy
+                de PartialEq
+                de PartialEq, Eq
+                de PartialEq, Eq, PartialOrd, Ord
+                de Clone
+                de PartialEq, PartialOrd
             "#]],
         );
     }
@@ -613,12 +613,12 @@ mod derive {
 #[derive(serde::Serialize, PartialEq, $0)] struct Test;
 "#,
             expect![[r#"
-                at Default
-                at Clone, Copy
-                at Eq
-                at Eq, PartialOrd, Ord
-                at Clone
-                at PartialOrd
+                de Default
+                de Clone, Copy
+                de Eq
+                de Eq, PartialOrd, Ord
+                de Clone
+                de PartialOrd
             "#]],
         )
     }
@@ -631,12 +631,12 @@ mod derive {
 #[derive($0 serde::Serialize, PartialEq)] struct Test;
 "#,
             expect![[r#"
-                at Default
-                at Clone, Copy
-                at Eq
-                at Eq, PartialOrd, Ord
-                at Clone
-                at PartialOrd
+                de Default
+                de Clone, Copy
+                de Eq
+                de Eq, PartialOrd, Ord
+                de Clone
+                de PartialOrd
             "#]],
         )
     }
@@ -649,7 +649,7 @@ mod derive {
 #[derive(der$0)] struct Test;
 "#,
             expect![[r#"
-                at DeriveIdentity (use proc_macros::DeriveIdentity)
+                de DeriveIdentity (use proc_macros::DeriveIdentity)
             "#]],
         );
         check_derive(
@@ -659,7 +659,7 @@ use proc_macros::DeriveIdentity;
 #[derive(der$0)] struct Test;
 "#,
             expect![[r#"
-                at DeriveIdentity
+                de DeriveIdentity
             "#]],
         );
     }
@@ -775,23 +775,23 @@ mod repr {
         check_repr(
             r#"#[repr($0)] struct Test;"#,
             expect![[r#"
-            at align($0)
-            at packed
-            at transparent
-            at C
-            at u8
-            at u16
-            at u32
-            at u64
-            at u128
-            at usize
-            at i8
-            at i16
-            at i32
-            at i64
-            at i28
-            at isize
-        "#]],
+                ba align($0)
+                ba packed
+                ba transparent
+                ba C
+                ba u8
+                ba u16
+                ba u32
+                ba u64
+                ba u128
+                ba usize
+                ba i8
+                ba i16
+                ba i32
+                ba i64
+                ba i28
+                ba isize
+            "#]],
         );
     }
 
@@ -805,21 +805,21 @@ mod repr {
         check_repr(
             r#"#[repr(align(1), $0)] struct Test;"#,
             expect![[r#"
-            at transparent
-            at C
-            at u8
-            at u16
-            at u32
-            at u64
-            at u128
-            at usize
-            at i8
-            at i16
-            at i32
-            at i64
-            at i28
-            at isize
-        "#]],
+                ba transparent
+                ba C
+                ba u8
+                ba u16
+                ba u32
+                ba u64
+                ba u128
+                ba usize
+                ba i8
+                ba i16
+                ba i32
+                ba i64
+                ba i28
+                ba isize
+            "#]],
         );
     }
 
@@ -828,21 +828,21 @@ mod repr {
         check_repr(
             r#"#[repr(packed, $0)] struct Test;"#,
             expect![[r#"
-            at transparent
-            at C
-            at u8
-            at u16
-            at u32
-            at u64
-            at u128
-            at usize
-            at i8
-            at i16
-            at i32
-            at i64
-            at i28
-            at isize
-        "#]],
+                ba transparent
+                ba C
+                ba u8
+                ba u16
+                ba u32
+                ba u64
+                ba u128
+                ba usize
+                ba i8
+                ba i16
+                ba i32
+                ba i64
+                ba i28
+                ba isize
+            "#]],
         );
     }
 
@@ -851,21 +851,21 @@ mod repr {
         check_repr(
             r#"#[repr(C, $0)] struct Test;"#,
             expect![[r#"
-            at align($0)
-            at packed
-            at u8
-            at u16
-            at u32
-            at u64
-            at u128
-            at usize
-            at i8
-            at i16
-            at i32
-            at i64
-            at i28
-            at isize
-        "#]],
+                ba align($0)
+                ba packed
+                ba u8
+                ba u16
+                ba u32
+                ba u64
+                ba u128
+                ba usize
+                ba i8
+                ba i16
+                ba i32
+                ba i64
+                ba i28
+                ba isize
+            "#]],
         );
     }
 
@@ -874,10 +874,10 @@ mod repr {
         check_repr(
             r#"#[repr(usize, $0)] struct Test;"#,
             expect![[r#"
-            at align($0)
-            at packed
-            at C
-        "#]],
+                ba align($0)
+                ba packed
+                ba C
+            "#]],
         );
     }
 }
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs
index 99b64821fc..0d14c176b5 100644
--- a/crates/ide_db/src/lib.rs
+++ b/crates/ide_db/src/lib.rs
@@ -149,6 +149,7 @@ pub enum SymbolKind {
     BuiltinAttr,
     Const,
     ConstParam,
+    Derive,
     Enum,
     Field,
     Function,
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index 61a8159278..1097a77afe 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -53,6 +53,7 @@ define_semantic_token_types![
     (COMMA, "comma"),
     (COMPARISON, "comparison"),
     (CONST_PARAMETER, "constParameter"),
+    (DERIVE, "derive"),
     (DOT, "dot"),
     (ESCAPE_SEQUENCE, "escapeSequence"),
     (FORMAT_SPECIFIER, "formatSpecifier"),
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 91245ace7b..f8c46b92fa 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -50,9 +50,10 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
         SymbolKind::Enum => lsp_types::SymbolKind::ENUM,
         SymbolKind::Variant => lsp_types::SymbolKind::ENUM_MEMBER,
         SymbolKind::Trait => lsp_types::SymbolKind::INTERFACE,
-        SymbolKind::Macro | SymbolKind::BuiltinAttr | SymbolKind::Attribute => {
-            lsp_types::SymbolKind::FUNCTION
-        }
+        SymbolKind::Macro
+        | SymbolKind::BuiltinAttr
+        | SymbolKind::Attribute
+        | SymbolKind::Derive => lsp_types::SymbolKind::FUNCTION,
         SymbolKind::Module | SymbolKind::ToolModule => lsp_types::SymbolKind::MODULE,
         SymbolKind::TypeAlias | SymbolKind::TypeParam => lsp_types::SymbolKind::TYPE_PARAMETER,
         SymbolKind::Field => lsp_types::SymbolKind::FIELD,
@@ -112,6 +113,7 @@ pub(crate) fn completion_item_kind(
             SymbolKind::Attribute => lsp_types::CompletionItemKind::FUNCTION,
             SymbolKind::Const => lsp_types::CompletionItemKind::CONSTANT,
             SymbolKind::ConstParam => lsp_types::CompletionItemKind::TYPE_PARAMETER,
+            SymbolKind::Derive => lsp_types::CompletionItemKind::FUNCTION,
             SymbolKind::Enum => lsp_types::CompletionItemKind::ENUM,
             SymbolKind::Field => lsp_types::CompletionItemKind::FIELD,
             SymbolKind::Function => lsp_types::CompletionItemKind::FUNCTION,
@@ -471,6 +473,7 @@ fn semantic_token_type_and_modifiers(
     let type_ = match highlight.tag {
         HlTag::Symbol(symbol) => match symbol {
             SymbolKind::Attribute => semantic_tokens::ATTRIBUTE,
+            SymbolKind::Derive => semantic_tokens::DERIVE,
             SymbolKind::Module => lsp_types::SemanticTokenType::NAMESPACE,
             SymbolKind::Impl => semantic_tokens::TYPE_ALIAS,
             SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY,

From 3472105ad9cef06d7a3a032047bcbf06bc80fe26 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Sat, 4 Dec 2021 18:23:25 +0100
Subject: [PATCH 3/3] Update semantic token docs

---
 crates/ide/src/syntax_highlighting.rs |  6 ++++--
 editors/code/package.json             | 10 ++++++++++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 56e07da0b9..0741e1ffbf 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -57,9 +57,11 @@ pub struct HlRange {
 // - For items:
 // +
 // [horizontal]
+// attribute:: Emitted for attribute macros.
 // enum:: Emitted for enums.
 // function:: Emitted for free-standing functions.
-// macro:: Emitted for macros.
+// derive:: Emitted for derive macros.
+// macro:: Emitted for function-like macros.
 // method:: Emitted for associated functions, also knowns as methods.
 // namespace:: Emitted for modules.
 // struct:: Emitted for structs.
@@ -90,6 +92,7 @@ pub struct HlRange {
 // +
 // [horizontal]
 // punctuation:: Emitted for general punctuation.
+// attributeBracket:: Emitted for attribute invocation brackets, that is the `#[` and `]` tokens.
 // angle:: Emitted for `<>` angle brackets.
 // brace:: Emitted for `{}` braces.
 // bracket:: Emitted for `[]` brackets.
@@ -102,7 +105,6 @@ pub struct HlRange {
 // //-
 //
 // [horizontal]
-// attribute:: Emitted for the `#[` `]` tokens.
 // builtinAttribute:: Emitted for names to builtin attributes in attribute path, the `repr` in `#[repr(u8)]` for example.
 // builtinType:: Emitted for builtin types like `u32`, `str` and `f32`.
 // comment:: Emitted for comments.
diff --git a/editors/code/package.json b/editors/code/package.json
index 5cad1752cc..f4d85d6abf 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -1126,6 +1126,11 @@
                 "id": "attribute",
                 "description": "Style for attributes"
             },
+            {
+                "id": "attributeBracket",
+                "description": "Style for attribute invocation brackets, that is the `#[` and `]` tokens",
+                "superType": "punctuation"
+            },
             {
                 "id": "bitwise",
                 "description": "Style for bitwise operators",
@@ -1180,6 +1185,11 @@
                 "id": "constParameter",
                 "description": "Style for const generics"
             },
+            {
+                "id": "derive",
+                "description": "Style for derives",
+                "superType": "attribute"
+            },
             {
                 "id": "dot",
                 "description": "Style for .",