Unnamed repository; edit this file 'description' to name the repository.
wip
| -rw-r--r-- | crates/hir/src/lib.rs | 20 | ||||
| -rw-r--r-- | crates/hir_def/src/nameres.rs | 2 | ||||
| -rw-r--r-- | crates/ide/src/navigation_target.rs | 10 | ||||
| -rw-r--r-- | crates/ide_db/src/items_locator.rs | 3 | ||||
| -rw-r--r-- | crates/ide_db/src/symbol_index.rs | 180 |
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); +} |