about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicolas Guichard <nicolas.guichard@kdab.com>2023-12-08 16:48:42 +0100
committerNicolas Guichard <nicolas.guichard@kdab.com>2024-01-03 13:05:36 +0100
commit73d9c77f2aeed394cf131dce55807be2d3f54064 (patch)
treef99ad5bce366eb09d39d93e1f539eb32bf5d81d4
parent566bb77f915d6c0b89f9db4aaf15e958bd6eb404 (diff)
downloadrust-73d9c77f2aeed394cf131dce55807be2d3f54064.tar.gz
rust-73d9c77f2aeed394cf131dce55807be2d3f54064.zip
scip: Populate SymbolInformation::kind
SymbolInformation::kind is finer-grained than the SCIP symbol suffix.
This also fixes a bug where all type aliases where treated like type
parameters.

```
trait SomeTrait {
  type AssociatedType; // ← this is SomeTrait#[AssociatedType]
}

type MyTypeAlias = u8; // ← this used to be [MyTypeAlias]
                       //   and now is MyTypeAlias#
```
-rw-r--r--crates/ide-db/src/defs.rs8
-rw-r--r--crates/ide/src/lib.rs5
-rw-r--r--crates/ide/src/moniker.rs246
-rw-r--r--crates/ide/src/static_index.rs4
-rw-r--r--crates/rust-analyzer/src/cli/scip.rs60
5 files changed, 248 insertions, 75 deletions
diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index 14c0f420ac5..410b8304592 100644
--- a/crates/ide-db/src/defs.rs
+++ b/crates/ide-db/src/defs.rs
@@ -10,7 +10,7 @@ use hir::{
     Adt, AsAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType, Const, Crate,
     DefWithBody, DeriveHelper, DocLinkDef, ExternCrateDecl, Field, Function, GenericParam,
     HasVisibility, HirDisplay, Impl, Label, Local, Macro, Module, ModuleDef, Name, PathResolution,
-    Semantics, Static, ToolModule, Trait, TraitAlias, TypeAlias, Variant, Visibility,
+    Semantics, Static, ToolModule, Trait, TraitAlias, TypeAlias, Variant, VariantDef, Visibility,
 };
 use stdx::{format_to, impl_from};
 use syntax::{
@@ -791,6 +791,12 @@ impl From<DocLinkDef> for Definition {
     }
 }
 
