about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-12-04 17:33:16 +0000
committerGitHub <noreply@github.com>2021-12-04 17:33:16 +0000
commit372a7cf98171eba668daa29aa94e0986a78022bd (patch)
tree4c1ef2acae67582e02a0adcd8e84420ced268664
parentb327cf3d0cb2f13af850400b341ea81c878ecf42 (diff)
parent3472105ad9cef06d7a3a032047bcbf06bc80fe26 (diff)
downloadrust-372a7cf98171eba668daa29aa94e0986a78022bd.tar.gz
rust-372a7cf98171eba668daa29aa94e0986a78022bd.zip
Merge #10929
10929: internal: Split up macro/attribute semantic tokens a bit more r=Veykril a=Veykril

Fixes https://github.com/rust-analyzer/rust-analyzer/issues/9172

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
-rw-r--r--crates/ide/src/navigation_target.rs8
-rw-r--r--crates/ide/src/syntax_highlighting.rs6
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs12
-rw-r--r--crates/ide/src/syntax_highlighting/tags.rs6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html10
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_strings.html20
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html12
-rw-r--r--crates/ide_completion/src/completions/attribute.rs24
-rw-r--r--crates/ide_completion/src/completions/attribute/cfg.rs13
-rw-r--r--crates/ide_completion/src/completions/attribute/derive.rs21
-rw-r--r--crates/ide_completion/src/completions/attribute/lint.rs11
-rw-r--r--crates/ide_completion/src/completions/attribute/repr.rs10
-rw-r--r--crates/ide_completion/src/item.rs4
-rw-r--r--crates/ide_completion/src/tests/attribute.rs180
-rw-r--r--crates/ide_db/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs2
-rw-r--r--crates/rust-analyzer/src/to_proto.rs14
-rw-r--r--editors/code/package.json10
19 files changed, 194 insertions, 173 deletions
diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs
index 49ff3625caa..d97e52200dc 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.rs b/crates/ide/src/syntax_highlighting.rs
index 56e07da0b90..0741e1ffbfa 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/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 34c4ccd4c76..a5be905983f 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::<ast::RangeExpr>(&token) => HlOperator::Other.into(),
                 _ if parent_matches::<ast::RangePat>(&token) => HlOperator::Other.into(),
                 _ if parent_matches::<ast::RestPat>(&token) => HlOperator::Other.into(),
