Auto merge of #14715 - Veykril:symbol-index, r=Veykril

Refactor symbol index

Closes https://github.com/rust-lang/rust-analyzer/issues/14677

instead of eagerly fetching the source data in symbol index we do it lazily now, this shouldn't make it much more expensive as we had to parse the source most of the time anyways even after fetching.
This commit is contained in:
bors 2023-05-02 10:34:53 +00:00
commit 94ac1cdbf5
13 changed files with 422 additions and 684 deletions

View File

@ -51,7 +51,7 @@ use hir_def::{
per_ns::PerNs,
resolver::{HasResolver, Resolver},
src::HasSource as _,
AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId,
TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
@ -119,11 +119,9 @@ pub use {
path::{ModPath, PathKind},
type_ref::{Mutability, TypeRef},
visibility::Visibility,
// FIXME: This is here since it is input of a method in `HirWrite`
// and things outside of hir need to implement that trait. We probably
// should move whole `hir_ty::display` to this crate so we will become
// able to use `ModuleDef` or `Definition` instead of `ModuleDefId`.
ModuleDefId,
// FIXME: This is here since some queries take it as input that are used
// outside of hir.
{AdtId, ModuleDefId},
},
hir_expand::{
attrs::Attr,
@ -4429,3 +4427,90 @@ impl HasCrate for Module {
Module::krate(*self)
}
}
pub trait HasContainer {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
}
impl HasContainer for Module {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
// FIXME: handle block expressions as modules (their parent is in a different DefMap)
let def_map = self.id.def_map(db.upcast());
match def_map[self.id.local_id].parent {
Some(parent_id) => ItemContainer::Module(Module { id: def_map.module_id(parent_id) }),
None => ItemContainer::Crate(def_map.krate()),
}
}
}
impl HasContainer for Function {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
container_id_to_hir(self.id.lookup(db.upcast()).container)
}
}
impl HasContainer for Struct {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
}
}
impl HasContainer for Union {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
}
}
impl HasContainer for Enum {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
}
}
impl HasContainer for TypeAlias {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
container_id_to_hir(self.id.lookup(db.upcast()).container)
}
}
impl HasContainer for Const {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
container_id_to_hir(self.id.lookup(db.upcast()).container)
}
}
impl HasContainer for Static {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
container_id_to_hir(self.id.lookup(db.upcast()).container)
}
}
impl HasContainer for Trait {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
}
}
impl HasContainer for TraitAlias {
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
}
}
fn container_id_to_hir(c: ItemContainerId) -> ItemContainer {
match c {
ItemContainerId::ExternBlockId(_id) => ItemContainer::ExternBlock(),
ItemContainerId::ModuleId(id) => ItemContainer::Module(Module { id }),
ItemContainerId::ImplId(id) => ItemContainer::Impl(Impl { id }),
ItemContainerId::TraitId(id) => ItemContainer::Trait(Trait { id }),
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ItemContainer {
Trait(Trait),
Impl(Impl),
Module(Module),
ExternBlock(),
Crate(CrateId),
}

View File

@ -1,89 +1,20 @@
//! File symbol extraction.
use base_db::FileRange;
use hir_def::{
item_tree::ItemTreeNode, src::HasSource, AdtId, AssocItemId, AssocItemLoc, DefWithBodyId,
HasModule, ImplId, ItemContainerId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId,
AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, MacroId, ModuleDefId, ModuleId, TraitId,
};
use hir_expand::{HirFileId, InFile};
use hir_ty::db::HirDatabase;
use syntax::{ast::HasName, AstNode, SmolStr, SyntaxNode, SyntaxNodePtr};
use syntax::SmolStr;
use crate::{Module, Semantics};
use crate::{Module, ModuleDef};
/// 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 {
// even though name can be derived from the def, we store it for efficiency
pub name: SmolStr,
pub loc: DeclarationLocation,
pub kind: FileSymbolKind,
pub container_name: Option<SmolStr>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DeclarationLocation {
/// The file id for both the `ptr` and `name_ptr`.
pub hir_file_id: HirFileId,
/// This points to the whole syntax node of the declaration.
pub ptr: SyntaxNodePtr,
/// This points to the [`syntax::ast::Name`] identifier of the declaration.
pub name_ptr: SyntaxNodePtr,
}
impl DeclarationLocation {
pub fn syntax<DB: HirDatabase>(&self, sema: &Semantics<'_, DB>) -> SyntaxNode {
let root = sema.parse_or_expand(self.hir_file_id);
self.ptr.to_node(&root)
}
pub fn original_range(&self, db: &dyn HirDatabase) -> FileRange {
let node = resolve_node(db, self.hir_file_id, &self.ptr);
node.as_ref().original_file_range(db.upcast())
}
pub fn original_name_range(&self, db: &dyn HirDatabase) -> Option<FileRange> {
let node = resolve_node(db, self.hir_file_id, &self.name_ptr);
node.as_ref().original_file_range_opt(db.upcast())
}
}
fn resolve_node(
db: &dyn HirDatabase,
file_id: HirFileId,
ptr: &SyntaxNodePtr,
) -> InFile<SyntaxNode> {
let root = db.parse_or_expand(file_id);
let node = ptr.to_node(&root);
InFile::new(file_id, node)
}
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum FileSymbolKind {
Const,
Enum,
Function,
Macro,
Module,
Static,
Struct,
Trait,
TraitAlias,
TypeAlias,
Union,
}
impl FileSymbolKind {
pub fn is_type(self: FileSymbolKind) -> bool {
matches!(
self,
FileSymbolKind::Struct
| FileSymbolKind::Enum
| FileSymbolKind::Trait
| FileSymbolKind::TypeAlias
| FileSymbolKind::Union
)
}
pub def: ModuleDef,
}
/// Represents an outstanding module that the symbol collector must collect symbols from.
@ -146,36 +77,34 @@ impl<'a> SymbolCollector<'a> {
match module_def_id {
ModuleDefId::ModuleId(id) => self.push_module(id),
ModuleDefId::FunctionId(id) => {
self.push_decl_assoc(id, FileSymbolKind::Function);
self.push_decl(id);
self.collect_from_body(id);
}
ModuleDefId::AdtId(AdtId::StructId(id)) => {
self.push_decl(id, FileSymbolKind::Struct)
}
ModuleDefId::AdtId(AdtId::EnumId(id)) => self.push_decl(id, FileSymbolKind::Enum),
ModuleDefId::AdtId(AdtId::UnionId(id)) => self.push_decl(id, FileSymbolKind::Union),
ModuleDefId::AdtId(AdtId::StructId(id)) => self.push_decl(id),
ModuleDefId::AdtId(AdtId::EnumId(id)) => self.push_decl(id),
ModuleDefId::AdtId(AdtId::UnionId(id)) => self.push_decl(id),
ModuleDefId::ConstId(id) => {
self.push_decl_assoc(id, FileSymbolKind::Const);
self.push_decl(id);
self.collect_from_body(id);
}
ModuleDefId::StaticId(id) => {
self.push_decl_assoc(id, FileSymbolKind::Static);
self.push_decl(id);
self.collect_from_body(id);
}
ModuleDefId::TraitId(id) => {
self.push_decl(id, FileSymbolKind::Trait);
self.push_decl(id);
self.collect_from_trait(id);
}
ModuleDefId::TraitAliasId(id) => {
self.push_decl(id, FileSymbolKind::TraitAlias);
self.push_decl(id);
}
ModuleDefId::TypeAliasId(id) => {
self.push_decl_assoc(id, FileSymbolKind::TypeAlias);
self.push_decl(id);
}
ModuleDefId::MacroId(id) => match id {
MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::MacroRulesId(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::ProcMacroId(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::Macro2Id(id) => self.push_decl(id),
MacroId::MacroRulesId(id) => self.push_decl(id),
MacroId::ProcMacroId(id) => self.push_decl(id),
},
// Don't index these.
ModuleDefId::BuiltinType(_) => {}
@ -195,9 +124,9 @@ impl<'a> SymbolCollector<'a> {
for &id in id {
if id.module(self.db.upcast()) == module_id {
match id {
MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::MacroRulesId(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::ProcMacroId(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::Macro2Id(id) => self.push_decl(id),
MacroId::MacroRulesId(id) => self.push_decl(id),
MacroId::ProcMacroId(id) => self.push_decl(id),
}
}
}
@ -245,124 +174,36 @@ impl<'a> SymbolCollector<'a> {
}
}
fn current_container_name(&self) -> Option<SmolStr> {
self.current_container_name.clone()
}
fn def_with_body_id_name(&self, body_id: DefWithBodyId) -> Option<SmolStr> {
match body_id {
DefWithBodyId::FunctionId(id) => Some(
id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
),
DefWithBodyId::StaticId(id) => Some(
id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
),
DefWithBodyId::ConstId(id) => Some(
id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
),
DefWithBodyId::VariantId(id) => Some({
let db = self.db.upcast();
id.parent.lookup(db).source(db).value.name()?.text().into()
}),
DefWithBodyId::FunctionId(id) => Some(self.db.function_data(id).name.to_smol_str()),
DefWithBodyId::StaticId(id) => Some(self.db.static_data(id).name.to_smol_str()),
DefWithBodyId::ConstId(id) => Some(self.db.const_data(id).name.as_ref()?.to_smol_str()),
DefWithBodyId::VariantId(id) => {
Some(self.db.enum_data(id.parent).variants[id.local_id].name.to_smol_str())
}
}
}
fn push_assoc_item(&mut self, assoc_item_id: AssocItemId) {
match assoc_item_id {
AssocItemId::FunctionId(id) => self.push_decl_assoc(id, FileSymbolKind::Function),
AssocItemId::ConstId(id) => self.push_decl_assoc(id, FileSymbolKind::Const),
AssocItemId::TypeAliasId(id) => self.push_decl_assoc(id, FileSymbolKind::TypeAlias),
AssocItemId::FunctionId(id) => self.push_decl(id),
AssocItemId::ConstId(id) => self.push_decl(id),
AssocItemId::TypeAliasId(id) => self.push_decl(id),
}
}
fn push_decl_assoc<L, T>(&mut self, id: L, kind: FileSymbolKind)
where
L: Lookup<Data = AssocItemLoc<T>>,
T: ItemTreeNode,
<T as ItemTreeNode>::Source: HasName,
{
fn container_name(db: &dyn HirDatabase, container: ItemContainerId) -> Option<SmolStr> {
match container {
ItemContainerId::ModuleId(module_id) => {
let module = Module::from(module_id);
module.name(db).and_then(|name| name.as_text())
}
ItemContainerId::TraitId(trait_id) => {
let trait_data = db.trait_data(trait_id);
trait_data.name.as_text()
}
ItemContainerId::ImplId(_) | ItemContainerId::ExternBlockId(_) => None,
}
fn push_decl(&mut self, id: impl Into<ModuleDefId>) {
let def = ModuleDef::from(id.into());
if let Some(name) = def.name(self.db) {
self.symbols.push(FileSymbol { name: name.to_smol_str(), def });
}
self.push_file_symbol(|s| {
let loc = id.lookup(s.db.upcast());
let source = loc.source(s.db.upcast());
let name_node = source.value.name()?;
let container_name =
container_name(s.db, loc.container).or_else(|| s.current_container_name());
Some(FileSymbol {
name: name_node.text().into(),
kind,
container_name,
loc: DeclarationLocation {
hir_file_id: source.file_id,
ptr: SyntaxNodePtr::new(source.value.syntax()),
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
},
})
})
}
fn push_decl<L>(&mut self, id: L, kind: FileSymbolKind)
where
L: Lookup,
<L as Lookup>::Data: HasSource,
<<L as Lookup>::Data as HasSource>::Value: HasName,
{
self.push_file_symbol(|s| {
let loc = id.lookup(s.db.upcast());
let source = loc.source(s.db.upcast());
let name_node = source.value.name()?;
Some(FileSymbol {
name: name_node.text().into(),
kind,
container_name: s.current_container_name(),
loc: DeclarationLocation {
hir_file_id: source.file_id,
ptr: SyntaxNodePtr::new(source.value.syntax()),
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
},
})
})
}
fn push_module(&mut self, module_id: ModuleId) {
self.push_file_symbol(|s| {
let def_map = module_id.def_map(s.db.upcast());
let module_data = &def_map[module_id.local_id];
let declaration = module_data.origin.declaration()?;
let module = declaration.to_node(s.db.upcast());
let name_node = module.name()?;
Some(FileSymbol {
name: name_node.text().into(),
kind: FileSymbolKind::Module,
container_name: s.current_container_name(),
loc: DeclarationLocation {
hir_file_id: declaration.file_id,
ptr: SyntaxNodePtr::new(module.syntax()),
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
},
})
})
}
fn push_file_symbol(&mut self, f: impl FnOnce(&Self) -> Option<FileSymbol>) {
if let Some(file_symbol) = f(self) {
self.symbols.push(file_symbol);
let def = Module::from(module_id);
if let Some(name) = def.name(self.db) {
self.symbols.push(FileSymbol { name: name.to_smol_str(), def: ModuleDef::Module(def) });
}
}
}

View File

@ -8,8 +8,8 @@
use arrayvec::ArrayVec;
use hir::{
Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, DeriveHelper, Field,
Function, GenericParam, HasVisibility, Impl, ItemInNs, Label, Local, Macro, Module, ModuleDef,
Name, PathResolution, Semantics, Static, ToolModule, Trait, TraitAlias, TypeAlias, Variant,
Function, GenericParam, HasVisibility, Impl, Label, Local, Macro, Module, ModuleDef, Name,
PathResolution, Semantics, Static, ToolModule, Trait, TraitAlias, TypeAlias, Variant,
Visibility,
};
use stdx::impl_from;
@ -622,22 +622,3 @@ impl From<ModuleDef> for Definition {
}
}
}
impl From<Definition> for Option<ItemInNs> {
fn from(def: Definition) -> Self {
let item = match def {
Definition::Module(it) => ModuleDef::Module(it),
Definition::Function(it) => ModuleDef::Function(it),
Definition::Adt(it) => ModuleDef::Adt(it),
Definition::Variant(it) => ModuleDef::Variant(it),
Definition::Const(it) => ModuleDef::Const(it),
Definition::Static(it) => ModuleDef::Static(it),
Definition::Trait(it) => ModuleDef::Trait(it),
Definition::TraitAlias(it) => ModuleDef::TraitAlias(it),
Definition::TypeAlias(it) => ModuleDef::TypeAlias(it),
Definition::BuiltinType(it) => ModuleDef::BuiltinType(it),
_ => return None,
};
Some(ItemInNs::from(item))
}
}

View File

@ -5,17 +5,11 @@
use either::Either;
use hir::{
import_map::{self, ImportKind},
symbols::FileSymbol,
AsAssocItem, Crate, ItemInNs, Semantics,
};
use limit::Limit;
use syntax::{ast, AstNode, SyntaxKind::NAME};
use crate::{
defs::{Definition, NameClass},
imports::import_assets::NameToImport,
symbol_index, RootDatabase,
};
use crate::{imports::import_assets::NameToImport, symbol_index, RootDatabase};
/// A value to use, when uncertain which limit to pick.
pub static DEFAULT_QUERY_SEARCH_LIMIT: Limit = Limit::new(40);
@ -118,10 +112,9 @@ fn find_items<'a>(
let local_results = local_query
.search(&symbol_index::crate_symbols(db, krate))
.into_iter()
.filter_map(move |local_candidate| get_name_definition(sema, &local_candidate))
.filter_map(|name_definition_to_import| match name_definition_to_import {
Definition::Macro(macro_def) => Some(ItemInNs::from(macro_def)),
def => <Option<_>>::from(def),
.filter_map(|local_candidate| match local_candidate.def {
hir::ModuleDef::Macro(macro_def) => Some(ItemInNs::Macros(macro_def)),
def => Some(ItemInNs::from(def)),
});
external_importables.chain(local_results).filter(move |&item| match assoc_item_search {
@ -131,22 +124,6 @@ fn find_items<'a>(
})
}
fn get_name_definition(
sema: &Semantics<'_, RootDatabase>,
import_candidate: &FileSymbol,
) -> Option<Definition> {
let _p = profile::span("get_name_definition");
let candidate_node = import_candidate.loc.syntax(sema);
let candidate_name_node = if candidate_node.kind() != NAME {
candidate_node.children().find(|it| it.kind() == NAME)?
} else {
candidate_node
};
let name = ast::Name::cast(candidate_name_node)?;
NameClass::classify(sema, &name)?.defined()
}
fn is_assoc_item(item: ItemInNs, db: &RootDatabase) -> bool {
item.as_module_def().and_then(|module_def| module_def.as_assoc_item(db)).is_some()
}

View File

@ -49,10 +49,7 @@ use base_db::{
salsa::{self, Durability},
AnchoredPath, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast,
};
use hir::{
db::{DefDatabase, ExpandDatabase, HirDatabase},
symbols::FileSymbolKind,
};
use hir::db::{DefDatabase, ExpandDatabase, HirDatabase};
use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase};
pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
@ -378,20 +375,22 @@ impl From<hir::MacroKind> for SymbolKind {
}
}
impl From<FileSymbolKind> for SymbolKind {
fn from(it: FileSymbolKind) -> Self {
impl From<hir::ModuleDefId> for SymbolKind {
fn from(it: hir::ModuleDefId) -> Self {
match it {
FileSymbolKind::Const => SymbolKind::Const,
FileSymbolKind::Enum => SymbolKind::Enum,
FileSymbolKind::Function => SymbolKind::Function,
FileSymbolKind::Macro => SymbolKind::Macro,
FileSymbolKind::Module => SymbolKind::Module,
FileSymbolKind::Static => SymbolKind::Static,
FileSymbolKind::Struct => SymbolKind::Struct,
FileSymbolKind::Trait => SymbolKind::Trait,
FileSymbolKind::TraitAlias => SymbolKind::TraitAlias,
FileSymbolKind::TypeAlias => SymbolKind::TypeAlias,
FileSymbolKind::Union => SymbolKind::Union,
hir::ModuleDefId::ConstId(..) => SymbolKind::Const,
hir::ModuleDefId::EnumVariantId(..) => SymbolKind::Variant,
hir::ModuleDefId::FunctionId(..) => SymbolKind::Function,
hir::ModuleDefId::MacroId(..) => SymbolKind::Macro,
hir::ModuleDefId::ModuleId(..) => SymbolKind::Module,
hir::ModuleDefId::StaticId(..) => SymbolKind::Static,
hir::ModuleDefId::AdtId(hir::AdtId::StructId(..)) => SymbolKind::Struct,
hir::ModuleDefId::AdtId(hir::AdtId::EnumId(..)) => SymbolKind::Enum,
hir::ModuleDefId::AdtId(hir::AdtId::UnionId(..)) => SymbolKind::Union,
hir::ModuleDefId::TraitId(..) => SymbolKind::Trait,
hir::ModuleDefId::TraitAliasId(..) => SymbolKind::TraitAlias,
hir::ModuleDefId::TypeAliasId(..) => SymbolKind::TypeAlias,
hir::ModuleDefId::BuiltinType(..) => SymbolKind::TypeAlias,
}
}
}

View File

@ -317,7 +317,14 @@ 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
&& !matches!(
symbol.def,
hir::ModuleDef::Adt(..)
| hir::ModuleDef::TypeAlias(..)
| hir::ModuleDef::BuiltinType(..)
)
{
continue;
}
if self.exact {

View File

@ -10,368 +10,226 @@
[
FileSymbol {
name: "Alias",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: TYPE_ALIAS,
range: 397..417,
def: TypeAlias(
TypeAlias {
id: TypeAliasId(
0,
),
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 402..407,
},
},
kind: TypeAlias,
container_name: None,
),
},
FileSymbol {
name: "CONST",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: CONST,
range: 340..361,
def: Const(
Const {
id: ConstId(
0,
),
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 346..351,
},
},
kind: Const,
container_name: None,
),
},
FileSymbol {
name: "CONST_WITH_INNER",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: CONST,
range: 520..592,
def: Const(
Const {
id: ConstId(
2,
),
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 526..542,
},
},
kind: Const,
container_name: None,
),
},
FileSymbol {
name: "Enum",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
def: Adt(
Enum(
Enum {
id: EnumId(
0,
),
},
),
ptr: SyntaxNodePtr {
kind: ENUM,
range: 185..207,
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 190..194,
},
},
kind: Enum,
container_name: None,
),
},
FileSymbol {
name: "Macro",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: MACRO_DEF,
range: 153..168,
def: Macro(
Macro {
id: Macro2Id(
Macro2Id(
0,
),
),
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 159..164,
},
},
kind: Macro,
container_name: None,
),
},
FileSymbol {
name: "STATIC",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: STATIC,
range: 362..396,
def: Static(
Static {
id: StaticId(
0,
),
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 369..375,
},
},
kind: Static,
container_name: None,
),
},
FileSymbol {
name: "Struct",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
def: Adt(
Struct(
Struct {
id: StructId(
1,
),
},
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 170..184,
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 177..183,
},
},
kind: Struct,
container_name: None,
),
},
FileSymbol {
name: "StructFromMacro",
loc: DeclarationLocation {
hir_file_id: HirFileId(
2147483648,
def: Adt(
Struct(
Struct {
id: StructId(
0,
),
},
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 0..22,
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 6..21,
},
},
kind: Struct,
container_name: None,
),
},
FileSymbol {
name: "StructInFn",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
def: Adt(
Struct(
Struct {
id: StructId(
4,
),
},
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 318..336,
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 325..335,
},
},
kind: Struct,
container_name: Some(
"main",
),
},
FileSymbol {
name: "StructInNamedConst",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
def: Adt(
Struct(
Struct {
id: StructId(
5,
),
},
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 555..581,
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 562..580,
},
},
kind: Struct,
container_name: Some(
"CONST_WITH_INNER",
),
},
FileSymbol {
name: "StructInUnnamedConst",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
def: Adt(
Struct(
Struct {
id: StructId(
6,
),
},
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 479..507,
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 486..506,
},
},
kind: Struct,
container_name: None,
),
},
FileSymbol {
name: "Trait",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: TRAIT,
range: 261..300,
def: Trait(
Trait {
id: TraitId(
0,
),
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 267..272,
},
},
kind: Trait,
container_name: None,
),
},
FileSymbol {
name: "Union",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
def: Adt(
Union(
Union {
id: UnionId(
0,
),
},
),
ptr: SyntaxNodePtr {
kind: UNION,
range: 208..222,
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 214..219,
},
},
kind: Union,
container_name: None,
),
},
FileSymbol {
name: "a_mod",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: MODULE,
range: 419..457,
def: Module(
Module {
id: ModuleId {
krate: Idx::<CrateData>(0),
block: None,
local_id: Idx::<ModuleData>(1),
},
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 423..428,
},
},
kind: Module,
container_name: None,
),
},
FileSymbol {
name: "b_mod",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: MODULE,
range: 594..604,
def: Module(
Module {
id: ModuleId {
krate: Idx::<CrateData>(0),
block: None,
local_id: Idx::<ModuleData>(2),
},
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 598..603,
},
},
kind: Module,
container_name: None,
),
},
FileSymbol {
name: "define_struct",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: MACRO_RULES,
range: 51..131,
def: Macro(
Macro {
id: MacroRulesId(
MacroRulesId(
1,
),
),
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 64..77,
},
},
kind: Macro,
container_name: None,
),
},
FileSymbol {
name: "impl_fn",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: FN,
range: 242..257,
def: Function(
Function {
id: FunctionId(
2,
),
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 245..252,
},
},
kind: Function,
container_name: None,
),
},
FileSymbol {
name: "macro_rules_macro",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: MACRO_RULES,
range: 1..48,
def: Macro(
Macro {
id: MacroRulesId(
MacroRulesId(
0,
),
),
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 14..31,
},
},
kind: Macro,
container_name: None,
),
},
FileSymbol {
name: "main",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: FN,
range: 302..338,
def: Function(
Function {
id: FunctionId(
0,
),
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 305..309,
},
},
kind: Function,
container_name: None,
),
},
FileSymbol {
name: "trait_fn",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
),
ptr: SyntaxNodePtr {
kind: FN,
range: 279..298,
def: Function(
Function {
id: FunctionId(
1,
),
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 282..290,
},
},
kind: Function,
container_name: Some(
"Trait",
),
},
],
@ -387,21 +245,15 @@
[
FileSymbol {
name: "StructInModA",
loc: DeclarationLocation {
hir_file_id: HirFileId(
0,
def: Adt(
Struct(
Struct {
id: StructId(
2,
),
},
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 435..455,
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 442..454,
},
},
kind: Struct,
container_name: None,
),
},
],
),
@ -416,21 +268,15 @@
[
FileSymbol {
name: "StructInModB",
loc: DeclarationLocation {
hir_file_id: HirFileId(
1,
def: Adt(
Struct(
Struct {
id: StructId(
3,
),
},
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 0..20,
},
name_ptr: SyntaxNodePtr {
kind: NAME,
range: 7..19,
},
},
kind: Struct,
container_name: None,
),
},
],
),

