Repository: rust-analyzer/rust-analyzer
Pull request #6934 (2020-12-18 19:03:13)

Implement `cfg_attr` handling
Part of https://github.com/rust-analyzer/rust-analyzer/issues/5548


Patch:
diff --git a/crates/assists/src/handlers/generate_function.rs b/crates/assists/src/handlers/generate_function.rs
index f4cf155b63..758188a429 100644
--- a/crates/assists/src/handlers/generate_function.rs
+++ b/crates/assists/src/handlers/generate_function.rs
@@ -145,7 +145,7 @@ impl FunctionBuilder {
             self.type_params,
             self.params,
             fn_body,
-            Some(make::ret_type(make::ty_unit())),
+            Some(make::ret_type(make::ty("()"))),
         );
         let leading_ws;
         let trailing_ws;
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 9cd0b72aa9..1b9c64ee55 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -12,6 +12,7 @@ use syntax::{
     ast::{self, AstNode, AttrsOwner},
     match_ast, AstToken, SmolStr, SyntaxNode,
 };
+use test_utils::mark;
 use tt::Subtree;
 
 use crate::{
@@ -122,9 +123,69 @@ impl RawAttrs {
     }
 
     /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
-    pub(crate) fn filter(self, _db: &dyn DefDatabase, _krate: CrateId) -> Attrs {
-        // FIXME actually implement this
-        Attrs(self)
+    pub(crate) fn filter(self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
+        let has_cfg_attrs = self.iter().any(|attr| {
+            attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr])
+        });
+        if !has_cfg_attrs {
+            return Attrs(self);
+        }
+
+        let crate_graph = db.crate_graph();
+        let new_attrs = self
+            .iter()
+            .filter_map(|attr| {
+                let attr = attr.clone();
+                let is_cfg_attr =
+                    attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]);
+                if !is_cfg_attr {
+                    return Some(attr);
+                }
+
+                let subtree = match &attr.input {
+                    Some(AttrInput::TokenTree(it)) => it,
+                    _ => return Some(attr),
+                };
+
+                // Input subtree is: `(cfg, attr)`
+                // Split it up into a `cfg` and an `attr` subtree.
+                // FIXME: There should be a common API for this.
+                let mut saw_comma = false;
+                let (mut cfg, attr): (Vec<_>, Vec<_>) =
+                    subtree.clone().token_trees.into_iter().partition(|tree| {
+                        if saw_comma {
+                            return false;
+                        }
+
+                        match tree {
+                            tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
+                                saw_comma = true;
+                            }
+                            _ => {}
+                        }
+
+                        true
+                    });
+                cfg.pop(); // `,` ends up in here
+
+                let attr = Subtree { delimiter: None, token_trees: attr };
+                let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg };
+                let cfg = CfgExpr::parse(&cfg);
+
+                let cfg_options = &crate_graph[krate].cfg_options;
+                if cfg_options.check(&cfg) == Some(false) {
+                    None
+                } else {
+                    mark::hit!(cfg_attr_active);
+
+                    let attr = ast::Attr::parse(&format!("#[{}]", attr)).ok()?;
+                    let hygiene = Hygiene::new_unhygienic(); // FIXME
+                    Attr::from_src(attr, &hygiene)
+                }
+            })
+            .collect();
+
+        Attrs(RawAttrs { entries: Some(new_attrs) })
     }
 }
 
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index 7fb4caea36..77eeee3fe9 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -153,6 +153,7 @@ pub mod known {
         // Special names
         macro_rules,
         doc,
+        cfg_attr,
         // Components of known path (value or mod name)
         std,
         core,
diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs
index 60e0cd4add..8ad50a2ee5 100644
--- a/crates/ide/src/call_hierarchy.rs
+++ b/crates/ide/src/call_hierarchy.rs
@@ -181,8 +181,8 @@ fn caller() {
     call<|>ee();
 }
 "#,
-            "callee Function FileId(0) 0..14 3..9",
-            &["caller Function FileId(0) 15..44 18..24 : [33..39]"],
+            "callee FN FileId(0) 0..14 3..9",
+            &["caller FN FileId(0) 15..44 18..24 : [33..39]"],
             &[],
         );
     }
@@ -197,8 +197,8 @@ fn caller() {
     callee();
 }
 "#,
-            "callee Function FileId(0) 0..14 3..9",
-            &["caller Function FileId(0) 15..44 18..24 : [33..39]"],
+            "callee FN FileId(0) 0..14 3..9",
+            &["caller FN FileId(0) 15..44 18..24 : [33..39]"],
             &[],
         );
     }
@@ -214,8 +214,8 @@ fn caller() {
     callee();
 }
 "#,
-            "callee Function FileId(0) 0..14 3..9",
-            &["caller Function FileId(0) 15..58 18..24 : [33..39, 47..53]"],
+            "callee FN FileId(0) 0..14 3..9",
+            &["caller FN FileId(0) 15..58 18..24 : [33..39, 47..53]"],
             &[],
         );
     }
@@ -234,10 +234,10 @@ fn caller2() {
     callee();
 }
 "#,
-            "callee Function FileId(0) 0..14 3..9",
+            "callee FN FileId(0) 0..14 3..9",
             &[
-                "caller1 Function FileId(0) 15..45 18..25 : [34..40]",
-                "caller2 Function FileId(0) 47..77 50..57 : [66..72]",
+                "caller1 FN FileId(0) 15..45 18..25 : [34..40]",
+                "caller2 FN FileId(0) 47..77 50..57 : [66..72]",
             ],
             &[],
         );
@@ -263,10 +263,10 @@ mod tests {
     }
 }
 "#,
-            "callee Function FileId(0) 0..14 3..9",
+            "callee FN FileId(0) 0..14 3..9",
             &[
-                "caller1 Function FileId(0) 15..45 18..25 : [34..40]",
-                "test_caller Function FileId(0) 95..149 110..121 : [134..140]",
+                "caller1 FN FileId(0) 15..45 18..25 : [34..40]",
+                "test_caller FN FileId(0) 95..149 110..121 : [134..140]",
             ],
             &[],
         );
@@ -287,8 +287,8 @@ fn caller() {
 //- /foo/mod.rs
 pub fn callee() {}
 "#,
-            "callee Function FileId(1) 0..18 7..13",
-            &["caller Function FileId(0) 27..56 30..36 : [45..51]"],
+            "callee FN FileId(1) 0..18 7..13",
+            &["caller FN FileId(0) 27..56 30..36 : [45..51]"],
             &[],
         );
     }
@@ -304,9 +304,9 @@ fn call<|>er() {
     callee();
 }
 "#,
-            "caller Function FileId(0) 15..58 18..24",
+            "caller FN FileId(0) 15..58 18..24",
             &[],
-            &["callee Function FileId(0) 0..14 3..9 : [33..39, 47..53]"],
+            &["callee FN FileId(0) 0..14 3..9 : [33..39, 47..53]"],
         );
     }
 
@@ -325,9 +325,9 @@ fn call<|>er() {
 //- /foo/mod.rs
 pub fn callee() {}
 "#,
-            "caller Function FileId(0) 27..56 30..36",
+            "caller FN FileId(0) 27..56 30..36",
             &[],
-            &["callee Function FileId(1) 0..18 7..13 : [45..51]"],
+            &["callee FN FileId(1) 0..18 7..13 : [45..51]"],
         );
     }
 
@@ -348,9 +348,9 @@ fn caller3() {
 
 }
 "#,
-            "caller2 Function FileId(0) 33..64 36..43",
-            &["caller1 Function FileId(0) 0..31 3..10 : [19..26]"],
-            &["caller3 Function FileId(0) 66..83 69..76 : [52..59]"],
+            "caller2 FN FileId(0) 33..64 36..43",
+            &["caller1 FN FileId(0) 0..31 3..10 : [19..26]"],
+            &["caller3 FN FileId(0) 66..83 69..76 : [52..59]"],
         );
     }
 
@@ -368,9 +368,9 @@ fn main() {
     a<|>()
 }
 "#,
-            "a Function FileId(0) 0..18 3..4",
-            &["main Function FileId(0) 31..52 34..38 : [47..48]"],
-            &["b Function FileId(0) 20..29 23..24 : [13..14]"],
+            "a FN FileId(0) 0..18 3..4",
+            &["main FN FileId(0) 31..52 34..38 : [47..48]"],
+            &["b FN FileId(0) 20..29 23..24 : [13..14]"],
         );
 
         check_hierarchy(
@@ -385,8 +385,8 @@ fn main() {
     a()
 }
 "#,
-            "b Function FileId(0) 20..29 23..24",
-            &["a Function FileId(0) 0..18 3..4 : [13..14]"],
+            "b FN FileId(0) 20..29 23..24",
+            &["a FN FileId(0) 0..18 3..4 : [13..14]"],
             &[],
         );
     }
diff --git a/crates/ide/src/display.rs b/crates/ide/src/display.rs
index bae9e40dfa..0650915c53 100644
--- a/crates/ide/src/display.rs
+++ b/crates/ide/src/display.rs
@@ -1,9 +1,10 @@
 //! This module contains utilities for turning SyntaxNodes and HIR types
 //! into types that may be used to render in a UI.
 
-pub(crate) mod navigation_target;
+mod navigation_target;
 mod short_label;
 
+pub use navigation_target::NavigationTarget;
 pub(crate) use navigation_target::{ToNav, TryToNav};
 pub(crate) use short_label::ShortLabel;
 
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index cbdd4ecc2a..48acb8c934 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -1,50 +1,26 @@
 //! FIXME: write short doc here
 
-use std::fmt;
-
 use either::Either;
 use hir::{AssocItem, Documentation, FieldSource, HasAttrs, HasSource, InFile, ModuleSource};