-                _ if parent_matches::<ast::Attr>(&token) => HlTag::Attribute.into(),
+                _ if parent_matches::<ast::Attr>(&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) => {
@@ -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 3e0a78392a3..7216eae0ebc 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,9 +124,11 @@ 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",
+                SymbolKind::Derive => "derive",
                 SymbolKind::Enum => "enum",
                 SymbolKind::Field => "field",
                 SymbolKind::Function => "function",
@@ -147,7 +149,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 1e778cc6194..0b1c5470ee9 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
     <span class="comment documentation">/// # Examples</span>
     <span class="comment documentation">///</span>
     <span class="comment documentation">/// ```</span>
-    <span class="comment documentation">/// #</span><span class="none injected"> </span><span class="attribute attribute injected">#</span><span class="attribute attribute injected">!</span><span class="attribute attribute injected">[</span><span class="builtin_attr attribute injected library">allow</span><span class="parenthesis attribute injected">(</span><span class="none attribute injected">unused_mut</span><span class="parenthesis attribute injected">)</span><span class="attribute attribute injected">]</span>
+    <span class="comment documentation">/// #</span><span class="none injected"> </span><span class="attribute_bracket attribute injected">#</span><span class="attribute_bracket attribute injected">!</span><span class="attribute_bracket attribute injected">[</span><span class="builtin_attr attribute injected library">allow</span><span class="parenthesis attribute injected">(</span><span class="none attribute injected">unused_mut</span><span class="parenthesis attribute injected">)</span><span class="attribute_bracket attribute injected">]</span>
     <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="keyword injected">mut</span><span class="none injected"> </span><span class="variable declaration injected mutable">foo</span><span class="colon injected">:</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
     <span class="comment documentation">/// ```</span>
     <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function associated declaration public static">new</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="struct">Foo</span> <span class="brace">{</span>
@@ -143,12 +143,12 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="comment documentation">///</span>
 <span class="comment documentation">/// ```</span>
 <span class="comment documentation">/// </span><span class="keyword control injected">loop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="brace injected">}</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">cfg_attr</span><span class="parenthesis attribute">(</span><span class="none attribute">not</span><span class="parenthesis attribute">(</span><span class="none attribute">feature</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"false"</span><span class="parenthesis attribute">)</span><span class="comma attribute">,</span><span class="attribute attribute"> </span><span class="none attribute">doc</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"</span><span class="keyword control injected">loop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="brace injected">}</span><span class="string_literal attribute">"</span><span class="parenthesis attribute">)</span><span class="attribute attribute">]</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">doc</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"</span><span class="keyword control injected">loop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="brace injected">}</span><span class="string_literal attribute">"</span><span class="attribute attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">cfg_attr</span><span class="parenthesis attribute">(</span><span class="none attribute">not</span><span class="parenthesis attribute">(</span><span class="none attribute">feature</span><span class="attribute_bracket attribute"> </span><span class="operator attribute">=</span><span class="attribute_bracket attribute"> </span><span class="string_literal attribute">"false"</span><span class="parenthesis attribute">)</span><span class="comma attribute">,</span><span class="attribute_bracket attribute"> </span><span class="none attribute">doc</span><span class="attribute_bracket attribute"> </span><span class="operator attribute">=</span><span class="attribute_bracket attribute"> </span><span class="string_literal attribute">"</span><span class="keyword control injected">loop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="brace injected">}</span><span class="string_literal attribute">"</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">doc</span><span class="attribute_bracket attribute"> </span><span class="operator attribute">=</span><span class="attribute_bracket attribute"> </span><span class="string_literal attribute">"</span><span class="keyword control injected">loop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="brace injected">}</span><span class="string_literal attribute">"</span><span class="attribute_bracket attribute">]</span>
 <span class="comment documentation">/// ```</span>
 <span class="comment documentation">///</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">cfg_attr</span><span class="parenthesis attribute">(</span><span class="none attribute">feature</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"alloc"</span><span class="comma attribute">,</span><span class="attribute attribute"> </span><span class="none attribute">doc</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"```rust"</span><span class="parenthesis attribute">)</span><span class="attribute attribute">]</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">cfg_attr</span><span class="parenthesis attribute">(</span><span class="none attribute">not</span><span class="parenthesis attribute">(</span><span class="none attribute">feature</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"alloc"</span><span class="parenthesis attribute">)</span><span class="comma attribute">,</span><span class="attribute attribute"> </span><span class="none attribute">doc</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"```ignore"</span><span class="parenthesis attribute">)</span><span class="attribute attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">cfg_attr</span><span class="parenthesis attribute">(</span><span class="none attribute">feature</span><span class="attribute_bracket attribute"> </span><span class="operator attribute">=</span><span class="attribute_bracket attribute"> </span><span class="string_literal attribute">"alloc"</span><span class="comma attribute">,</span><span class="attribute_bracket attribute"> </span><span class="none attribute">doc</span><span class="attribute_bracket attribute"> </span><span class="operator attribute">=</span><span class="attribute_bracket attribute"> </span><span class="string_literal attribute">"```rust"</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">cfg_attr</span><span class="parenthesis attribute">(</span><span class="none attribute">not</span><span class="parenthesis attribute">(</span><span class="none attribute">feature</span><span class="attribute_bracket attribute"> </span><span class="operator attribute">=</span><span class="attribute_bracket attribute"> </span><span class="string_literal attribute">"alloc"</span><span class="parenthesis attribute">)</span><span class="comma attribute">,</span><span class="attribute_bracket attribute"> </span><span class="none attribute">doc</span><span class="attribute_bracket attribute"> </span><span class="operator attribute">=</span><span class="attribute_bracket attribute"> </span><span class="string_literal attribute">"```ignore"</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="punctuation injected">_</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="function injected">example</span><span class="parenthesis injected">(</span><span class="operator injected">&</span><span class="none injected">alloc::</span><span class="macro injected">vec!</span><span class="bracket injected">[</span><span class="numeric_literal injected">1</span><span class="comma injected">,</span><span class="none injected"> </span><span class="numeric_literal injected">2</span><span class="comma injected">,</span><span class="none injected"> </span><span class="numeric_literal injected">3</span><span class="bracket injected">]</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
 <span class="comment documentation">/// ```</span>
 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration public">mix_and_match</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
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 b44fc817c78..e457069e1f6 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
         <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>io<span class="colon">:</span><span class="colon">:</span>_print<span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>format_args_nl<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="brace">}</span><span class="parenthesis">)</span>
 <span class="brace">}</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute attribute">]</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">format_args</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute attribute">]</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">const_format_args</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute attribute">]</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">format_args_nl</span> <span class="brace">{</span><span class="brace">}</span>
 
 <span class="keyword">mod</span> <span class="module declaration">panic</span> <span class="brace">{</span>
@@ -77,12 +77,12 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="parenthesis attribute">(</span><span class="none attribute">std_panic</span><span class="parenthesis attribute">)</span><span class="attribute attribute">]</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="parenthesis attribute">(</span><span class="none attribute">std_panic</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">panic</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">assert</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">asm</span> <span class="brace">{</span><span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">toho</span> <span class="brace">{</span>
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 65dfbdf2119..04494283d5d 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
     <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function associated declaration reference unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">repr</span><span class="parenthesis attribute">(</span><span class="none attribute">packed</span><span class="parenthesis attribute">)</span><span class="attribute attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">repr</span><span class="parenthesis attribute">(</span><span class="none attribute">packed</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">struct</span> <span class="struct declaration">Packed</span> <span class="brace">{</span>
     <span class="field declaration">a</span><span class="colon">:</span> <span class="builtin_type">u16</span><span class="comma">,</span>
 <span class="brace">}</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 370f58080e6..b0fbbfda2a1 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
 <pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="brace">}</span><span class="semicolon">;</span>
 <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span><span class="brace">}</span>
 
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">allow</span><span class="parenthesis attribute">(</span><span class="parenthesis attribute">)</span><span class="attribute attribute">]</span>
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="module attribute crate_root library">proc_macros</span><span class="operator attribute">::</span><span class="macro attribute library">identity</span><span class="attribute attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">allow</span><span class="parenthesis attribute">(</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="module attribute crate_root library">proc_macros</span><span class="operator attribute">::</span><span class="attribute attribute library">identity</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration public">ops</span> <span class="brace">{</span>
-    <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">lang</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"fn_once"</span><span class="attribute attribute">]</span>
+    <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">lang</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"fn_once"</span><span class="attribute_bracket attribute">]</span>
     <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration public">FnOnce</span><span class="angle">&lt;</span><span class="type_param declaration">Args</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
 
-    <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">lang</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"fn_mut"</span><span class="attribute attribute">]</span>
+    <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">lang</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"fn_mut"</span><span class="attribute_bracket attribute">]</span>
     <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration public">FnMut</span><span class="angle">&lt;</span><span class="type_param declaration">Args</span><span class="angle">&gt;</span><span class="colon">:</span> <span class="trait public">FnOnce</span><span class="angle">&lt;</span><span class="type_param">Args</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
 
-    <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute library">lang</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"fn"</span><span class="attribute attribute">]</span>
+    <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">lang</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"fn"</span><span class="attribute_bracket attribute">]</span>
     <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration public">Fn</span><span class="angle">&lt;</span><span class="type_param declaration">Args</span><span class="angle">&gt;</span><span class="colon">:</span> <span class="trait public">FnMut</span><span class="angle">&lt;</span><span class="type_param">Args</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 
@@ -87,7 +87,7 @@ proc_macros::<span class="macro">mirror!</span> <span class="brace">{</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="macro attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="macro attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="brace">{</span>
     <span class="field declaration">x</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span>
 <span class="brace">}</span>
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs
index 8740db326b0..f09015efb60 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 1a10531a1bd..e53bf491743 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::BuiltinAttr, 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::BuiltinAttr, 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::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 b9032318ece..0daf1147882 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::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(
-                    CompletionItemKind::Attribute,
+                    SymbolKind::Derive,
                     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 05a29dd0ae2..e2477423a2d 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 c240912f023..805038091c7 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::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 b3f404d9053..4a6e034dc91 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,9 +231,11 @@ 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",
+                SymbolKind::Derive => "de",
                 SymbolKind::Enum => "en",
                 SymbolKind::Field => "fd",
                 SymbolKind::Function => "fn",
@@ -255,7 +256,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_completion/src/tests/attribute.rs b/crates/ide_completion/src/tests/attribute.rs
index 45979d4828c..8141fab299e 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 67f23536bd8..0d14c176b58 100644
--- a/crates/ide_db/src/lib.rs
+++ b/crates/ide_db/src/lib.rs
@@ -145,9 +145,11 @@ fn line_index(db: &dyn LineIndexDatabase, file_id: FileId) -> Arc<LineIndex> {
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub enum SymbolKind {
+    Attribute,
     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 8e1ccfb397b..1097a77afec 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"),
@@ -52,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 579ad22baca..f8c46b92fa8 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -50,7 +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 => 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,
@@ -100,7 +103,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,8 +110,10 @@ 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::Derive => lsp_types::CompletionItemKind::FUNCTION,
             SymbolKind::Enum => lsp_types::CompletionItemKind::ENUM,
             SymbolKind::Field => lsp_types::CompletionItemKind::FIELD,
             SymbolKind::Function => lsp_types::CompletionItemKind::FUNCTION,
@@ -117,7 +121,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 +472,8 @@ 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::Derive => semantic_tokens::DERIVE,
             SymbolKind::Module => lsp_types::SemanticTokenType::NAMESPACE,
             SymbolKind::Impl => semantic_tokens::TYPE_ALIAS,
             SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY,
@@ -504,7 +510,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,
diff --git a/editors/code/package.json b/editors/code/package.json
index 13b0867c251..26f21f73d45 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -1126,6 +1126,11 @@
                 "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",
                 "superType": "operator"
@@ -1180,6 +1185,11 @@
                 "description": "Style for const generics"
             },
             {
+                "id": "derive",
+                "description": "Style for derives",
+                "superType": "attribute"
+            },
+            {
                 "id": "dot",
                 "description": "Style for .",
                 "superType": "punctuation"