View File

@ -263,7 +263,7 @@ mod tests {
expect![["callee Function FileId(0) 0..14 3..9"]],
expect![[r#"
caller1 Function FileId(0) 15..45 18..25 : [34..40]
test_caller Function FileId(0) 95..149 110..121 : [134..140]"#]],
test_caller Function FileId(0) 95..149 110..121 tests : [134..140]"#]],
expect![[]],
);
}
@ -283,7 +283,7 @@ fn caller() {
//- /foo/mod.rs
pub fn callee() {}
"#,
expect![["callee Function FileId(1) 0..18 7..13"]],
expect!["callee Function FileId(1) 0..18 7..13 foo"],
expect![["caller Function FileId(0) 27..56 30..36 : [45..51]"]],
expect![[]],
);
@ -323,7 +323,7 @@ pub fn callee() {}
"#,
expect![["caller Function FileId(0) 27..56 30..36"]],
expect![[]],
expect![["callee Function FileId(1) 0..18 7..13 : [45..51]"]],
expect!["callee Function FileId(1) 0..18 7..13 foo : [45..51]"],
);
}
@ -477,7 +477,7 @@ fn caller() {
S1::callee();
}
"#,
expect![["callee Function FileId(0) 15..27 18..24"]],
expect!["callee Function FileId(0) 15..27 18..24 T1"],
expect![["caller Function FileId(0) 82..115 85..91 : [104..110]"]],
expect![[]],
);

