Unnamed repository; edit this file 'description' to name the repository.
Jake Heinz 2021-11-27
parent dca8f61 · commit 0447be7
-rw-r--r--crates/hir/src/lib.rs20
-rw-r--r--crates/hir_def/src/nameres.rs2
-rw-r--r--crates/ide/src/navigation_target.rs10
-rw-r--r--crates/ide_db/src/items_locator.rs3
-rw-r--r--crates/ide_db/src/symbol_index.rs180
5 files changed, 172 insertions, 43 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 3946f51642..afa773aaa4 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -40,16 +40,13 @@ use hir_def::{
adt::{ReprKind, VariantData},
body::{BodyDiagnostic, SyntheticSyntax},
expr::{BindingAnnotation, LabelId, Pat, PatId},
- item_tree::ItemTreeNode,
lang_item::LangItemTarget,
nameres,
per_ns::PerNs,
resolver::{HasResolver, Resolver},
- src::HasSource as _,
- AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId,
- DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
- LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
- TypeParamId, UnionId,
+ AssocContainerId, AssocItemId, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
+ FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, LocalEnumVariantId, LocalFieldId,
+ StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
};
use hir_expand::{name::name, MacroCallKind, MacroDefId, MacroDefKind};
use hir_ty::{
@@ -109,10 +106,19 @@ pub use {
attr::{Attr, Attrs, AttrsWithOwner, Documentation},
find_path::PrefixKind,
import_map,
- nameres::ModuleSource,
+ item_scope::ItemScope,
+ item_tree::ItemTreeNode,
+ nameres::{DefMap, ModuleData, ModuleOrigin, ModuleSource},
path::{ModPath, PathKind},
+ src::HasSource as DefHasSource, // xx: I don't like this shadowing of HasSource... :(
type_ref::{Mutability, TypeRef},
visibility::Visibility,
+ AdtId,
+ AssocItemLoc,
+ ItemLoc,
+ Lookup,
+ ModuleDefId,
+ ModuleId,
},
hir_expand::{
name::{known, Name},
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 882d54c996..cf670e5cc1 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -148,7 +148,7 @@ pub enum ModuleOrigin {
}
impl ModuleOrigin {
- fn declaration(&self) -> Option<AstId<ast::Module>> {
+ pub fn declaration(&self) -> Option<AstId<ast::Module>> {
match self {
ModuleOrigin::File { declaration: module, .. }
| ModuleOrigin::Inline { definition: module, .. } => Some(*module),
diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs
index 3121cdd4a2..f7cdb3ce8d 100644
--- a/crates/ide/src/navigation_target.rs
+++ b/crates/ide/src/navigation_target.rs
@@ -4,8 +4,8 @@ use std::fmt;
use either::Either;
use hir::{
- AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirDisplay, InFile, ModuleSource,
- Semantics,
+ db::AstDatabase, AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirDisplay,
+ InFile, ModuleSource, Semantics,
};
use ide_db::{
base_db::{FileId, FileRange},
@@ -170,7 +170,7 @@ impl NavigationTarget {
impl ToNav for FileSymbol {
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
NavigationTarget {
- file_id: self.file_id,
+ file_id: self.file_id.original_file(db),
name: self.name.clone(),
kind: Some(match self.kind {
FileSymbolKind::Function => SymbolKind::Function,
@@ -517,8 +517,8 @@ impl TryToNav for hir::ConstParam {
/// 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 parse = sema.parse(symbol.file_id);
- let node = symbol.ptr.to_node(parse.syntax());
+ let syntax = sema.db.parse_or_expand(symbol.file_id)?;
+ let node = symbol.ptr.to_node(&syntax);
match_ast! {
match node {
diff --git a/crates/ide_db/src/items_locator.rs b/crates/ide_db/src/items_locator.rs
index a3ea3edc97..33bb14adde 100644
--- a/crates/ide_db/src/items_locator.rs
+++ b/crates/ide_db/src/items_locator.rs
@@ -4,6 +4,7 @@
//! are located in different caches, with different APIs.
use either::Either;
use hir::{
+ db::AstDatabase,
import_map::{self, ImportKind},
AsAssocItem, Crate, ItemInNs, Semantics,
};
@@ -135,7 +136,7 @@ fn get_name_definition(
let _p = profile::span("get_name_definition");
let file_id = import_candidate.file_id;
- let candidate_node = import_candidate.ptr.to_node(sema.parse(file_id).syntax());
+ let candidate_node = import_candidate.ptr.to_node(&sema.db.parse_or_expand(file_id)?);
let candidate_name_node = if candidate_node.kind() != NAME {
candidate_node.children().find(|it| it.kind() == NAME)?
} else {
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs
index 54ceafa67f..5bea5837a7 100644
--- a/crates/ide_db/src/symbol_index.rs
+++ b/crates/ide_db/src/symbol_index.rs
@@ -33,7 +33,10 @@ use base_db::{
CrateId, FileId, SourceDatabaseExt, SourceRootId,
};
use fst::{self, Streamer};
-use hir::db::DefDatabase;
+use hir::{
+ db::DefDatabase, AdtId, AssocItemLoc, DefHasSource, HirFileId, ItemLoc, ItemScope,
+ ItemTreeNode, Lookup, ModuleData, ModuleDefId, ModuleId,
+};
use rayon::prelude::*;
use rustc_hash::{FxHashMap, FxHashSet};
use syntax::{
@@ -202,21 +205,29 @@ pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<Fil
// that instead?
let def_map = db.crate_def_map(krate);
- let mut files = Vec::new();
- let mut modules = vec![def_map.root()];
- while let Some(module) = modules.pop() {
- let data = &def_map[module];
- files.extend(data.origin.file_id());
- modules.extend(data.children.values());
- }
-
- let snap = Snap(db.snapshot());
-
- let buf = files
- .par_iter()
- .map_with(snap, |db, &file_id| db.0.file_symbols(file_id))
- .collect::<Vec<_>>();
- let buf = buf.iter().map(|it| &**it).collect::<Vec<_>>();
+ // let mut files = Vec::new();
+ // let mut modules = vec![def_map.root()];
+ // while let Some(module) = modules.pop() {
+ // let data = &def_map[module];
+ // files.extend(data.origin.file_id());
+ // modules.extend(data.children.values());
+ // }
+
+ // let snap = Snap(db.snapshot());
+
+ // let buf = files
+ // .par_iter()
+ // .map_with(snap, |db, &file_id| db.0.file_symbols(file_id))
+ // .collect::<Vec<_>>();
+
+ // todo: make this fast!!!
+ // how do i salsa this?
+
+ let buf: Vec<_> = def_map
+ .modules()
+ .map(|(_, module_data)| SymbolIndex::new(module_data_to_file_symbols(db, module_data)))
+ .collect();
+ let buf = buf.iter().collect::<Vec<_>>();
query.search(&buf)
}
@@ -364,7 +375,7 @@ impl Query {
/// possible.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FileSymbol {
- pub file_id: FileId,
+ pub file_id: HirFileId,
pub name: SmolStr,
pub kind: FileSymbolKind,
pub range: TextRange,
@@ -456,23 +467,134 @@ 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,
- MACRO_DEF => FileSymbolKind::Macro,
- UNION => FileSymbolKind::Union,
+ FN => FileSymbolKind::Function, // FunctionId
+ STRUCT => FileSymbolKind::Struct, // AdtId::StructId
+ ENUM => FileSymbolKind::Enum, // AdtId::EnumId
+ TRAIT => FileSymbolKind::Trait, // TraitId
+ MODULE => FileSymbolKind::Module, // ModuleId
+ TYPE_ALIAS => FileSymbolKind::TypeAlias, // TypeAliasId
+ CONST => FileSymbolKind::Const, // ConstId
+ STATIC => FileSymbolKind::Static, // StaticId
+ MACRO_RULES => FileSymbolKind::Macro, // via ItemScope::macros
+ MACRO_DEF => FileSymbolKind::Macro, // via ItemScope::macros
+ UNION => FileSymbolKind::Union, // AdtId::UnionId
kind => unreachable!("{:?}", kind),
},
range: node.text_range(),
ptr,
- file_id,
+ file_id: file_id.into(),
name_range: Some(name_range),
container_name: None,
})
}
+
+fn module_data_to_file_symbols(db: &dyn DefDatabase, module_data: &ModuleData) -> Vec<FileSymbol> {
+ let mut symbols = Vec::new();
+ collect_symbols_from_item_scope(db, &mut symbols, &module_data.scope);
+ // todo: collect macros from scope.macros().
+ symbols
+}
+
+fn collect_symbols_from_item_scope(
+ db: &dyn DefDatabase,
+ symbols: &mut Vec<FileSymbol>,
+ scope: &ItemScope,
+) {
+ // todo: dedupe code.
+ fn decl_assoc<L, T>(db: &dyn DefDatabase, id: L, kind: FileSymbolKind) -> Option<FileSymbol>
+ where
+ L: Lookup<Data = AssocItemLoc<T>>,
+ T: ItemTreeNode,
+ <T as ItemTreeNode>::Source: HasName,
+ {
+ let loc = id.lookup(db);
+ let source = loc.source(db);
+ let name = source.value.name()?;
+ let file_id = loc.id.file_id();
+
+ let name_range = name.syntax().text_range();
+ let name = name.text().into();
+ let ptr = SyntaxNodePtr::new(source.value.syntax());
+
+ Some(FileSymbol {
+ name,
+ kind,
+ range: source.value.syntax().text_range(),
+ // todo: fill out based on loc.container.
+ container_name: None,
+ file_id,
+ name_range: Some(name_range),
+ ptr,
+ })
+ }
+ fn decl<L, T>(db: &dyn DefDatabase, id: L, kind: FileSymbolKind) -> Option<FileSymbol>
+ where
+ L: Lookup<Data = ItemLoc<T>>,
+ T: ItemTreeNode,
+ <T as ItemTreeNode>::Source: HasName,
+ {
+ let loc = id.lookup(db);
+ let source = loc.source(db);
+ let name = source.value.name()?;
+ let file_id = loc.id.file_id();
+ let name_range = name.syntax().text_range();
+ let name = name.text().into();
+ let ptr = SyntaxNodePtr::new(source.value.syntax());
+
+ Some(FileSymbol {
+ name,
+ kind,
+ range: source.value.syntax().text_range(),
+ container_name: None,
+ file_id,
+ name_range: Some(name_range),
+ ptr,
+ })
+ }
+
+ fn decl_module(db: &dyn DefDatabase, module_id: ModuleId) -> Option<FileSymbol> {
+ let def_map = module_id.def_map(db);
+ let module_data = &def_map[module_id.local_id];
+ let declaration = module_data.origin.declaration()?;
+ let file_id = match module_data.origin.file_id() {
+ Some(file_id) => file_id.into(),
+ None => declaration.file_id,
+ };
+
+ let module = declaration.to_node(db.upcast());
+ let name = module.name()?;
+ let name_range = name.syntax().text_range();
+ let name = name.text().into();
+ let ptr = SyntaxNodePtr::new(module.syntax());
+
+ Some(FileSymbol {
+ name,
+ kind: FileSymbolKind::Module,
+ range: module.syntax().text_range(),
+ container_name: None,
+ file_id,
+ name_range: Some(name_range),
+ ptr,
+ })
+ }
+
+ let symbols_iter = scope.declarations().filter_map(|module_def_id| match module_def_id {
+ ModuleDefId::ModuleId(module_id) => decl_module(db, module_id),
+ ModuleDefId::FunctionId(function_id) => {
+ decl_assoc(db, function_id, FileSymbolKind::Function)
+ }
+ ModuleDefId::AdtId(AdtId::StructId(struct_id)) => {
+ decl(db, struct_id, FileSymbolKind::Struct)
+ }
+ ModuleDefId::AdtId(AdtId::EnumId(enum_id)) => decl(db, enum_id, FileSymbolKind::Enum),
+ ModuleDefId::AdtId(AdtId::UnionId(union_id)) => decl(db, union_id, FileSymbolKind::Union),
+ ModuleDefId::EnumVariantId(_) => None,
+ ModuleDefId::ConstId(const_id) => decl_assoc(db, const_id, FileSymbolKind::Const),
+ ModuleDefId::StaticId(static_id) => decl(db, static_id, FileSymbolKind::Static),
+ ModuleDefId::TraitId(trait_id) => decl(db, trait_id, FileSymbolKind::Trait),
+ ModuleDefId::TypeAliasId(alias_id) => decl_assoc(db, alias_id, FileSymbolKind::TypeAlias),
+ ModuleDefId::BuiltinType(_) => None,
+ });
+
+ symbols.extend(symbols_iter);
+}