-use ide_db::{
-    base_db::{FileId, SourceDatabase},
-    symbol_index::FileSymbolKind,
-};
+use ide_db::base_db::{FileId, SourceDatabase};
 use ide_db::{defs::Definition, RootDatabase};
 use syntax::{
     ast::{self, NameOwner},
-    match_ast, AstNode, SmolStr, TextRange,
+    match_ast, AstNode, SmolStr,
+    SyntaxKind::{self, IDENT_PAT, LIFETIME_PARAM, TYPE_PARAM},
+    TextRange,
 };
 
 use crate::FileSymbol;
 
 use super::short_label::ShortLabel;
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub enum SymbolKind {
-    Module,
-    Impl,
-    Field,
-    TypeParam,
-    LifetimeParam,
-    SelfParam,
-    Local,
-    Function,
-    Const,
-    Static,
-    Struct,
-    Enum,
-    Variant,
-    Union,
-    TypeAlias,
-    Trait,
-    Macro,
-}
-
 /// `NavigationTarget` represents and element in the editor's UI which you can
 /// click on to navigate to a particular piece of code.
 ///
 /// Typically, a `NavigationTarget` corresponds to some element in the source
 /// code, like a function or a struct, but this is not strictly required.
-#[derive(Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct NavigationTarget {
     pub file_id: FileId,
     /// Range which encompasses the whole element.
@@ -64,30 +40,12 @@ pub struct NavigationTarget {
     /// Clients should place the cursor on this range when navigating to this target.
     pub focus_range: Option<TextRange>,
     pub name: SmolStr,
-    pub kind: Option<SymbolKind>,
+    pub kind: SyntaxKind,
     pub container_name: Option<SmolStr>,
     pub description: Option<String>,
     pub docs: Option<Documentation>,
 }
 
-impl fmt::Debug for NavigationTarget {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut f = f.debug_struct("NavigationTarget");
-        macro_rules! opt {
-            ($($name:ident)*) => {$(
-                if let Some(it) = &self.$name {
-                    f.field(stringify!($name), it);
-                }
-            )*}
-        }
-        f.field("file_id", &self.file_id).field("full_range", &self.full_range);
-        opt!(focus_range);
-        f.field("name", &self.name);
-        opt!(kind container_name description docs);
-        f.finish()
-    }
-}
-
 pub(crate) trait ToNav {
     fn to_nav(&self, db: &RootDatabase) -> NavigationTarget;
 }
@@ -111,7 +69,7 @@ impl NavigationTarget {
                 name,
                 None,
                 frange.range,
-                SymbolKind::Module,
+                src.value.syntax().kind(),
             );
             res.docs = module.attrs(db).docs();
             res.description = src.value.short_label();
@@ -128,13 +86,8 @@ impl NavigationTarget {
 
     #[cfg(test)]
     pub(crate) fn debug_render(&self) -> String {
-        let mut buf = format!(
-            "{} {:?} {:?} {:?}",
-            self.name,
-            self.kind.unwrap(),
-            self.file_id,
-            self.full_range
-        );
+        let mut buf =
+            format!("{} {:?} {:?} {:?}", self.name, self.kind, self.file_id, self.full_range);
         if let Some(focus_range) = self.focus_range {
             buf.push_str(&format!(" {:?}", focus_range))
         }
@@ -148,7 +101,6 @@ impl NavigationTarget {
     pub(crate) fn from_named(
         db: &RootDatabase,
         node: InFile<&dyn ast::NameOwner>,
-        kind: SymbolKind,
     ) -> NavigationTarget {
         let name =
             node.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_"));
@@ -156,7 +108,13 @@ impl NavigationTarget {
             node.value.name().map(|it| node.with_value(it.syntax()).original_file_range(db).range);
         let frange = node.map(|it| it.syntax()).original_file_range(db);
 
-        NavigationTarget::from_syntax(frange.file_id, name, focus_range, frange.range, kind)
+        NavigationTarget::from_syntax(
+            frange.file_id,
+            name,
+            focus_range,
+            frange.range,
+            node.value.syntax().kind(),
+        )
     }
 
     fn from_syntax(
@@ -164,12 +122,12 @@ impl NavigationTarget {
         name: SmolStr,
         focus_range: Option<TextRange>,
         full_range: TextRange,
-        kind: SymbolKind,
+        kind: SyntaxKind,
     ) -> NavigationTarget {
         NavigationTarget {
             file_id,
             name,
-            kind: Some(kind),
+            kind,
             full_range,
             focus_range,
             container_name: None,
@@ -184,17 +142,7 @@ impl ToNav for FileSymbol {
         NavigationTarget {
             file_id: self.file_id,
             name: self.name.clone(),
-            kind: Some(match self.kind {
-                FileSymbolKind::Function => SymbolKind::Function,
-                FileSymbolKind::Struct => SymbolKind::Struct,
-                FileSymbolKind::Enum => SymbolKind::Enum,
-                FileSymbolKind::Trait => SymbolKind::Trait,
-                FileSymbolKind::Module => SymbolKind::Module,
-                FileSymbolKind::TypeAlias => SymbolKind::TypeAlias,
-                FileSymbolKind::Const => SymbolKind::Const,
-                FileSymbolKind::Static => SymbolKind::Static,
-                FileSymbolKind::Macro => SymbolKind::Macro,
-            }),
+            kind: self.kind,
             full_range: self.range,
             focus_range: self.name_range,
             container_name: self.container_name.clone(),
@@ -243,36 +191,16 @@ impl TryToNav for hir::ModuleDef {
     }
 }
 
-pub(crate) trait ToNavFromAst {
-    const KIND: SymbolKind;
-}
-impl ToNavFromAst for hir::Function {
-    const KIND: SymbolKind = SymbolKind::Function;
-}
-impl ToNavFromAst for hir::Const {
-    const KIND: SymbolKind = SymbolKind::Const;
-}
-impl ToNavFromAst for hir::Static {
-    const KIND: SymbolKind = SymbolKind::Static;
-}
-impl ToNavFromAst for hir::Struct {
-    const KIND: SymbolKind = SymbolKind::Struct;
-}
-impl ToNavFromAst for hir::Enum {
-    const KIND: SymbolKind = SymbolKind::Enum;
-}
-impl ToNavFromAst for hir::EnumVariant {
-    const KIND: SymbolKind = SymbolKind::Variant;
-}
-impl ToNavFromAst for hir::Union {
-    const KIND: SymbolKind = SymbolKind::Union;
-}
-impl ToNavFromAst for hir::TypeAlias {
-    const KIND: SymbolKind = SymbolKind::TypeAlias;
-}
-impl ToNavFromAst for hir::Trait {
-    const KIND: SymbolKind = SymbolKind::Trait;
-}
+pub(crate) trait ToNavFromAst {}
+impl ToNavFromAst for hir::Function {}
+impl ToNavFromAst for hir::Const {}
+impl ToNavFromAst for hir::Static {}
+impl ToNavFromAst for hir::Struct {}
+impl ToNavFromAst for hir::Enum {}
+impl ToNavFromAst for hir::EnumVariant {}
+impl ToNavFromAst for hir::Union {}
+impl ToNavFromAst for hir::TypeAlias {}
+impl ToNavFromAst for hir::Trait {}
 
 impl<D> ToNav for D
 where
@@ -281,11 +209,8 @@ where
 {
     fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
         let src = self.source(db);
-        let mut res = NavigationTarget::from_named(
-            db,
-            src.as_ref().map(|it| it as &dyn ast::NameOwner),
-            D::KIND,
-        );
+        let mut res =
+            NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner));
         res.docs = self.docs(db);
         res.description = src.value.short_label();
         res
@@ -303,7 +228,7 @@ impl ToNav for hir::Module {
             }
         };
         let frange = src.with_value(syntax).original_file_range(db);
-        NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, SymbolKind::Module)
+        NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, syntax.kind())
     }
 }
 
@@ -327,7 +252,7 @@ impl ToNav for hir::Impl {
             "impl".into(),
             focus_range,
             frange.range,
-            SymbolKind::Impl,
+            src.value.syntax().kind(),
         )
     }
 }
@@ -338,8 +263,7 @@ impl ToNav for hir::Field {
 
         match &src.value {
             FieldSource::Named(it) => {
-                let mut res =
-                    NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field);
+                let mut res = NavigationTarget::from_named(db, src.with_value(it));
                 res.docs = self.docs(db);
                 res.description = it.short_label();
                 res
@@ -351,7 +275,7 @@ impl ToNav for hir::Field {
                     "".into(),
                     None,
                     frange.range,
-                    SymbolKind::Field,
+                    it.syntax().kind(),
                 )
             }
         }
@@ -362,11 +286,8 @@ impl ToNav for hir::MacroDef {
     fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
         let src = self.source(db);
         log::debug!("nav target {:#?}", src.value.syntax());
-        let mut res = NavigationTarget::from_named(
-            db,
-            src.as_ref().map(|it| it as &dyn ast::NameOwner),
-            SymbolKind::Macro,
-        );
+        let mut res =
+            NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner));
         res.docs = self.docs(db);
         res
     }