View File

@ -2170,52 +2170,53 @@ mod M {
fn main() { let s$0t = (A(1), B(2), M::C(3) ); }
"#,
expect![[r#"
[
GoToType(
[
HoverGotoTypeData {
mod_path: "test::A",
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 0..14,
focus_range: 7..8,
name: "A",
kind: Struct,
description: "struct A",
},
[
GoToType(
[
HoverGotoTypeData {
mod_path: "test::A",
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 0..14,
focus_range: 7..8,
name: "A",
kind: Struct,
description: "struct A",
},
HoverGotoTypeData {
mod_path: "test::B",
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 15..29,
focus_range: 22..23,
name: "B",
kind: Struct,
description: "struct B",
},
},
HoverGotoTypeData {
mod_path: "test::B",
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 15..29,
focus_range: 22..23,
name: "B",
kind: Struct,
description: "struct B",
},
HoverGotoTypeData {
mod_path: "test::M::C",
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 42..60,
focus_range: 53..54,
name: "C",
kind: Struct,
description: "pub struct C",
},
},
HoverGotoTypeData {
mod_path: "test::M::C",
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 42..60,
focus_range: 53..54,
name: "C",
kind: Struct,
container_name: "M",
description: "pub struct C",
},
],
),
]
"#]],
},
],
),
]
"#]],
);
}
@ -2544,6 +2545,7 @@ pub mod future {
focus_range: 60..66,
name: "Future",
kind: Trait,
container_name: "future",
description: "pub trait Future",
},
},