+impl From<VariantDef> for Definition {
+    fn from(def: VariantDef) -> Self {
+        ModuleDef::from(def).into()
+    }
+}
+
 impl TryFrom<DefWithBody> for Definition {
     type Error = ();
     fn try_from(def: DefWithBody) -> Result<Self, Self::Error> {
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 6ff16b9e2f7..e5da1a24c84 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -99,7 +99,10 @@ pub use crate::{
     },
     join_lines::JoinLinesConfig,
     markup::Markup,
-    moniker::{MonikerDescriptorKind, MonikerKind, MonikerResult, PackageInformation},
+    moniker::{
+        MonikerDescriptorKind, MonikerKind, MonikerResult, PackageInformation,
+        SymbolInformationKind,
+    },
     move_item::Direction,
     navigation_target::{NavigationTarget, UpmappingResult},
     prime_caches::ParallelPrimeCachesProgress,
diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs
index 8e8bb5e0139..94ddd162de4 100644
--- a/crates/ide/src/moniker.rs
+++ b/crates/ide/src/moniker.rs
@@ -1,7 +1,7 @@
 //! This module generates [moniker](https://microsoft.github.io/language-server-protocol/specifications/lsif/0.6.0/specification/#exportsImports)
 //! for LSIF and LSP.
 
-use hir::{AsAssocItem, AssocItemContainer, Crate, DescendPreference, Semantics};
+use hir::{Adt, AsAssocItem, AssocItemContainer, Crate, DescendPreference, MacroKind, Semantics};
 use ide_db::{
     base_db::{CrateOrigin, FilePosition, LangCrateOrigin},
     defs::{Definition, IdentClass},
@@ -25,6 +25,62 @@ pub enum MonikerDescriptorKind {
     Meta,
 }
 
+// Subset of scip_types::SymbolInformation::Kind
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum SymbolInformationKind {
+    AssociatedType,
+    Attribute,
+    Constant,
+    Enum,
+    EnumMember,
+    Field,
+    Function,
+    Macro,
+    Method,
+    Module,
+    Parameter,
+    SelfParameter,
+    StaticMethod,
+    StaticVariable,
+    Struct,
+    Trait,
+    TraitMethod,
+    Type,
+    TypeAlias,
+    TypeParameter,
+    Union,
+    Variable,
+}
+
+impl From<SymbolInformationKind> for MonikerDescriptorKind {
+    fn from(value: SymbolInformationKind) -> Self {
+        match value {
+            SymbolInformationKind::AssociatedType => Self::TypeParameter,
+            SymbolInformationKind::Attribute => Self::Macro,
+            SymbolInformationKind::Constant => Self::Term,
+            SymbolInformationKind::Enum => Self::Type,
+            SymbolInformationKind::EnumMember => Self::Type,
+            SymbolInformationKind::Field => Self::Term,
+            SymbolInformationKind::Function => Self::Method,
+            SymbolInformationKind::Macro => Self::Macro,
+            SymbolInformationKind::Method => Self::Method,
+            SymbolInformationKind::Module => Self::Namespace,
+            SymbolInformationKind::Parameter => Self::Parameter,
+            SymbolInformationKind::SelfParameter => Self::Parameter,
+            SymbolInformationKind::StaticMethod => Self::Method,
+            SymbolInformationKind::StaticVariable => Self::Meta,
+            SymbolInformationKind::Struct => Self::Type,
+            SymbolInformationKind::Trait => Self::Type,
+            SymbolInformationKind::TraitMethod => Self::Method,
+            SymbolInformationKind::Type => Self::Type,
+            SymbolInformationKind::TypeAlias => Self::Type,
+            SymbolInformationKind::TypeParameter => Self::TypeParameter,
+            SymbolInformationKind::Union => Self::Type,
+            SymbolInformationKind::Variable => Self::Term,
+        }
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct MonikerDescriptor {
     pub name: String,
@@ -112,6 +168,69 @@ pub(crate) fn moniker(
     Some(RangeInfo::new(original_token.text_range(), navs))
 }
 
+pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformationKind {
+    use SymbolInformationKind::*;
+
+    match def {
+        Definition::Macro(it) => match it.kind(db) {
+            MacroKind::Declarative => Macro,
+            MacroKind::Derive => Attribute,
+            MacroKind::BuiltIn => Macro,
+            MacroKind::Attr => Attribute,
+            MacroKind::ProcMacro => Macro,
+        },
+        Definition::Field(..) => Field,
+        Definition::Module(..) => Module,
+        Definition::Function(it) => {
+            if it.as_assoc_item(db).is_some() {
+                if it.has_self_param(db) {
+                    if it.has_body(db) {
+                        Method
+                    } else {
+                        TraitMethod
+                    }
+                } else {
+                    StaticMethod
+                }
+            } else {
+                Function
+            }
+        }
+        Definition::Adt(Adt::Struct(..)) => Struct,
+        Definition::Adt(Adt::Union(..)) => Union,
+        Definition::Adt(Adt::Enum(..)) => Enum,
+        Definition::Variant(..) => EnumMember,
+        Definition::Const(..) => Constant,
+        Definition::Static(..) => StaticVariable,
+        Definition::Trait(..) => Trait,
+        Definition::TraitAlias(..) => Trait,
+        Definition::TypeAlias(it) => {
+            if it.as_assoc_item(db).is_some() {
+                AssociatedType
+            } else {
+                TypeAlias
+            }
+        }
+        Definition::BuiltinType(..) => Type,
+        Definition::SelfType(..) => TypeAlias,
+        Definition::GenericParam(..) => TypeParameter,
+        Definition::Local(it) => {
+            if it.is_self(db) {
+                SelfParameter
+            } else if it.is_param(db) {
+                Parameter
+            } else {
+                Variable
+            }
+        }
+        Definition::Label(..) => Variable, // For lack of a better variant
+        Definition::DeriveHelper(..) => Attribute,
+        Definition::BuiltinAttr(..) => Attribute,
+        Definition::ToolModule(..) => Module,
+        Definition::ExternCrateDecl(..) => Module,
+    }
+}
+
 pub(crate) fn def_to_moniker(
     db: &RootDatabase,
     def: Definition,
@@ -134,7 +253,7 @@ pub(crate) fn def_to_moniker(
     description.extend(module.path_to_root(db).into_iter().filter_map(|x| {
         Some(MonikerDescriptor {
             name: x.name(db)?.display(db).to_string(),
-            desc: MonikerDescriptorKind::Namespace,
+            desc: def_to_kind(db, x.into()).into(),
         })
     }));
 
@@ -147,7 +266,7 @@ pub(crate) fn def_to_moniker(
                 // we have to include the trait name as part of the moniker for uniqueness.
                 description.push(MonikerDescriptor {
                     name: trait_.name(db).display(db).to_string(),
-                    desc: MonikerDescriptorKind::Type,
+                    desc: def_to_kind(db, trait_.into()).into(),
                 });
             }
             AssocItemContainer::Impl(impl_) => {
@@ -156,14 +275,14 @@ pub(crate) fn def_to_moniker(
                 if let Some(adt) = impl_.self_ty(db).as_adt() {
                     description.push(MonikerDescriptor {
                         name: adt.name(db).display(db).to_string(),
-                        desc: MonikerDescriptorKind::Type,
+                        desc: def_to_kind(db, adt.into()).into(),
                     });
                 }
 
                 if let Some(trait_) = impl_.trait_(db) {
                     description.push(MonikerDescriptor {
                         name: trait_.name(db).display(db).to_string(),
-                        desc: MonikerDescriptorKind::Type,
+                        desc: def_to_kind(db, trait_.into()).into(),
                     });
                 }
             }
@@ -173,21 +292,26 @@ pub(crate) fn def_to_moniker(
     if let Definition::Field(it) = def {
         description.push(MonikerDescriptor {
             name: it.parent_def(db).name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::Type,
+            desc: def_to_kind(db, it.parent_def(db).into()).into(),
         });
     }
 
     // Qualify locals/parameters by their parent definition name.
     if let Definition::Local(it) = def {
-        let parent_name = it.parent(db).name(db);
-        if let Some(name) = parent_name {
-            description.push(MonikerDescriptor {
-                name: name.display(db).to_string(),
-                desc: MonikerDescriptorKind::Method,
-            });
+        let parent = Definition::try_from(it.parent(db)).ok();
+        if let Some(parent) = parent {
+            let parent_name = parent.name(db);
+            if let Some(name) = parent_name {
+                description.push(MonikerDescriptor {
+                    name: name.display(db).to_string(),
+                    desc: def_to_kind(db, parent).into(),
+                });
+            }
         }
     }
 
+    let desc = def_to_kind(db, def).into();
+
     let name_desc = match def {
         // These are handled by top-level guard (for performance).
         Definition::GenericParam(_)
@@ -201,67 +325,51 @@ pub(crate) fn def_to_moniker(
                 return None;
             }
 
-            MonikerDescriptor {
-                name: local.name(db).display(db).to_string(),
-                desc: MonikerDescriptorKind::Parameter,
-            }
+            MonikerDescriptor { name: local.name(db).display(db).to_string(), desc }
+        }
+        Definition::Macro(m) => {
+            MonikerDescriptor { name: m.name(db).display(db).to_string(), desc }
+        }
+        Definition::Function(f) => {
+            MonikerDescriptor { name: f.name(db).display(db).to_string(), desc }
+        }
+        Definition::Variant(v) => {
+            MonikerDescriptor { name: v.name(db).display(db).to_string(), desc }
+        }
+        Definition::Const(c) => {
+            MonikerDescriptor { name: c.name(db)?.display(db).to_string(), desc }
+        }
+        Definition::Trait(trait_) => {
+            MonikerDescriptor { name: trait_.name(db).display(db).to_string(), desc }
+        }
+        Definition::TraitAlias(ta) => {
+            MonikerDescriptor { name: ta.name(db).display(db).to_string(), desc }
+        }
+        Definition::TypeAlias(ta) => {
+            MonikerDescriptor { name: ta.name(db).display(db).to_string(), desc }
+        }
+        Definition::Module(m) => {
+            MonikerDescriptor { name: m.name(db)?.display(db).to_string(), desc }
+        }
+        Definition::BuiltinType(b) => {
+            MonikerDescriptor { name: b.name().display(db).to_string(), desc }
         }
-        Definition::Macro(m) => MonikerDescriptor {
-            name: m.name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::Macro,
-        },
-        Definition::Function(f) => MonikerDescriptor {
-            name: f.name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::Method,
-        },
-        Definition::Variant(v) => MonikerDescriptor {
-            name: v.name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::Type,
-        },
-        Definition::Const(c) => MonikerDescriptor {
-            name: c.name(db)?.display(db).to_string(),
-            desc: MonikerDescriptorKind::Term,
-        },
-        Definition::Trait(trait_) => MonikerDescriptor {
-            name: trait_.name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::Type,
-        },
-        Definition::TraitAlias(ta) => MonikerDescriptor {
-            name: ta.name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::Type,
-        },
-        Definition::TypeAlias(ta) => MonikerDescriptor {
-            name: ta.name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::TypeParameter,
-        },
-        Definition::Module(m) => MonikerDescriptor {
-            name: m.name(db)?.display(db).to_string(),
-            desc: MonikerDescriptorKind::Namespace,
-        },
-        Definition::BuiltinType(b) => MonikerDescriptor {
-            name: b.name().display(db).to_string(),
-            desc: MonikerDescriptorKind::Type,
-        },
         Definition::SelfType(imp) => MonikerDescriptor {
             name: imp.self_ty(db).as_adt()?.name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::Type,
-        },
-        Definition::Field(it) => MonikerDescriptor {
-            name: it.name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::Term,
-        },
-        Definition::Adt(adt) => MonikerDescriptor {
-            name: adt.name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::Type,
-        },
-        Definition::Static(s) => MonikerDescriptor {
-            name: s.name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::Meta,
-        },
-        Definition::ExternCrateDecl(m) => MonikerDescriptor {
-            name: m.name(db).display(db).to_string(),
-            desc: MonikerDescriptorKind::Namespace,
+            desc,
         },
+        Definition::Field(it) => {
+            MonikerDescriptor { name: it.name(db).display(db).to_string(), desc }
+        }
+        Definition::Adt(adt) => {
+            MonikerDescriptor { name: adt.name(db).display(db).to_string(), desc }
+        }
+        Definition::Static(s) => {
+            MonikerDescriptor { name: s.name(db).display(db).to_string(), desc }
+        }
+        Definition::ExternCrateDecl(m) => {
+            MonikerDescriptor { name: m.name(db).display(db).to_string(), desc }
+        }
     };
 
     description.push(name_desc);
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index ff13bd54a37..47fe2472a5e 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -17,7 +17,7 @@ use crate::navigation_target::UpmappingResult;
 use crate::{
     hover::hover_for_definition,
     inlay_hints::AdjustmentHintsMode,
-    moniker::{def_to_moniker, MonikerResult},
+    moniker::{def_to_kind, def_to_moniker, MonikerResult, SymbolInformationKind},
     parent_module::crates_for,
     Analysis, Fold, HoverConfig, HoverResult, InlayHint, InlayHintsConfig, TryToNav,
 };
@@ -49,6 +49,7 @@ pub struct TokenStaticData {
     pub display_name: Option<String>,
     pub enclosing_moniker: Option<MonikerResult>,
     pub signature: Option<String>,
+    pub kind: SymbolInformationKind,
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -180,6 +181,7 @@ impl StaticIndex<'_> {
                         .zip(def.enclosing_definition(self.db))
                         .and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)),
                     signature: def.label(self.db),
+                    kind: def_to_kind(self.db, def),
                 });
                 self.def_map.insert(def, it);
                 it
diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs
index 8123c4b7150..c86b2c0ba40 100644
--- a/crates/rust-analyzer/src/cli/scip.rs
+++ b/crates/rust-analyzer/src/cli/scip.rs
@@ -7,8 +7,8 @@ use std::{
 };
 
 use ide::{
-    LineCol, MonikerDescriptorKind, MonikerResult, StaticIndex, StaticIndexedFile, TextRange,
-    TokenId,
+    LineCol, MonikerDescriptorKind, MonikerResult, StaticIndex, StaticIndexedFile,
+    SymbolInformationKind, TextRange, TokenId,
 };
 use ide_db::LineIndexDatabase;
 use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice};
@@ -155,7 +155,7 @@ impl flags::Scip {
                             documentation: documentation.unwrap_or_default(),
                             relationships: Vec::new(),
                             special_fields: Default::default(),
-                            kind: Default::default(),
+                            kind: symbol_kind(token.kind).into(),
                             display_name: token.display_name.clone().unwrap_or_default(),
                             signature_documentation: signature_documentation.into(),
                             enclosing_symbol: enclosing_symbol.unwrap_or_default(),
@@ -250,6 +250,34 @@ fn new_descriptor(name: &str, suffix: scip_types::descriptor::Suffix) -> scip_ty
     }
 }
 
+fn symbol_kind(kind: SymbolInformationKind) -> scip_types::symbol_information::Kind {
+    use scip_types::symbol_information::Kind as ScipKind;
+    match kind {
+        SymbolInformationKind::AssociatedType => ScipKind::AssociatedType,
+        SymbolInformationKind::Attribute => ScipKind::Attribute,
+        SymbolInformationKind::Constant => ScipKind::Constant,
+        SymbolInformationKind::Enum => ScipKind::Enum,
+        SymbolInformationKind::EnumMember => ScipKind::EnumMember,
+        SymbolInformationKind::Field => ScipKind::Field,
+        SymbolInformationKind::Function => ScipKind::Function,
+        SymbolInformationKind::Macro => ScipKind::Macro,
+        SymbolInformationKind::Method => ScipKind::Method,
+        SymbolInformationKind::Module => ScipKind::Module,
+        SymbolInformationKind::Parameter => ScipKind::Parameter,
+        SymbolInformationKind::SelfParameter => ScipKind::SelfParameter,
+        SymbolInformationKind::StaticMethod => ScipKind::StaticMethod,
+        SymbolInformationKind::StaticVariable => ScipKind::StaticVariable,
+        SymbolInformationKind::Struct => ScipKind::Struct,
+        SymbolInformationKind::Trait => ScipKind::Trait,
+        SymbolInformationKind::TraitMethod => ScipKind::TraitMethod,
+        SymbolInformationKind::Type => ScipKind::Type,
+        SymbolInformationKind::TypeAlias => ScipKind::TypeAlias,
+        SymbolInformationKind::TypeParameter => ScipKind::TypeParameter,
+        SymbolInformationKind::Union => ScipKind::Union,
+        SymbolInformationKind::Variable => ScipKind::Variable,
+    }
+}
+
 fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol {
     use scip_types::descriptor::Suffix::*;
 
@@ -376,6 +404,21 @@ pub mod module {
     }
 
     #[test]
+    fn symbol_for_trait_alias() {
+        check_symbol(
+            r#"
+//- /foo/lib.rs crate:foo@0.1.0,https://a.b/foo.git library
+#![feature(trait_alias)]
+pub mod module {
+    pub trait MyTrait {}
+    pub trait MyTraitAlias$0 = MyTrait;
+}
+"#,
+            "rust-analyzer cargo foo 0.1.0 module/MyTraitAlias#",
+        );
+    }
+
+    #[test]
     fn symbol_for_trait_constant() {
         check_symbol(
             r#"
@@ -541,4 +584,15 @@ pub mod example_mod {
             "rust-analyzer cargo main . foo/Bar#",
         );
     }
+
+    #[test]
+    fn symbol_for_for_type_alias() {
+        check_symbol(
+            r#"
+    //- /lib.rs crate:main
+    pub type MyTypeAlias$0 = u8;
+    "#,
+            "rust-analyzer cargo main . MyTypeAlias#",
+        );
+    }
 }