@@ -409,7 +330,7 @@ impl ToNav for hir::Local {
         NavigationTarget {
             file_id: full_range.file_id,
             name,
-            kind: Some(SymbolKind::Local),
+            kind: IDENT_PAT,
             full_range: full_range.range,
             focus_range: None,
             container_name: None,
@@ -433,7 +354,7 @@ impl ToNav for hir::TypeParam {
         NavigationTarget {
             file_id: src.file_id.original_file(db),
             name: self.name(db).to_string().into(),
-            kind: Some(SymbolKind::TypeParam),
+            kind: TYPE_PARAM,
             full_range,
             focus_range,
             container_name: None,
@@ -450,7 +371,7 @@ impl ToNav for hir::LifetimeParam {
         NavigationTarget {
             file_id: src.file_id.original_file(db),
             name: self.name(db).to_string().into(),
-            kind: Some(SymbolKind::LifetimeParam),
+            kind: LIFETIME_PARAM,
             full_range,
             focus_range: Some(full_range),
             container_name: None,
@@ -507,21 +428,34 @@ fn foo() { enum FooInner { } }
                         0,
                     ),
                     full_range: 0..17,
-                    focus_range: 5..13,
+                    focus_range: Some(
+                        5..13,
+                    ),
                     name: "FooInner",
-                    kind: Enum,
-                    description: "enum FooInner",
+                    kind: ENUM,
+                    container_name: None,
+                    description: Some(
+                        "enum FooInner",
+                    ),
+                    docs: None,
                 },
                 NavigationTarget {
                     file_id: FileId(
                         0,
                     ),
                     full_range: 29..46,
-                    focus_range: 34..42,
+                    focus_range: Some(
+                        34..42,
+                    ),
                     name: "FooInner",
-                    kind: Enum,
-                    container_name: "foo",
-                    description: "enum FooInner",
+                    kind: ENUM,
+                    container_name: Some(
+                        "foo",
+                    ),
+                    description: Some(
+                        "enum FooInner",
+                    ),
+                    docs: None,
                 },
             ]
         "#]]
diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs
index 32556dad33..c515313914 100644
--- a/crates/ide/src/file_structure.rs
+++ b/crates/ide/src/file_structure.rs
@@ -1,17 +1,15 @@
 use syntax::{
     ast::{self, AttrsOwner, GenericParamsOwner, NameOwner},
-    match_ast, AstNode, SourceFile, SyntaxNode, TextRange, WalkEvent,
+    match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, WalkEvent,
 };
 
-use crate::SymbolKind;
-
 #[derive(Debug, Clone)]
 pub struct StructureNode {
     pub parent: Option<usize>,
     pub label: String,
     pub navigation_range: TextRange,
     pub node_range: TextRange,
-    pub kind: SymbolKind,
+    pub kind: SyntaxKind,
     pub detail: Option<String>,
     pub deprecated: bool,
 }
@@ -53,27 +51,25 @@ pub(crate) fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
 }
 
 fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
-    fn decl<N: NameOwner + AttrsOwner>(node: N, kind: SymbolKind) -> Option<StructureNode> {
-        decl_with_detail(&node, None, kind)
+    fn decl<N: NameOwner + AttrsOwner>(node: N) -> Option<StructureNode> {
+        decl_with_detail(&node, None)
     }
 
     fn decl_with_type_ref<N: NameOwner + AttrsOwner>(
         node: &N,
         type_ref: Option<ast::Type>,
-        kind: SymbolKind,
     ) -> Option<StructureNode> {
         let detail = type_ref.map(|type_ref| {
             let mut detail = String::new();
             collapse_ws(type_ref.syntax(), &mut detail);
             detail
         });
-        decl_with_detail(node, detail, kind)
+        decl_with_detail(node, detail)
     }
 
     fn decl_with_detail<N: NameOwner + AttrsOwner>(
         node: &N,
         detail: Option<String>,
-        kind: SymbolKind,
     ) -> Option<StructureNode> {
         let name = node.name()?;
 
@@ -82,7 +78,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
             label: name.text().to_string(),
             navigation_range: name.syntax().text_range(),
             node_range: node.syntax().text_range(),
-            kind,
+            kind: node.syntax().kind(),
             detail,
             deprecated: node.attrs().filter_map(|x| x.simple_name()).any(|x| x == "deprecated"),
         })
@@ -121,18 +117,18 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
                     collapse_ws(ret_type.syntax(), &mut detail);
                 }
 
-                decl_with_detail(&it, Some(detail), SymbolKind::Function)
+                decl_with_detail(&it, Some(detail))
             },
-            ast::Struct(it) => decl(it, SymbolKind::Struct),
-            ast::Union(it) => decl(it, SymbolKind::Union),
-            ast::Enum(it) => decl(it, SymbolKind::Enum),
-            ast::Variant(it) => decl(it, SymbolKind::Variant),
-            ast::Trait(it) => decl(it, SymbolKind::Trait),
-            ast::Module(it) => decl(it, SymbolKind::Module),
-            ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::TypeAlias),
-            ast::RecordField(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Field),
-            ast::Const(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Const),
-            ast::Static(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Static),
+            ast::Struct(it) => decl(it),
+            ast::Union(it) => decl(it),
+            ast::Enum(it) => decl(it),
+            ast::Variant(it) => decl(it),
+            ast::Trait(it) => decl(it),
+            ast::Module(it) => decl(it),
+            ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty()),
+            ast::RecordField(it) => decl_with_type_ref(&it, it.ty()),
+            ast::Const(it) => decl_with_type_ref(&it, it.ty()),
+            ast::Static(it) => decl_with_type_ref(&it, it.ty()),
             ast::Impl(it) => {
                 let target_type = it.self_ty()?;
                 let target_trait = it.trait_();
@@ -148,13 +144,13 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
                     label,
                     navigation_range: target_type.syntax().text_range(),
                     node_range: it.syntax().text_range(),
-                    kind: SymbolKind::Impl,
+                    kind: it.syntax().kind(),
                     detail: None,
                     deprecated: false,
                 };
                 Some(node)
             },
-            ast::MacroRules(it) => decl(it, SymbolKind::Macro),
+            ast::MacroRules(it) => decl(it),
             _ => None,
         }
     }
@@ -226,7 +222,7 @@ fn very_obsolete() {}
                         label: "Foo",
                         navigation_range: 8..11,
                         node_range: 1..26,
-                        kind: Struct,
+                        kind: STRUCT,
                         detail: None,
                         deprecated: false,
                     },
@@ -237,7 +233,7 @@ fn very_obsolete() {}
                         label: "x",
                         navigation_range: 18..19,
                         node_range: 18..24,
-                        kind: Field,
+                        kind: RECORD_FIELD,
                         detail: Some(
                             "i32",
                         ),
@@ -248,7 +244,7 @@ fn very_obsolete() {}
                         label: "m",
                         navigation_range: 32..33,
                         node_range: 28..158,
-                        kind: Module,
+                        kind: MODULE,
                         detail: None,
                         deprecated: false,
                     },
@@ -259,7 +255,7 @@ fn very_obsolete() {}
                         label: "bar1",
                         navigation_range: 43..47,
                         node_range: 40..52,
-                        kind: Function,
+                        kind: FN,
                         detail: Some(
                             "fn()",
                         ),
@@ -272,7 +268,7 @@ fn very_obsolete() {}
                         label: "bar2",
                         navigation_range: 60..64,
                         node_range: 57..81,
-                        kind: Function,
+                        kind: FN,
                         detail: Some(
                             "fn<T>(t: T) -> T",
                         ),
@@ -285,7 +281,7 @@ fn very_obsolete() {}
                         label: "bar3",
                         navigation_range: 89..93,
                         node_range: 86..156,
-                        kind: Function,
+                        kind: FN,
                         detail: Some(
                             "fn<A, B>(a: A, b: B) -> Vec< u32 >",
                         ),
@@ -296,7 +292,7 @@ fn very_obsolete() {}
                         label: "E",
                         navigation_range: 165..166,
                         node_range: 160..180,
-                        kind: Enum,
+                        kind: ENUM,
                         detail: None,
                         deprecated: false,
                     },
@@ -307,7 +303,7 @@ fn very_obsolete() {}
                         label: "X",
                         navigation_range: 169..170,
                         node_range: 169..170,
-                        kind: Variant,
+                        kind: VARIANT,
                         detail: None,
                         deprecated: false,
                     },
@@ -318,7 +314,7 @@ fn very_obsolete() {}
                         label: "Y",
                         navigation_range: 172..173,
                         node_range: 172..178,
-                        kind: Variant,
+                        kind: VARIANT,
                         detail: None,
                         deprecated: false,
                     },
@@ -327,7 +323,7 @@ fn very_obsolete() {}
                         label: "T",
                         navigation_range: 186..187,
                         node_range: 181..193,
-                        kind: TypeAlias,
+                        kind: TYPE_ALIAS,
                         detail: Some(
                             "()",
                         ),
@@ -338,7 +334,7 @@ fn very_obsolete() {}
                         label: "S",
                         navigation_range: 201..202,
                         node_range: 194..213,
-                        kind: Static,
+                        kind: STATIC,
                         detail: Some(
                             "i32",
                         ),
@@ -349,7 +345,7 @@ fn very_obsolete() {}
                         label: "C",
                         navigation_range: 220..221,
                         node_range: 214..232,
-                        kind: Const,
+                        kind: CONST,
                         detail: Some(
                             "i32",
                         ),
@@ -360,7 +356,7 @@ fn very_obsolete() {}
                         label: "impl E",
                         navigation_range: 239..240,
                         node_range: 234..243,
-                        kind: Impl,
+                        kind: IMPL,
                         detail: None,
                         deprecated: false,
                     },
@@ -369,7 +365,7 @@ fn very_obsolete() {}
                         label: "impl fmt::Debug for E",
                         navigation_range: 265..266,
                         node_range: 245..269,
-                        kind: Impl,
+                        kind: IMPL,
                         detail: None,
                         deprecated: false,
                     },
@@ -378,7 +374,7 @@ fn very_obsolete() {}
                         label: "mc",
                         navigation_range: 284..286,
                         node_range: 271..303,
-                        kind: Macro,
+                        kind: MACRO_RULES,
                         detail: None,
                         deprecated: false,
                     },
@@ -387,7 +383,7 @@ fn very_obsolete() {}
                         label: "mcexp",
                         navigation_range: 334..339,
                         node_range: 305..356,