View File

@ -398,7 +398,7 @@ impl Analysis {
self.with_db(|db| {
symbol_index::world_symbols(db, query)
.into_iter() // xx: should we make this a par iter?
.filter_map(|s| s.try_to_nav(db))
.filter_map(|s| s.def.try_to_nav(db))
.collect::<Vec<_>>()
})
}

View File

@ -4,8 +4,8 @@ use std::fmt;
use either::Either;
use hir::{
symbols::FileSymbol, AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirDisplay,
InFile, LocalSource, ModuleSource, Semantics,
AssocItem, Documentation, FieldSource, HasAttrs, HasContainer, HasSource, HirDisplay, InFile,
LocalSource, ModuleSource,
};
use ide_db::{
base_db::{FileId, FileRange},
@ -15,7 +15,7 @@ use ide_db::{defs::Definition, RootDatabase};
use stdx::never;
use syntax::{
ast::{self, HasName},
match_ast, AstNode, SmolStr, SyntaxNode, TextRange,
AstNode, SmolStr, SyntaxNode, TextRange,
};
/// `NavigationTarget` represents an element in the editor's UI which you can
@ -158,24 +158,6 @@ impl NavigationTarget {
}
}
impl TryToNav for FileSymbol {
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
let full_range = self.loc.original_range(db);
let name_range = self.loc.original_name_range(db)?;
Some(NavigationTarget {
file_id: full_range.file_id,
name: self.name.clone(),
kind: Some(self.kind.into()),
full_range: full_range.range,
focus_range: Some(name_range.range),
container_name: self.container_name.clone(),
description: description_from_symbol(db, self),
docs: None,
})
}
}
impl TryToNav for Definition {
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
match self {
@ -221,38 +203,80 @@ impl TryToNav for hir::ModuleDef {
}
}
pub(crate) trait ToNavFromAst {
pub(crate) trait ToNavFromAst: Sized {
const KIND: SymbolKind;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
_ = db;
None
}
}
fn container_name(db: &RootDatabase, t: impl HasContainer) -> Option<SmolStr> {
match t.container(db) {
hir::ItemContainer::Trait(it) => Some(it.name(db).to_smol_str()),
// FIXME: Handle owners of blocks correctly here
hir::ItemContainer::Module(it) => it.name(db).map(|name| name.to_smol_str()),
_ => None,
}
}
impl ToNavFromAst for hir::Function {
const KIND: SymbolKind = SymbolKind::Function;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
container_name(db, self)
}
}
impl ToNavFromAst for hir::Const {
const KIND: SymbolKind = SymbolKind::Const;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
container_name(db, self)
}
}
impl ToNavFromAst for hir::Static {
const KIND: SymbolKind = SymbolKind::Static;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
container_name(db, self)
}
}
impl ToNavFromAst for hir::Struct {
const KIND: SymbolKind = SymbolKind::Struct;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
container_name(db, self)
}
}
impl ToNavFromAst for hir::Enum {
const KIND: SymbolKind = SymbolKind::Enum;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
container_name(db, self)
}
}
impl ToNavFromAst for hir::Variant {
const KIND: SymbolKind = SymbolKind::Variant;
}
impl ToNavFromAst for hir::Union {
const KIND: SymbolKind = SymbolKind::Union;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
container_name(db, self)
}
}
impl ToNavFromAst for hir::TypeAlias {
const KIND: SymbolKind = SymbolKind::TypeAlias;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
container_name(db, self)
}
}
impl ToNavFromAst for hir::Trait {
const KIND: SymbolKind = SymbolKind::Trait;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
container_name(db, self)
}
}
impl ToNavFromAst for hir::TraitAlias {
const KIND: SymbolKind = SymbolKind::TraitAlias;
fn container_name(self, db: &RootDatabase) -> Option<SmolStr> {
container_name(db, self)
}
}
impl<D> TryToNav for D
@ -269,6 +293,7 @@ where
);
res.docs = self.docs(db);
res.description = Some(self.display(db).to_string());
res.container_name = self.container_name(db);
Some(res)
}
}
@ -544,32 +569,6 @@ impl TryToNav for hir::ConstParam {
}
}
/// Get a description of a symbol.
///
/// e.g. `struct Name`, `enum Name`, `fn Name`
pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> {
let sema = Semantics::new(db);
let node = symbol.loc.syntax(&sema);
match_ast! {
match node {
ast::Fn(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Struct(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Enum(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Trait(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::TraitAlias(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Module(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::TypeAlias(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Const(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Static(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::RecordField(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Variant(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Union(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
_ => None,
}
}
}
fn orig_focus_range(
db: &RootDatabase,
file_id: hir::HirFileId,
@ -614,7 +613,6 @@ fn foo() { enum FooInner { } }
focus_range: 34..42,
name: "FooInner",
kind: Enum,
container_name: "foo",
description: "enum FooInner",
},
]

View File

@ -715,7 +715,7 @@ fn f() {
}
"#,
expect![[r#"
Foo Struct FileId(1) 17..51 28..31
Foo Struct FileId(1) 17..51 28..31 foo
FileId(0) 53..56
FileId(2) 79..82
@ -803,7 +803,7 @@ pub(super) struct Foo$0 {
}
"#,
expect![[r#"
Foo Struct FileId(2) 0..41 18..21
Foo Struct FileId(2) 0..41 18..21 some
FileId(1) 20..23 Import
FileId(1) 47..50
@ -1542,7 +1542,7 @@ fn f() {
FileId(0) 161..165
func Function FileId(0) 137..146 140..144
func Function FileId(0) 137..146 140..144 module
FileId(0) 181..185
"#]],
@ -1581,7 +1581,7 @@ trait Trait {
}
"#,
expect![[r#"
func Function FileId(0) 48..87 51..55
func Function FileId(0) 48..87 51..55 Trait
FileId(0) 74..78
"#]],
@ -1692,7 +1692,7 @@ fn f<T: Trait>() {
}
"#,
expect![[r#"
CONST Const FileId(0) 18..37 24..29
CONST Const FileId(0) 18..37 24..29 Trait
FileId(0) 71..76
FileId(0) 125..130
@ -1721,7 +1721,7 @@ fn f<T: Trait>() {
}
"#,
expect![[r#"
TypeAlias TypeAlias FileId(0) 18..33 23..32
TypeAlias TypeAlias FileId(0) 18..33 23..32 Trait
FileId(0) 66..75
FileId(0) 117..126
@ -1750,7 +1750,7 @@ fn f<T: Trait>() {
}
"#,
expect![[r#"
function Function FileId(0) 18..34 21..29
function Function FileId(0) 18..34 21..29 Trait
FileId(0) 65..73
FileId(0) 112..120
@ -1894,7 +1894,7 @@ fn f<T: Trait>() {
}
"#,
expect![[r#"
TypeAlias TypeAlias FileId(0) 18..33 23..32
TypeAlias TypeAlias FileId(0) 18..33 23..32 Trait
FileId(0) 66..75
FileId(0) 117..126
@ -1950,7 +1950,7 @@ impl Foo for Bar {
fn method() {}
"#,
expect![[r#"
method Function FileId(0) 16..39 19..25
method Function FileId(0) 16..39 19..25 Foo
FileId(0) 101..107
"#]],

View File

@ -2579,6 +2579,7 @@ mod r#mod {
),
full_range: 47..84,
name: "r#for",
container_name: "r#mod",
},
kind: DocTest {
test_id: Path(
@ -2595,6 +2596,7 @@ mod r#mod {
),
full_range: 90..146,
name: "r#struct",
container_name: "r#mod",
},
kind: DocTest {
test_id: Path(