diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 14c0f420ac552..410b8304592d5 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 for Definition { } } +impl From for Definition { + fn from(def: VariantDef) -> Self { + ModuleDef::from(def).into() + } +} + impl TryFrom for Definition { type Error = (); fn try_from(def: DefWithBody) -> Result { diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 6ff16b9e2f713..e5da1a24c84a2 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 8e8bb5e0139ea..94ddd162de4e4 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 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 ff13bd54a37b1..47fe2472a5e99 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, pub enclosing_moniker: Option, pub signature: Option, + 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 8123c4b715030..c86b2c0ba4052 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::*; @@ -375,6 +403,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( @@ -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#", + ); + } }