-                        kind: Macro,
+                        kind: MACRO_RULES,
                         detail: None,
                         deprecated: false,
                     },
@@ -396,7 +392,7 @@ fn very_obsolete() {}
                         label: "mcexp",
                         navigation_range: 387..392,
                         node_range: 358..409,
-                        kind: Macro,
+                        kind: MACRO_RULES,
                         detail: None,
                         deprecated: false,
                     },
@@ -405,7 +401,7 @@ fn very_obsolete() {}
                         label: "obsolete",
                         navigation_range: 428..436,
                         node_range: 411..441,
-                        kind: Function,
+                        kind: FN,
                         detail: Some(
                             "fn()",
                         ),
@@ -416,7 +412,7 @@ fn very_obsolete() {}
                         label: "very_obsolete",
                         navigation_range: 481..494,
                         node_range: 443..499,
-                        kind: Function,
+                        kind: FN,
                         detail: Some(
                             "fn()",
                         ),
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 7a12e99652..173509b08b 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -9,7 +9,7 @@ use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset,
 
 use crate::{
     display::{ToNav, TryToNav},
-    FilePosition, NavigationTarget, RangeInfo, SymbolKind,
+    FilePosition, NavigationTarget, RangeInfo,
 };
 
 // Feature: Go to Definition
@@ -86,7 +86,7 @@ fn self_to_nav_target(self_param: ast::SelfParam, file_id: FileId) -> Option<Nav
         full_range: self_param.syntax().text_range(),
         focus_range: Some(self_token.text_range()),
         name: self_token.text().clone(),
-        kind: Some(SymbolKind::SelfParam),
+        kind: self_token.kind(),
         container_name: None,
         description: None,
         docs: None,
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index b06fa5f155..da6bb726ab 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -2187,9 +2187,14 @@ fn foo_<|>test() {}
                                     0,
                                 ),
                                 full_range: 0..24,
-                                focus_range: 11..19,
+                                focus_range: Some(
+                                    11..19,
+                                ),
                                 name: "foo_test",
-                                kind: Function,
+                                kind: FN,
+                                container_name: None,
+                                description: None,
+                                docs: None,
                             },
                             kind: Test {
                                 test_id: Path(
@@ -2225,9 +2230,14 @@ mod tests<|> {
                                     0,
                                 ),
                                 full_range: 0..46,
-                                focus_range: 4..9,
+                                focus_range: Some(
+                                    4..9,
+                                ),
                                 name: "tests",
-                                kind: Module,
+                                kind: MODULE,
+                                container_name: None,
+                                description: None,
+                                docs: None,
                             },
                             kind: TestMod {
                                 path: "tests",
@@ -2259,10 +2269,16 @@ fn main() { let s<|>t = S{ f1:0 }; }
                                         0,
                                     ),
                                     full_range: 0..19,
-                                    focus_range: 7..8,
+                                    focus_range: Some(
+                                        7..8,
+                                    ),
                                     name: "S",
-                                    kind: Struct,
-                                    description: "struct S",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct S",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2292,10 +2308,16 @@ fn main() { let s<|>t = S{ f1:Arg(0) }; }
                                         0,
                                     ),
                                     full_range: 17..37,
-                                    focus_range: 24..25,
+                                    focus_range: Some(
+                                        24..25,
+                                    ),
                                     name: "S",
-                                    kind: Struct,
-                                    description: "struct S",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct S",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2305,10 +2327,16 @@ fn main() { let s<|>t = S{ f1:Arg(0) }; }
                                         0,
                                     ),
                                     full_range: 0..16,
-                                    focus_range: 7..10,
+                                    focus_range: Some(
+                                        7..10,
+                                    ),
                                     name: "Arg",
-                                    kind: Struct,
-                                    description: "struct Arg",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct Arg",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2338,10 +2366,16 @@ fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
                                         0,
                                     ),
                                     full_range: 17..37,
-                                    focus_range: 24..25,
+                                    focus_range: Some(
+                                        24..25,
+                                    ),
                                     name: "S",
-                                    kind: Struct,
-                                    description: "struct S",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct S",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2351,10 +2385,16 @@ fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
                                         0,
                                     ),
                                     full_range: 0..16,
-                                    focus_range: 7..10,
+                                    focus_range: Some(
+                                        7..10,
+                                    ),
                                     name: "Arg",
-                                    kind: Struct,
-                                    description: "struct Arg",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct Arg",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2387,10 +2427,16 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
                                         0,
                                     ),
                                     full_range: 0..14,
-                                    focus_range: 7..8,
+                                    focus_range: Some(
+                                        7..8,
+                                    ),
                                     name: "A",
-                                    kind: Struct,
-                                    description: "struct A",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct A",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2400,10 +2446,16 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
                                         0,
                                     ),
                                     full_range: 15..29,
-                                    focus_range: 22..23,
+                                    focus_range: Some(
+                                        22..23,
+                                    ),
                                     name: "B",
-                                    kind: Struct,
-                                    description: "struct B",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct B",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2413,10 +2465,16 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
                                         0,
                                     ),
                                     full_range: 42..60,
-                                    focus_range: 53..54,
+                                    focus_range: Some(
+                                        53..54,
+                                    ),
                                     name: "C",
-                                    kind: Struct,
-                                    description: "pub struct C",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "pub struct C",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2446,10 +2504,16 @@ fn main() { let s<|>t = foo(); }
                                         0,
                                     ),
                                     full_range: 0..12,
-                                    focus_range: 6..9,
+                                    focus_range: Some(
+                                        6..9,
+                                    ),
                                     name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Foo",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2480,10 +2544,16 @@ fn main() { let s<|>t = foo(); }
                                         0,
                                     ),
                                     full_range: 0..15,
-                                    focus_range: 6..9,
+                                    focus_range: Some(
+                                        6..9,
+                                    ),
                                     name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Foo",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2493,10 +2563,16 @@ fn main() { let s<|>t = foo(); }
                                         0,
                                     ),
                                     full_range: 16..25,
-                                    focus_range: 23..24,
+                                    focus_range: Some(
+                                        23..24,
+                                    ),
                                     name: "S",
-                                    kind: Struct,
-                                    description: "struct S",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct S",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2527,10 +2603,16 @@ fn main() { let s<|>t = foo(); }
                                         0,
                                     ),
                                     full_range: 0..12,
-                                    focus_range: 6..9,
+                                    focus_range: Some(
+                                        6..9,
+                                    ),
                                     name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Foo",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2540,10 +2622,16 @@ fn main() { let s<|>t = foo(); }
                                         0,
                                     ),
                                     full_range: 13..25,
-                                    focus_range: 19..22,
+                                    focus_range: Some(
+                                        19..22,
+                                    ),
                                     name: "Bar",
-                                    kind: Trait,
-                                    description: "trait Bar",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Bar",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2577,10 +2665,16 @@ fn main() { let s<|>t = foo(); }
                                         0,
                                     ),
                                     full_range: 0..15,
-                                    focus_range: 6..9,
+                                    focus_range: Some(
+                                        6..9,
+                                    ),
                                     name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Foo",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2590,10 +2684,16 @@ fn main() { let s<|>t = foo(); }
                                         0,
                                     ),
                                     full_range: 16..31,
-                                    focus_range: 22..25,
+                                    focus_range: Some(
+                                        22..25,
+                                    ),
                                     name: "Bar",
-                                    kind: Trait,
-                                    description: "trait Bar",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Bar",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2603,10 +2703,16 @@ fn main() { let s<|>t = foo(); }
                                         0,
                                     ),
                                     full_range: 32..44,
-                                    focus_range: 39..41,
+                                    focus_range: Some(
+                                        39..41,
+                                    ),
                                     name: "S1",
-                                    kind: Struct,
-                                    description: "struct S1",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct S1",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2616,10 +2722,16 @@ fn main() { let s<|>t = foo(); }
                                         0,
                                     ),
                                     full_range: 45..57,
-                                    focus_range: 52..54,
+                                    focus_range: Some(
+                                        52..54,
+                                    ),
                                     name: "S2",
-                                    kind: Struct,
-                                    description: "struct S2",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct S2",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2647,10 +2759,16 @@ fn foo(ar<|>g: &impl Foo) {}
                                         0,
                                     ),
                                     full_range: 0..12,
-                                    focus_range: 6..9,
+                                    focus_range: Some(
+                                        6..9,
+                                    ),
                                     name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Foo",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2681,10 +2799,16 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
                                         0,
                                     ),
                                     full_range: 0..12,
-                                    focus_range: 6..9,
+                                    focus_range: Some(
+                                        6..9,
+                                    ),
                                     name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Foo",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2694,10 +2818,16 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
                                         0,
                                     ),
                                     full_range: 13..28,
-                                    focus_range: 19..22,
+                                    focus_range: Some(
+                                        19..22,
+                                    ),
                                     name: "Bar",
-                                    kind: Trait,
-                                    description: "trait Bar",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Bar",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2707,10 +2837,16 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
                                         0,
                                     ),
                                     full_range: 29..39,
-                                    focus_range: 36..37,
+                                    focus_range: Some(
+                                        36..37,
+                                    ),
                                     name: "S",
-                                    kind: Struct,
-                                    description: "struct S",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct S",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2746,10 +2882,16 @@ mod future {
                                         0,
                                     ),
                                     full_range: 101..163,
-                                    focus_range: 140..146,
+                                    focus_range: Some(
+                                        140..146,
+                                    ),
                                     name: "Future",
-                                    kind: Trait,
-                                    description: "pub trait Future",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "pub trait Future",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2759,10 +2901,16 @@ mod future {
                                         0,
                                     ),
                                     full_range: 0..9,
-                                    focus_range: 7..8,
+                                    focus_range: Some(
+                                        7..8,
+                                    ),
                                     name: "S",
-                                    kind: Struct,
-                                    description: "struct S",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct S",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2791,10 +2939,16 @@ fn foo(ar<|>g: &impl Foo<S>) {}
                                         0,
                                     ),
                                     full_range: 0..15,
-                                    focus_range: 6..9,
+                                    focus_range: Some(
+                                        6..9,
+                                    ),
                                     name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Foo",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2804,10 +2958,16 @@ fn foo(ar<|>g: &impl Foo<S>) {}
                                         0,
                                     ),
                                     full_range: 16..27,
-                                    focus_range: 23..24,
+                                    focus_range: Some(
+                                        23..24,
+                                    ),
                                     name: "S",
-                                    kind: Struct,
-                                    description: "struct S",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct S",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2841,10 +3001,16 @@ fn main() { let s<|>t = foo(); }
                                         0,
                                     ),
                                     full_range: 42..55,
-                                    focus_range: 49..50,
+                                    focus_range: Some(
+                                        49..50,
+                                    ),
                                     name: "B",
-                                    kind: Struct,
-                                    description: "struct B",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct B",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2854,10 +3020,16 @@ fn main() { let s<|>t = foo(); }
                                         0,
                                     ),
                                     full_range: 0..12,
-                                    focus_range: 6..9,
+                                    focus_range: Some(
+                                        6..9,
+                                    ),
                                     name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Foo",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2885,10 +3057,16 @@ fn foo(ar<|>g: &dyn Foo) {}
                                         0,
                                     ),
                                     full_range: 0..12,
-                                    focus_range: 6..9,
+                                    focus_range: Some(
+                                        6..9,
+                                    ),
                                     name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Foo",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2917,10 +3095,16 @@ fn foo(ar<|>g: &dyn Foo<S>) {}
                                         0,
                                     ),
                                     full_range: 0..15,
-                                    focus_range: 6..9,
+                                    focus_range: Some(
+                                        6..9,
+                                    ),
                                     name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Foo",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2930,10 +3114,16 @@ fn foo(ar<|>g: &dyn Foo<S>) {}
                                         0,
                                     ),
                                     full_range: 16..27,
-                                    focus_range: 23..24,
+                                    focus_range: Some(
+                                        23..24,
+                                    ),
                                     name: "S",
-                                    kind: Struct,
-                                    description: "struct S",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct S",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -2965,10 +3155,16 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                                         0,
                                     ),
                                     full_range: 0..21,
-                                    focus_range: 6..15,
+                                    focus_range: Some(
+                                        6..15,
+                                    ),
                                     name: "ImplTrait",
-                                    kind: Trait,
-                                    description: "trait ImplTrait",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait ImplTrait",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2978,10 +3174,16 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                                         0,
                                     ),
                                     full_range: 43..57,
-                                    focus_range: 50..51,
+                                    focus_range: Some(
+                                        50..51,
+                                    ),
                                     name: "B",
-                                    kind: Struct,
-                                    description: "struct B",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct B",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -2991,10 +3193,16 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                                         0,
                                     ),
                                     full_range: 22..42,
-                                    focus_range: 28..36,
+                                    focus_range: Some(
+                                        28..36,
+                                    ),
                                     name: "DynTrait",
-                                    kind: Trait,
-                                    description: "trait DynTrait",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait DynTrait",
+                                    ),
+                                    docs: None,
                                 },
                             },
                             HoverGotoTypeData {
@@ -3004,10 +3212,16 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                                         0,
                                     ),
                                     full_range: 58..69,
-                                    focus_range: 65..66,
+                                    focus_range: Some(
+                                        65..66,
+                                    ),
                                     name: "S",
-                                    kind: Struct,
-                                    description: "struct S",
+                                    kind: STRUCT,
+                                    container_name: None,
+                                    description: Some(
+                                        "struct S",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
@@ -3046,10 +3260,16 @@ fn main() { let s<|>t = test().get(); }
                                         0,
                                     ),
                                     full_range: 0..62,
-                                    focus_range: 6..9,
+                                    focus_range: Some(
+                                        6..9,
+                                    ),
                                     name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
+                                    kind: TRAIT,
+                                    container_name: None,
+                                    description: Some(
+                                        "trait Foo",
+                                    ),
+                                    docs: None,
                                 },
                             },
                         ],
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index dbad9a84f6..c5c652cda4 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -57,14 +57,14 @@ use ide_db::{
     symbol_index::{self, FileSymbol},
     LineIndexDatabase,
 };
-use syntax::SourceFile;
+use syntax::{SourceFile, TextRange, TextSize};
 
 use crate::display::ToNav;
 
 pub use crate::{
     call_hierarchy::CallItem,
     diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity},
-    display::navigation_target::{NavigationTarget, SymbolKind},
+    display::NavigationTarget,
     expand_macro::ExpandedMacro,
     file_structure::StructureNode,
     folding_ranges::{Fold, FoldKind},
@@ -79,20 +79,21 @@ pub use crate::{
         HighlightedRange,
     },
 };
-pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist};
 pub use completion::{
     CompletionConfig, CompletionItem, CompletionItemKind, CompletionResolveCapability,
     CompletionScore, ImportEdit, InsertTextFormat,
 };
+pub use ide_db::{
+    call_info::CallInfo,
+    search::{Reference, ReferenceAccess, ReferenceKind},
+};
+
+pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist};
 pub use hir::{Documentation, Semantics};
 pub use ide_db::base_db::{
     Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot,
     SourceRootId,
 };
-pub use ide_db::{
-    call_info::CallInfo,
-    search::{Reference, ReferenceAccess, ReferenceKind},
-};
 pub use ide_db::{
     label::Label,
     line_index::{LineCol, LineIndex},
@@ -102,7 +103,6 @@ pub use ide_db::{
     RootDatabase,
 };
 pub use ssr::SsrError;
-pub use syntax::{TextRange, TextSize};
 pub use text_edit::{Indel, TextEdit};
 
 pub type Cancelable<T> = Result<T, Canceled>;
diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs
index be344a09b3..6cc3b2991c 100644
--- a/crates/ide/src/parent_module.rs
+++ b/crates/ide/src/parent_module.rs
@@ -78,7 +78,7 @@ mod tests {
             ",
         );
         let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
-        nav.assert_match("foo Module FileId(0) 0..8");
+        nav.assert_match("foo MODULE FileId(0) 0..8");
     }
 
     #[test]
@@ -97,7 +97,7 @@ mod tests {
             ",
         );
         let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
-        nav.assert_match("foo Module FileId(0) 0..8");
+        nav.assert_match("foo MODULE FileId(0) 0..8");
     }
 
     #[test]
@@ -113,7 +113,7 @@ mod tests {
             ",
         );
         let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
-        nav.assert_match("baz Module FileId(0) 32..44");
+        nav.assert_match("baz MODULE FileId(0) 32..44");
     }
 
     #[test]
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 8c00a71058..98190a86b2 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -24,7 +24,7 @@ use syntax::{
     match_ast, AstNode, SyntaxKind, SyntaxNode, TextRange, TokenAtOffset,
 };
 
-use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, SymbolKind};
+use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo};
 
 #[derive(Debug, Clone)]
 pub struct ReferenceSearchResult {
@@ -278,7 +278,7 @@ fn try_find_self_references(
             full_range: self_param.syntax().text_range(),
             focus_range: Some(param_self_token.text_range()),
             name: param_self_token.text().clone(),
-            kind: Some(SymbolKind::SelfParam),
+            kind: param_self_token.kind(),
             container_name: None,
             description: None,
             docs: None,
@@ -343,7 +343,7 @@ fn main() {
 }
 "#,
             expect![[r#"
-                Foo Struct FileId(0) 0..26 7..10 Other
+                Foo STRUCT FileId(0) 0..26 7..10 Other
 
                 FileId(0) 101..104 StructLiteral
             "#]],
@@ -361,7 +361,7 @@ struct Foo<|> {}
 }
 "#,
             expect![[r#"
-                Foo Struct FileId(0) 0..13 7..10 Other
+                Foo STRUCT FileId(0) 0..13 7..10 Other
 
                 FileId(0) 41..44 Other
                 FileId(0) 54..57 StructLiteral
@@ -380,7 +380,7 @@ struct Foo<T> <|>{}
 }
 "#,
             expect![[r#"
-                Foo Struct FileId(0) 0..16 7..10 Other
+                Foo STRUCT FileId(0) 0..16 7..10 Other
 
                 FileId(0) 64..67 StructLiteral
             "#]],
@@ -399,7 +399,7 @@ fn main() {
 }
 "#,
             expect![[r#"
-                Foo Struct FileId(0) 0..16 7..10 Other
+                Foo STRUCT FileId(0) 0..16 7..10 Other
 
                 FileId(0) 54..57 StructLiteral
             "#]],
@@ -420,7 +420,7 @@ fn main() {
 }
 "#,
             expect![[r#"
-                Foo Enum FileId(0) 0..26 5..8 Other
+                Foo ENUM FileId(0) 0..26 5..8 Other
 
                 FileId(0) 63..66 EnumLiteral
             "#]],
@@ -441,7 +441,7 @@ fn main() {
 }
 "#,
             expect![[r#"
-                Foo Enum FileId(0) 0..26 5..8 Other
+                Foo ENUM FileId(0) 0..26 5..8 Other
 
                 FileId(0) 50..53 Other
                 FileId(0) 63..66 EnumLiteral
@@ -463,7 +463,7 @@ fn main() {
 }
 "#,
             expect![[r#"
-                Foo Enum FileId(0) 0..32 5..8 Other
+                Foo ENUM FileId(0) 0..32 5..8 Other
 
                 FileId(0) 73..76 EnumLiteral
             "#]],
@@ -484,7 +484,7 @@ fn main() {
 }
 "#,
             expect![[r#"
-                Foo Enum FileId(0) 0..33 5..8 Other
+                Foo ENUM FileId(0) 0..33 5..8 Other
 
                 FileId(0) 70..73 EnumLiteral
             "#]],
@@ -507,7 +507,7 @@ fn main() {
     i = 5;
 }"#,
             expect![[r#"
-                i Local FileId(0) 24..25 Other Write
+                i IDENT_PAT FileId(0) 24..25 Other Write
 
                 FileId(0) 50..51 Other Write
                 FileId(0) 54..55 Other Read
@@ -531,7 +531,7 @@ fn bar() {
 }
 "#,
             expect![[r#"
-                spam Local FileId(0) 19..23 Other
+                spam IDENT_PAT FileId(0) 19..23 Other
 
                 FileId(0) 34..38 Other Read
                 FileId(0) 41..45 Other Read
@@ -546,7 +546,7 @@ fn bar() {
 fn foo(i : u32) -> u32 { i<|> }
 "#,
             expect![[r#"
-                i Local FileId(0) 7..8 Other
+                i IDENT_PAT FileId(0) 7..8 Other
 
                 FileId(0) 25..26 Other Read
             "#]],
@@ -560,7 +560,7 @@ fn foo(i : u32) -> u32 { i<|> }
 fn foo(i<|> : u32) -> u32 { i }
 "#,
             expect![[r#"
-                i Local FileId(0) 7..8 Other
+                i IDENT_PAT FileId(0) 7..8 Other
 
                 FileId(0) 25..26 Other Read
             "#]],
@@ -581,7 +581,7 @@ fn main(s: Foo) {
 }
 "#,
             expect![[r#"
-                spam Field FileId(0) 17..30 21..25 Other
+                spam RECORD_FIELD FileId(0) 17..30 21..25 Other
 
                 FileId(0) 67..71 Other Read
             "#]],
@@ -598,7 +598,7 @@ impl Foo {
 }
 "#,
             expect![[r#"
-                f Function FileId(0) 27..43 30..31 Other
+                f FN FileId(0) 27..43 30..31 Other
 
             "#]],
         );
@@ -615,7 +615,7 @@ enum Foo {
 }
 "#,
             expect![[r#"
-                B Variant FileId(0) 22..23 22..23 Other
+                B VARIANT FileId(0) 22..23 22..23 Other
 
             "#]],
         );
@@ -632,7 +632,7 @@ enum Foo {
 }
 "#,
             expect![[r#"
-                field Field FileId(0) 26..35 26..31 Other
+                field RECORD_FIELD FileId(0) 26..35 26..31 Other
 
             "#]],
         );
@@ -673,7 +673,7 @@ fn f() {
 }
 "#,
             expect![[r#"
-                Foo Struct FileId(1) 17..51 28..31 Other
+                Foo STRUCT FileId(1) 17..51 28..31 Other
 
                 FileId(0) 53..56 StructLiteral
                 FileId(2) 79..82 StructLiteral
@@ -703,7 +703,7 @@ pub struct Foo {
 }
 "#,
             expect![[r#"
-                foo Module FileId(1) 0..35 Other
+                foo SOURCE_FILE FileId(1) 0..35 Other
 
                 FileId(0) 14..17 Other
             "#]],
@@ -731,7 +731,7 @@ pub(super) struct Foo<|> {
 }
 "#,
             expect![[r#"
-                Foo Struct FileId(2) 0..41 18..21 Other
+                Foo STRUCT FileId(2) 0..41 18..21 Other
 
                 FileId(1) 20..23 Other
                 FileId(1) 47..50 StructLiteral
@@ -759,7 +759,7 @@ pub(super) struct Foo<|> {
             code,
             None,
             expect![[r#"
-                quux Function FileId(0) 19..35 26..30 Other
+                quux FN FileId(0) 19..35 26..30 Other
 
                 FileId(1) 16..20 StructLiteral
                 FileId(2) 16..20 StructLiteral
@@ -770,7 +770,7 @@ pub(super) struct Foo<|> {
             code,
             Some(SearchScope::single_file(FileId(2))),
             expect![[r#"
-                quux Function FileId(0) 19..35 26..30 Other
+                quux FN FileId(0) 19..35 26..30 Other
 
                 FileId(2) 16..20 StructLiteral
             "#]],
@@ -790,7 +790,7 @@ fn foo() {
 }
 "#,
             expect![[r#"
-                m1 Macro FileId(0) 0..46 29..31 Other
+                m1 MACRO_RULES FileId(0) 0..46 29..31 Other
 
                 FileId(0) 63..65 StructLiteral
                 FileId(0) 73..75 StructLiteral
@@ -808,7 +808,7 @@ fn foo() {
 }
 "#,
             expect![[r#"
-                i Local FileId(0) 23..24 Other Write
+                i IDENT_PAT FileId(0) 23..24 Other Write
 
                 FileId(0) 34..35 Other Write
                 FileId(0) 38..39 Other Read
@@ -830,7 +830,7 @@ fn foo() {
 }
 "#,
             expect![[r#"
-                f Field FileId(0) 15..21 15..16 Other
+                f RECORD_FIELD FileId(0) 15..21 15..16 Other
 
                 FileId(0) 55..56 RecordFieldExprOrPat Read
                 FileId(0) 68..69 Other Write
@@ -848,7 +848,7 @@ fn foo() {
 }
 "#,
             expect![[r#"
-                i Local FileId(0) 19..20 Other
+                i IDENT_PAT FileId(0) 19..20 Other
 
                 FileId(0) 26..27 Other Write
             "#]],
@@ -872,7 +872,7 @@ fn main() {
 }
 "#,
             expect![[r#"
-                new Function FileId(0) 54..81 61..64 Other
+                new FN FileId(0) 54..81 61..64 Other
 
                 FileId(0) 126..129 StructLiteral
             "#]],
@@ -894,7 +894,7 @@ use crate::f;
 fn g() { f(); }
 "#,
             expect![[r#"
-                f Function FileId(0) 22..31 25..26 Other
+                f FN FileId(0) 22..31 25..26 Other
 
                 FileId(1) 11..12 Other
                 FileId(1) 24..25 StructLiteral
@@ -917,7 +917,7 @@ fn f(s: S) {
 }
 "#,
             expect![[r#"
-                field Field FileId(0) 15..24 15..20 Other
+                field RECORD_FIELD FileId(0) 15..24 15..20 Other
 
                 FileId(0) 68..73 FieldShorthandForField Read
             "#]],
@@ -941,7 +941,7 @@ fn f(e: En) {
 }
 "#,
             expect![[r#"
-                field Field FileId(0) 32..41 32..37 Other
+                field RECORD_FIELD FileId(0) 32..41 32..37 Other
 
                 FileId(0) 102..107 FieldShorthandForField Read
             "#]],
@@ -965,7 +965,7 @@ fn f() -> m::En {
 }
 "#,
             expect![[r#"
-                field Field FileId(0) 56..65 56..61 Other
+                field RECORD_FIELD FileId(0) 56..65 56..61 Other
 
                 FileId(0) 125..130 RecordFieldExprOrPat Read
             "#]],
@@ -990,7 +990,7 @@ impl Foo {
 }
 "#,
             expect![[r#"
-                self SelfParam FileId(0) 47..51 47..51 SelfKw Read
+                self SELF_KW FileId(0) 47..51 47..51 SelfKw Read
 
                 FileId(0) 71..75 SelfKw Read
                 FileId(0) 152..156 SelfKw Read
@@ -1038,7 +1038,7 @@ fn foo<'a, 'b: 'a>(x: &'a<|> ()) -> &'a () where &'a (): Foo<'a> {
 }
 "#,
             expect![[r#"
-                'a LifetimeParam FileId(0) 55..57 55..57 Lifetime
+                'a LIFETIME_PARAM FileId(0) 55..57 55..57 Lifetime
 
                 FileId(0) 63..65 Lifetime
                 FileId(0) 71..73 Lifetime
@@ -1056,7 +1056,7 @@ fn foo<'a, 'b: 'a>(x: &'a<|> ()) -> &'a () where &'a (): Foo<'a> {
 type Foo<'a, T> where T: 'a<|> = &'a T;
 "#,
             expect![[r#"
-                'a LifetimeParam FileId(0) 9..11 9..11 Lifetime
+                'a LIFETIME_PARAM FileId(0) 9..11 9..11 Lifetime
 
                 FileId(0) 25..27 Lifetime
                 FileId(0) 31..33 Lifetime
@@ -1078,7 +1078,7 @@ impl<'a> Foo<'a> for &'a () {
 }
 "#,
             expect![[r#"
-                'a LifetimeParam FileId(0) 47..49 47..49 Lifetime
+                'a LIFETIME_PARAM FileId(0) 47..49 47..49 Lifetime
 
                 FileId(0) 55..57 Lifetime
                 FileId(0) 64..66 Lifetime
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index ff386be804..2f465c1951 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -12,7 +12,7 @@ use syntax::{
 
 use crate::{
     display::{ToNav, TryToNav},
-    FileId, NavigationTarget, SymbolKind,
+    FileId, NavigationTarget,
 };
 
 #[derive(Debug, Clone)]
@@ -137,11 +137,7 @@ fn runnable_fn(sema: &Semantics<RootDatabase>, func: ast::Fn, file_id: FileId) -
         }
     };
 
-    let nav = NavigationTarget::from_named(
-        sema.db,
-        InFile::new(file_id.into(), &func),
-        SymbolKind::Function,
-    );
+    let nav = NavigationTarget::from_named(sema.db, InFile::new(file_id.into(), &func));
     let cfg = def.attrs(sema.db).cfg();
     Some(Runnable { nav, kind, cfg })
 }
@@ -208,7 +204,7 @@ fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Op
     nav.focus_range = None;
     nav.description = None;
     nav.docs = None;
-    nav.kind = None;
+    nav.kind = syntax::SyntaxKind::COMMENT;
     let res = Runnable { nav, kind: RunnableKind::DocTest { test_id }, cfg: attrs.cfg() };
     Some(res)
 }
@@ -352,9 +348,14 @@ fn bench() {}
                                 0,
                             ),
                             full_range: 1..13,
-                            focus_range: 4..8,
+                            focus_range: Some(
+                                4..8,
+                            ),
                             name: "main",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Bin,
                         cfg: None,
@@ -365,9 +366,14 @@ fn bench() {}
                                 0,
                             ),
                             full_range: 15..39,
-                            focus_range: 26..34,
+                            focus_range: Some(
+                                26..34,
+                            ),
                             name: "test_foo",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Test {
                             test_id: Path(
@@ -385,9 +391,14 @@ fn bench() {}
                                 0,
                             ),
                             full_range: 41..75,
-                            focus_range: 62..70,
+                            focus_range: Some(
+                                62..70,
+                            ),
                             name: "test_foo",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Test {
                             test_id: Path(
@@ -405,9 +416,14 @@ fn bench() {}
                                 0,
                             ),
                             full_range: 77..99,
-                            focus_range: 89..94,
+                            focus_range: Some(
+                                89..94,
+                            ),
                             name: "bench",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Bench {
                             test_id: Path(
@@ -497,9 +513,14 @@ struct StructWithRunnable(String);
                                 0,
                             ),
                             full_range: 1..13,
-                            focus_range: 4..8,
+                            focus_range: Some(
+                                4..8,
+                            ),
                             name: "main",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Bin,
                         cfg: None,
@@ -510,7 +531,12 @@ struct StructWithRunnable(String);
                                 0,
                             ),
                             full_range: 15..74,
+                            focus_range: None,
                             name: "should_have_runnable",
+                            kind: COMMENT,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: DocTest {
                             test_id: Path(
@@ -525,7 +551,12 @@ struct StructWithRunnable(String);
                                 0,
                             ),
                             full_range: 76..148,
+                            focus_range: None,
                             name: "should_have_runnable_1",
+                            kind: COMMENT,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: DocTest {
                             test_id: Path(
@@ -540,7 +571,12 @@ struct StructWithRunnable(String);
                                 0,
                             ),
                             full_range: 150..254,
+                            focus_range: None,
                             name: "should_have_runnable_2",
+                            kind: COMMENT,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: DocTest {
                             test_id: Path(
@@ -555,7 +591,12 @@ struct StructWithRunnable(String);
                                 0,
                             ),
                             full_range: 756..821,
+                            focus_range: None,
                             name: "StructWithRunnable",
+                            kind: COMMENT,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: DocTest {
                             test_id: Path(
@@ -594,9 +635,14 @@ impl Data {
                                 0,
                             ),
                             full_range: 1..13,
-                            focus_range: 4..8,
+                            focus_range: Some(
+                                4..8,
+                            ),
                             name: "main",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Bin,
                         cfg: None,
@@ -607,7 +653,12 @@ impl Data {
                                 0,
                             ),
                             full_range: 44..98,
+                            focus_range: None,
                             name: "foo",
+                            kind: COMMENT,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: DocTest {
                             test_id: Path(
@@ -641,9 +692,14 @@ mod test_mod {
                                 0,
                             ),
                             full_range: 1..51,
-                            focus_range: 5..13,
+                            focus_range: Some(
+                                5..13,
+                            ),
                             name: "test_mod",
-                            kind: Module,
+                            kind: MODULE,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: TestMod {
                             path: "test_mod",
@@ -656,9 +712,14 @@ mod test_mod {
                                 0,
                             ),
                             full_range: 20..49,
-                            focus_range: 35..44,
+                            focus_range: Some(
+                                35..44,
+                            ),
                             name: "test_foo1",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Test {
                             test_id: Path(
@@ -711,9 +772,14 @@ mod root_tests {
                                 0,
                             ),
                             full_range: 22..323,
-                            focus_range: 26..40,
+                            focus_range: Some(
+                                26..40,
+                            ),
                             name: "nested_tests_0",
-                            kind: Module,
+                            kind: MODULE,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: TestMod {
                             path: "root_tests::nested_tests_0",
@@ -726,9 +792,14 @@ mod root_tests {
                                 0,
                             ),
                             full_range: 51..192,
-                            focus_range: 55..69,
+                            focus_range: Some(
+                                55..69,
+                            ),
                             name: "nested_tests_1",
-                            kind: Module,
+                            kind: MODULE,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: TestMod {
                             path: "root_tests::nested_tests_0::nested_tests_1",
@@ -741,9 +812,14 @@ mod root_tests {
                                 0,
                             ),
                             full_range: 84..126,
-                            focus_range: 107..121,
+                            focus_range: Some(
+                                107..121,
+                            ),
                             name: "nested_test_11",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Test {
                             test_id: Path(
@@ -761,9 +837,14 @@ mod root_tests {
                                 0,
                             ),
                             full_range: 140..182,
-                            focus_range: 163..177,
+                            focus_range: Some(
+                                163..177,
+                            ),
                             name: "nested_test_12",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Test {
                             test_id: Path(
@@ -781,9 +862,14 @@ mod root_tests {
                                 0,
                             ),
                             full_range: 202..286,
-                            focus_range: 206..220,
+                            focus_range: Some(
+                                206..220,
+                            ),
                             name: "nested_tests_2",
-                            kind: Module,
+                            kind: MODULE,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: TestMod {
                             path: "root_tests::nested_tests_0::nested_tests_2",
@@ -796,9 +882,14 @@ mod root_tests {
                                 0,
                             ),
                             full_range: 235..276,
-                            focus_range: 258..271,
+                            focus_range: Some(
+                                258..271,
+                            ),
                             name: "nested_test_2",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Test {
                             test_id: Path(
@@ -834,9 +925,14 @@ fn test_foo1() {}
                                 0,
                             ),
                             full_range: 1..50,
-                            focus_range: 36..45,
+                            focus_range: Some(
+                                36..45,
+                            ),
                             name: "test_foo1",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Test {
                             test_id: Path(
@@ -879,9 +975,14 @@ fn test_foo1() {}
                                 0,
                             ),
                             full_range: 1..72,
-                            focus_range: 58..67,
+                            focus_range: Some(
+                                58..67,
+                            ),
                             name: "test_foo1",
-                            kind: Function,
+                            kind: FN,
+                            container_name: None,
+                            description: None,
+                            docs: None,
                         },
                         kind: Test {
                             test_id: Path(
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs
index 0aa6a07651..ca455fa03e 100644
--- a/crates/ide_db/src/symbol_index.rs
+++ b/crates/ide_db/src/symbol_index.rs
@@ -39,7 +39,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
 use syntax::{
     ast::{self, NameOwner},
     match_ast, AstNode, Parse, SmolStr, SourceFile,
-    SyntaxKind::*,
+    SyntaxKind::{self, *},
     SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent,
 };
 
@@ -323,7 +323,7 @@ impl Query {
                 let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value);
 
                 for symbol in &symbol_index.symbols[start..end] {
-                    if self.only_types && !symbol.kind.is_type() {
+                    if self.only_types && !is_type(symbol.kind) {
                         continue;
                     }
                     if self.exact && symbol.name != self.query {
@@ -341,44 +341,23 @@ impl Query {
     }
 }
 
+fn is_type(kind: SyntaxKind) -> bool {
+    matches!(kind, STRUCT | ENUM | TRAIT | TYPE_ALIAS)
+}
+
 /// The actual data that is stored in the index. It should be as compact as
 /// possible.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct FileSymbol {
     pub file_id: FileId,
     pub name: SmolStr,
-    pub kind: FileSymbolKind,
+    pub kind: SyntaxKind,
     pub range: TextRange,
     pub ptr: SyntaxNodePtr,
     pub name_range: Option<TextRange>,
     pub container_name: Option<SmolStr>,
 }
 
-#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
-pub enum FileSymbolKind {
-    Function,
-    Struct,
-    Enum,
-    Trait,
-    Module,
-    TypeAlias,
-    Const,
-    Static,
-    Macro,
-}
-
-impl FileSymbolKind {
-    fn is_type(self: FileSymbolKind) -> bool {
-        matches!(
-            self,
-            FileSymbolKind::Struct
-                | FileSymbolKind::Enum
-                | FileSymbolKind::Trait
-                | FileSymbolKind::TypeAlias
-        )
-    }
-}
-
 fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec<FileSymbol> {
     let mut symbols = Vec::new();
     let mut stack = Vec::new();
@@ -433,18 +412,7 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
 fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> {
     to_symbol(node).map(move |(name, ptr, name_range)| FileSymbol {
         name,
-        kind: match node.kind() {
-            FN => FileSymbolKind::Function,
-            STRUCT => FileSymbolKind::Struct,
-            ENUM => FileSymbolKind::Enum,
-            TRAIT => FileSymbolKind::Trait,
-            MODULE => FileSymbolKind::Module,
-            TYPE_ALIAS => FileSymbolKind::TypeAlias,
-            CONST => FileSymbolKind::Const,
-            STATIC => FileSymbolKind::Static,
-            MACRO_RULES => FileSymbolKind::Macro,
-            kind => unreachable!("{:?}", kind),
-        },
+        kind: node.kind(),
         range: node.text_range(),
         ptr,
         file_id,
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs
index 23039eba49..1a078f6b4c 100644
--- a/crates/parser/src/grammar.rs
+++ b/crates/parser/src/grammar.rs
@@ -133,6 +133,10 @@ pub(crate) mod fragments {
 
         m.complete(p, MACRO_STMTS);
     }
+
+    pub(crate) fn attr(p: &mut Parser) {
+        attributes::outer_attrs(p)
+    }
 }
 
 pub(crate) fn reparser(
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index 41e62116f8..ab8e4c70e8 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -99,6 +99,8 @@ pub enum FragmentKind {
     // FIXME: use separate fragment kinds for macro inputs and outputs?
     Items,
     Statements,
+
+    Attr,
 }
 
 pub fn parse_fragment(
@@ -118,6 +120,7 @@ pub fn parse_fragment(
         FragmentKind::Statement => grammar::fragments::stmt,
         FragmentKind::Items => grammar::fragments::macro_items,
         FragmentKind::Statements => grammar::fragments::macro_stmts,
+        FragmentKind::Attr => grammar::fragments::attr,
     };
     parse_from_tokens(token_source, tree_sink, parser)
 }
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 66f8bee991..af226c1090 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -9,7 +9,7 @@ use std::{
 
 use ide::{
     CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData,
-    NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, SymbolKind, TextEdit,
+    NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit,
 };
 use itertools::Itertools;
 use lsp_server::ErrorCode;
@@ -27,7 +27,7 @@ use project_model::TargetKind;
 use serde::{Deserialize, Serialize};
 use serde_json::to_value;
 use stdx::{format_to, split_once};
-use syntax::{algo, ast, AstNode, TextRange, TextSize};
+use syntax::{algo, ast, AstNode, SyntaxKind, TextRange, TextSize};
 
 use crate::{
     cargo_target_spec::CargoTargetSpec,
@@ -385,10 +385,7 @@ pub(crate) fn handle_workspace_symbol(
             #[allow(deprecated)]
             let info = SymbolInformation {
                 name: nav.name.to_string(),
-                kind: nav
-                    .kind
-                    .map(to_proto::symbol_kind)
-                    .unwrap_or(lsp_types::SymbolKind::Variable),
+                kind: to_proto::symbol_kind(nav.kind),
                 tags: None,
                 location: to_proto::location_from_nav(snap, nav)?,
                 container_name,
@@ -1040,10 +1037,10 @@ pub(crate) fn handle_code_lens(
                 .filter(|it| {
                     matches!(
                         it.kind,
-                        SymbolKind::Trait
-                            | SymbolKind::Struct
-                            | SymbolKind::Enum
-                            | SymbolKind::Union
+                        SyntaxKind::TRAIT
+                            | SyntaxKind::STRUCT
+                            | SyntaxKind::ENUM
+                            | SyntaxKind::UNION
                     )
                 })
                 .map(|it| {
@@ -1266,7 +1263,7 @@ pub(crate) fn handle_call_hierarchy_prepare(
     let RangeInfo { range: _, info: navs } = nav_info;
     let res = navs
         .into_iter()
-        .filter(|it| it.kind == Some(SymbolKind::Function))
+        .filter(|it| it.kind == SyntaxKind::FN)
         .map(|it| to_proto::call_hierarchy_item(&snap, it))
         .collect::<Result<Vec<_>>>()?;
 
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 6b2302803a..72f77a016c 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -5,13 +5,14 @@ use std::{
 };
 
 use ide::{
-    Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, FileId,
-    FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag,
-    HighlightedRange, Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup,
-    NavigationTarget, ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange,
-    SourceFileEdit, SymbolKind, TextEdit, TextRange, TextSize,
+    Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation,
+    FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, HighlightedRange,
+    Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget,
+    ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit,
 };
+use ide_db::base_db::{FileId, FileRange};
 use itertools::Itertools;
+use syntax::{SyntaxKind, TextRange, TextSize};
 
 use crate::{
     cargo_target_spec::CargoTargetSpec, global_state::GlobalStateSnapshot,
@@ -29,24 +30,21 @@ pub(crate) fn range(line_index: &LineIndex, range: TextRange) -> lsp_types::Rang
     lsp_types::Range::new(start, end)
 }
 
-pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
-    match symbol_kind {
-        SymbolKind::Function => lsp_types::SymbolKind::Function,
-        SymbolKind::Struct => lsp_types::SymbolKind::Struct,
-        SymbolKind::Enum => lsp_types::SymbolKind::Enum,
-        SymbolKind::Variant => lsp_types::SymbolKind::EnumMember,
-        SymbolKind::Trait => lsp_types::SymbolKind::Interface,
-        SymbolKind::Macro => lsp_types::SymbolKind::Function,
-        SymbolKind::Module => lsp_types::SymbolKind::Module,
-        SymbolKind::TypeAlias | SymbolKind::TypeParam => lsp_types::SymbolKind::TypeParameter,
-        SymbolKind::Field => lsp_types::SymbolKind::Field,
-        SymbolKind::Static => lsp_types::SymbolKind::Constant,
-        SymbolKind::Const => lsp_types::SymbolKind::Constant,
-        SymbolKind::Impl => lsp_types::SymbolKind::Object,
-        SymbolKind::Local | SymbolKind::SelfParam | SymbolKind::LifetimeParam => {
-            lsp_types::SymbolKind::Variable
-        }
-        SymbolKind::Union => lsp_types::SymbolKind::Struct,
+pub(crate) fn symbol_kind(syntax_kind: SyntaxKind) -> lsp_types::SymbolKind {
+    match syntax_kind {
+        SyntaxKind::FN => lsp_types::SymbolKind::Function,
+        SyntaxKind::STRUCT => lsp_types::SymbolKind::Struct,
+        SyntaxKind::ENUM => lsp_types::SymbolKind::Enum,
+        SyntaxKind::VARIANT => lsp_types::SymbolKind::EnumMember,
+        SyntaxKind::TRAIT => lsp_types::SymbolKind::Interface,
+        SyntaxKind::MACRO_CALL => lsp_types::SymbolKind::Function,
+        SyntaxKind::MODULE => lsp_types::SymbolKind::Module,
+        SyntaxKind::TYPE_ALIAS => lsp_types::SymbolKind::TypeParameter,
+        SyntaxKind::RECORD_FIELD => lsp_types::SymbolKind::Field,
+        SyntaxKind::STATIC => lsp_types::SymbolKind::Constant,
+        SyntaxKind::CONST => lsp_types::SymbolKind::Constant,
+        SyntaxKind::IMPL => lsp_types::SymbolKind::Object,
+        _ => lsp_types::SymbolKind::Variable,
     }
 }
 
@@ -721,7 +719,7 @@ pub(crate) fn call_hierarchy_item(
 ) -> Result<lsp_types::CallHierarchyItem> {
     let name = target.name.to_string();
     let detail = target.description.clone();
-    let kind = target.kind.map(symbol_kind).unwrap_or(lsp_types::SymbolKind::Function);
+    let kind = symbol_kind(target.kind);
     let (uri, range, selection_range) = location_info(snap, target)?;
     Ok(lsp_types::CallHierarchyItem {
         name,
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index ba7e5d2fb1..16b079c42a 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -20,9 +20,6 @@ pub fn name_ref(text: &str) -> ast::NameRef {
 pub fn ty(text: &str) -> ast::Type {
     ast_from_text(&format!("impl {} for D {{}};", text))
 }
-pub fn ty_unit() -> ast::Type {
-    ty("()")
-}
 
 pub fn assoc_item_list() -> ast::AssocItemList {
     ast_from_text("impl C for D {};")
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index e753b11bb8..4d272f367a 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -205,6 +205,13 @@ impl ast::Type {
     }
 }
 
+impl ast::Attr {
+    /// Returns `text`, parsed as an attribute, but only if it has no errors.
+    pub fn parse(text: &str) -> Result<Self, ()> {
+        parsing::parse_text_fragment(text, parser::FragmentKind::Attr)
+    }
+}
+
 /// Matches a `SyntaxNode` against an `ast` type.
 ///
 /// # Example:
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 191960960a..2f3dde8acd 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -132,7 +132,6 @@ async function tryActivate(context: vscode.ExtensionContext) {
     ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config));
 
     activateInlayHints(ctx);
-    warnAboutRustLangExtensionConflict();
 
     vscode.workspace.onDidChangeConfiguration(
         _ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }),
@@ -400,13 +399,3 @@ async function queryForGithubToken(state: PersistentState): Promise<void> {
         await state.updateGithubToken(newToken);
     }
 }
-
-function warnAboutRustLangExtensionConflict() {
-    const rustLangExt = vscode.extensions.getExtension("rust-lang.rust");
-    if (rustLangExt !== undefined) {
-        vscode.window.showWarningMessage(
-            "You have both rust-analyzer (matklad.rust-analyzer) and Rust (rust-lang.rust) " +
-            "plugins enabled. These are known to conflict and cause various functions of " +
-            "both plugins to not work correctly. You should disable one of them.", "Got it");
-    };
-}


Test patch:
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index 1a7b988318..58d69d3c6b 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -1,4 +1,5 @@
 use base_db::fixture::WithFixture;
+use test_utils::mark;
 
 use crate::test_db::TestDB;
 
@@ -119,3 +120,20 @@ fn inactive_item() {
         "#,
     );
 }
+
+/// Tests that `cfg` attributes behind `cfg_attr` is handled properly.
+#[test]
+fn inactive_via_cfg_attr() {
+    mark::check!(cfg_attr_active);
+    check_diagnostics(
+        r#"
+        //- /lib.rs
+          #[cfg_attr(not(never), cfg(no))] fn f() {}
+        //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled
+
+          #[cfg_attr(not(never), cfg(not(no)))] fn f() {}
+
+          #[cfg_attr(never, cfg(no))] fn g() {}
+        "#,
+    );
+}