From 3ab1519cb27b927074ed7fbbb18a856e6e7fabb8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 23 Jan 2019 23:14:13 +0300 Subject: Change ids strategy this is a part of larghish hir refactoring which aims to * replace per-source-root module trees with per crate trees * switch from a monotyped DedId to type-specific ids --- crates/ra_db/src/input.rs | 12 ++ crates/ra_db/src/lib.rs | 2 +- crates/ra_hir/src/adt.rs | 2 +- crates/ra_hir/src/code_model_api.rs | 32 +++- crates/ra_hir/src/code_model_impl/krate.rs | 24 +-- crates/ra_hir/src/code_model_impl/module.rs | 180 +++++++++------------ crates/ra_hir/src/db.rs | 36 ++--- crates/ra_hir/src/ids.rs | 22 +-- crates/ra_hir/src/impl_block.rs | 25 ++- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/mock.rs | 13 +- crates/ra_hir/src/module_tree.rs | 36 ++--- crates/ra_hir/src/nameres.rs | 56 +++---- crates/ra_hir/src/nameres/lower.rs | 74 +++------ crates/ra_hir/src/nameres/tests.rs | 35 ++-- crates/ra_hir/src/query_definitions.rs | 20 ++- crates/ra_hir/src/source_binder.rs | 28 ++-- crates/ra_hir/src/ty.rs | 21 +-- crates/ra_hir/src/ty/method_resolution.rs | 26 ++- crates/ra_ide_api/src/completion/complete_path.rs | 37 +++-- .../ra_ide_api/src/completion/completion_item.rs | 61 +++---- crates/ra_ide_api/src/db.rs | 1 + crates/ra_ide_api/src/goto_definition.rs | 4 +- crates/ra_ide_api/src/navigation_target.rs | 13 +- crates/ra_ide_api/src/rename.rs | 25 +-- .../src/snapshots/tests__rename_mod.snap | 10 +- 26 files changed, 366 insertions(+), 431 deletions(-) diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index b5d63e820..9825d52cf 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs @@ -160,6 +160,7 @@ pub trait FilesDatabase: salsa::Database { /// Contents of the source root. #[salsa::input] fn source_root(&self, id: SourceRootId) -> Arc; + fn source_root_crates(&self, id: SourceRootId) -> Arc>; /// The set of "local" (that is, from the current workspace) roots. /// Files in local roots are assumed to change frequently. #[salsa::input] @@ -173,6 +174,17 @@ pub trait FilesDatabase: salsa::Database { fn crate_graph(&self) -> Arc; } +fn source_root_crates(db: &impl FilesDatabase, id: SourceRootId) -> Arc> { + let root = db.source_root(id); + let graph = db.crate_graph(); + let res = root + .files + .values() + .filter_map(|&it| graph.crate_id_for_crate_root(it)) + .collect::>(); + Arc::new(res) +} + #[cfg(test)] mod tests { use super::{CrateGraph, FileId, SmolStr}; diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs index 32d7e09b9..84759c75a 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs @@ -13,7 +13,7 @@ pub use crate::{ cancellation::Canceled, input::{ FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, - FileTextQuery, FileSourceRootQuery, SourceRootQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery, + FileTextQuery, FileSourceRootQuery, SourceRootQuery, SourceRootCratesQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery, FileRelativePathQuery }, loc2id::LocationIntener, diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index ab1c428db..4cca09351 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -64,9 +64,9 @@ fn get_def_id( ..same_file_loc.source_item_id }; let loc = DefLoc { + module: same_file_loc.module, kind: expected_kind, source_item_id, - ..*same_file_loc }; loc.id(db) } diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 3ff07bd60..f59a60c07 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -14,13 +14,14 @@ use crate::{ adt::VariantData, generics::GenericParams, code_model_impl::def_id_to_ast, - docs::{Documentation, Docs, docs_from_ast} + docs::{Documentation, Docs, docs_from_ast}, + module_tree::ModuleId, }; /// hir::Crate describes a single crate. It's the main interface with which /// a crate's dependencies interact. Mostly, it should be just a proxy for the /// root module. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Crate { pub(crate) crate_id: CrateId, } @@ -45,7 +46,6 @@ impl Crate { #[derive(Debug)] pub enum Def { - Module(Module), Struct(Struct), Enum(Enum), EnumVariant(EnumVariant), @@ -57,9 +57,29 @@ pub enum Def { Item, } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Module { - pub(crate) def_id: DefId, + pub(crate) krate: CrateId, + pub(crate) module_id: ModuleId, +} + +/// The defs which can be visible in the module. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ModuleDef { + Module(Module), + Def(DefId), +} + +impl Into for Module { + fn into(self) -> ModuleDef { + ModuleDef::Module(self) + } +} + +impl Into for DefId { + fn into(self) -> ModuleDef { + ModuleDef::Def(self) + } } pub enum ModuleSource { @@ -149,7 +169,7 @@ impl Module { self.scope_impl(db) } - pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs { + pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs { self.resolve_path_impl(db, path) } diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs index 8c6e34873..cdd30b402 100644 --- a/crates/ra_hir/src/code_model_impl/krate.rs +++ b/crates/ra_hir/src/code_model_impl/krate.rs @@ -1,7 +1,7 @@ use ra_db::CrateId; use crate::{ - HirFileId, Crate, CrateDependency, AsName, DefLoc, DefKind, Module, SourceItemId, + Crate, CrateDependency, AsName, Module, db::HirDatabase, }; @@ -21,27 +21,13 @@ impl Crate { .collect() } pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option { - let crate_graph = db.crate_graph(); - let file_id = crate_graph.crate_root(self.crate_id); - let source_root_id = db.file_source_root(file_id); - let file_id = HirFileId::from(file_id); - let module_tree = db.module_tree(source_root_id); - // FIXME: teach module tree about crate roots instead of guessing - let source = SourceItemId { - file_id, - item_id: None, - }; - let module_id = module_tree.find_module_by_source(source)?; + let module_tree = db.module_tree(self.crate_id); + let module_id = module_tree.modules().next()?; - let def_loc = DefLoc { - kind: DefKind::Module, - source_root_id, + let module = Module { + krate: self.crate_id, module_id, - source_item_id: module_id.source(&module_tree), }; - let def_id = def_loc.id(db); - - let module = Module::new(def_id); Some(module) } } diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index d94079f11..5d00e905b 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs @@ -1,52 +1,33 @@ -use ra_db::{SourceRootId, FileId}; -use ra_syntax::{ast, SyntaxNode, AstNode, TreeArc}; +use ra_db::FileId; +use ra_syntax::{ast, SyntaxNode, TreeArc}; use crate::{ - Module, ModuleSource, Problem, - Crate, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def, + Module, ModuleSource, Problem, ModuleDef, + Crate, Name, Path, PathKind, PerNs, Def, module_tree::ModuleId, nameres::{ModuleScope, lower::ImportId}, db::HirDatabase, }; impl Module { - pub(crate) fn new(def_id: DefId) -> Self { - crate::code_model_api::Module { def_id } - } - - pub(crate) fn from_module_id( - db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, - ) -> Self { - let module_tree = db.module_tree(source_root_id); - let def_loc = DefLoc { - kind: DefKind::Module, - source_root_id, + fn with_module_id(&self, module_id: ModuleId) -> Module { + Module { module_id, - source_item_id: module_id.source(&module_tree), - }; - let def_id = def_loc.id(db); - Module::new(def_id) + krate: self.krate, + } } pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let link = loc.module_id.parent_link(&module_tree)?; + let module_tree = db.module_tree(self.krate); + let link = self.module_id.parent_link(&module_tree)?; Some(link.name(&module_tree).clone()) } pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { - let loc = self.def_id.loc(db); - let file_id = loc.source_item_id.file_id.as_original_file(); - let syntax_node = db.file_item(loc.source_item_id); - let module_source = if let Some(source_file) = ast::SourceFile::cast(&syntax_node) { - ModuleSource::SourceFile(source_file.to_owned()) - } else { - let module = ast::Module::cast(&syntax_node).unwrap(); - ModuleSource::Module(module.to_owned()) - }; + let module_tree = db.module_tree(self.krate); + let source = self.module_id.source(&module_tree); + let module_source = ModuleSource::from_source_item_id(db, source); + let file_id = source.file_id.as_original_file(); (file_id, module_source) } @@ -54,9 +35,8 @@ impl Module { &self, db: &impl HirDatabase, ) -> Option<(FileId, TreeArc)> { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let link = loc.module_id.parent_link(&module_tree)?; + let module_tree = db.module_tree(self.krate); + let link = self.module_id.parent_link(&module_tree)?; let file_id = link .owner(&module_tree) .source(&module_tree) @@ -71,85 +51,67 @@ impl Module { db: &impl HirDatabase, import: ImportId, ) -> TreeArc { - let loc = self.def_id.loc(db); - let source_map = db.lower_module_source_map(loc.source_root_id, loc.module_id); + let source_map = db.lower_module_source_map(self.clone()); let (_, source) = self.definition_source(db); source_map.get(&source, import) } - pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Option { - let root = self.crate_root(db); - let loc = root.def_id.loc(db); - let file_id = loc.source_item_id.file_id.as_original_file(); - - let crate_graph = db.crate_graph(); - let crate_id = crate_graph.crate_id_for_crate_root(file_id)?; - Some(Crate::new(crate_id)) + pub(crate) fn krate_impl(&self, _db: &impl HirDatabase) -> Option { + Some(Crate::new(self.krate)) } pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let module_id = loc.module_id.crate_root(&module_tree); - Module::from_module_id(db, loc.source_root_id, module_id) + let module_tree = db.module_tree(self.krate); + let module_id = self.module_id.crate_root(&module_tree); + self.with_module_id(module_id) } /// Finds a child module with the specified name. pub(crate) fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let child_id = loc.module_id.child(&module_tree, name)?; - Some(Module::from_module_id(db, loc.source_root_id, child_id)) + let module_tree = db.module_tree(self.krate); + let child_id = self.module_id.child(&module_tree, name)?; + Some(self.with_module_id(child_id)) } /// Iterates over all child modules. pub(crate) fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator { - // FIXME this should be implementable without collecting into a vec, but - // it's kind of hard since the iterator needs to keep a reference to the - // module tree. - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let children = loc + let module_tree = db.module_tree(self.krate); + let children = self .module_id .children(&module_tree) - .map(|(_, module_id)| Module::from_module_id(db, loc.source_root_id, module_id)) + .map(|(_, module_id)| self.with_module_id(module_id)) .collect::>(); children.into_iter() } pub(crate) fn parent_impl(&self, db: &impl HirDatabase) -> Option { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - let parent_id = loc.module_id.parent(&module_tree)?; - Some(Module::from_module_id(db, loc.source_root_id, parent_id)) + let module_tree = db.module_tree(self.krate); + let parent_id = self.module_id.parent(&module_tree)?; + Some(self.with_module_id(parent_id)) } /// Returns a `ModuleScope`: a set of items, visible in this module. pub(crate) fn scope_impl(&self, db: &impl HirDatabase) -> ModuleScope { - let loc = self.def_id.loc(db); - let item_map = db.item_map(loc.source_root_id); - item_map.per_module[&loc.module_id].clone() + let item_map = db.item_map(self.krate); + item_map.per_module[&self.module_id].clone() } - pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs { - let mut curr_per_ns = PerNs::types( - match path.kind { - PathKind::Crate => self.crate_root(db), - PathKind::Self_ | PathKind::Plain => self.clone(), - PathKind::Super => { - if let Some(p) = self.parent(db) { - p - } else { - return PerNs::none(); - } - } - PathKind::Abs => { - // TODO: absolute use is not supported + pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs { + let mut curr_per_ns: PerNs = PerNs::types(match path.kind { + PathKind::Crate => self.crate_root(db).into(), + PathKind::Self_ | PathKind::Plain => self.clone().into(), + PathKind::Super => { + if let Some(p) = self.parent(db) { + p.into() + } else { return PerNs::none(); } } - .def_id, - ); + PathKind::Abs => { + // TODO: absolute use is not supported + return PerNs::none(); + } + }); for segment in path.segments.iter() { let curr = match curr_per_ns.as_ref().take_types() { @@ -164,32 +126,39 @@ impl Module { } }; // resolve segment in curr - curr_per_ns = match curr.resolve(db) { - Def::Module(m) => { + + curr_per_ns = match curr { + ModuleDef::Module(m) => { let scope = m.scope(db); match scope.get(&segment.name) { - Some(r) => r.def_id, + Some(r) => r.def_id.clone(), None => PerNs::none(), } } - Def::Enum(e) => { - // enum variant - let matching_variant = e - .variants(db) - .into_iter() - .find(|(n, _variant)| n == &segment.name); - - match matching_variant { - Some((_n, variant)) => PerNs::both(variant.def_id(), e.def_id()), - None => PerNs::none(), + ModuleDef::Def(def) => { + match def.resolve(db) { + Def::Enum(e) => { + // enum variant + let matching_variant = e + .variants(db) + .into_iter() + .find(|(n, _variant)| n == &segment.name); + + match matching_variant { + Some((_n, variant)) => { + PerNs::both(variant.def_id().into(), e.def_id().into()) + } + None => PerNs::none(), + } + } + _ => { + // could be an inherent method call in UFCS form + // (`Struct::method`), or some other kind of associated + // item... Which we currently don't handle (TODO) + PerNs::none() + } } } - _ => { - // could be an inherent method call in UFCS form - // (`Struct::method`), or some other kind of associated - // item... Which we currently don't handle (TODO) - PerNs::none() - } }; } curr_per_ns @@ -199,8 +168,7 @@ impl Module { &self, db: &impl HirDatabase, ) -> Vec<(TreeArc, Problem)> { - let loc = self.def_id.loc(db); - let module_tree = db.module_tree(loc.source_root_id); - loc.module_id.problems(&module_tree, db) + let module_tree = db.module_tree(self.krate); + self.module_id.problems(&module_tree, db) } } diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index cc03da1e2..0898daa3c 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -1,15 +1,15 @@ use std::sync::Arc; use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; -use ra_db::{SourceRootId, SyntaxDatabase, salsa}; +use ra_db::{SyntaxDatabase, CrateId, salsa}; use crate::{ - HirInterner, DefId, MacroCallId, Name, HirFileId, - SourceFileItems, SourceItemId, Crate, + DefId, MacroCallId, Name, HirFileId, + SourceFileItems, SourceItemId, Crate, Module, HirInterner, query_definitions, FnSignature, FnScopes, macros::MacroExpansion, - module_tree::{ModuleId, ModuleTree}, + module_tree::ModuleTree, nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, adt::{StructData, EnumData, EnumVariantData}, @@ -56,38 +56,22 @@ pub trait HirDatabase: SyntaxDatabase + AsRef { fn submodules(&self, source: SourceItemId) -> Arc>; #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)] - fn lower_module( - &self, - source_root_id: SourceRootId, - module_id: ModuleId, - ) -> (Arc, Arc); + fn lower_module(&self, module: Module) -> (Arc, Arc); #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_module_query)] - fn lower_module_module( - &self, - source_root_id: SourceRootId, - module_id: ModuleId, - ) -> Arc; + fn lower_module_module(&self, module: Module) -> Arc; #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_source_map_query)] - fn lower_module_source_map( - &self, - source_root_id: SourceRootId, - module_id: ModuleId, - ) -> Arc; + fn lower_module_source_map(&self, module: Module) -> Arc; #[salsa::invoke(query_definitions::item_map)] - fn item_map(&self, source_root_id: SourceRootId) -> Arc; + fn item_map(&self, crate_id: CrateId) -> Arc; #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)] - fn module_tree(&self, source_root_id: SourceRootId) -> Arc; + fn module_tree(&self, crate_id: CrateId) -> Arc; #[salsa::invoke(crate::impl_block::impls_in_module)] - fn impls_in_module( - &self, - source_root_id: SourceRootId, - module_id: ModuleId, - ) -> Arc; + fn impls_in_module(&self, module: Module) -> Arc; #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] fn impls_in_crate(&self, krate: Crate) -> Arc; diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 43f0e81f9..99f04e4ef 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -1,11 +1,10 @@ -use ra_db::{SourceRootId, LocationIntener, FileId}; +use ra_db::{LocationIntener, FileId}; use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ HirDatabase, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate, Module, Trait, Type, Static, Const, - module_tree::ModuleId, }; #[derive(Debug, Default)] @@ -110,10 +109,9 @@ impl From for HirFileId { pub struct MacroCallId(RawId); impl_arena_id!(MacroCallId); -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroCallLoc { - pub(crate) source_root_id: SourceRootId, - pub(crate) module_id: ModuleId, + pub(crate) module: Module, pub(crate) source_item_id: SourceItemId, } @@ -139,14 +137,12 @@ impl_arena_id!(DefId); #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DefLoc { pub(crate) kind: DefKind, - pub(crate) source_root_id: SourceRootId, - pub(crate) module_id: ModuleId, + pub(crate) module: Module, pub(crate) source_item_id: SourceItemId, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub(crate) enum DefKind { - Module, Function, Struct, Enum, @@ -177,10 +173,6 @@ impl DefId { pub fn resolve(self, db: &impl HirDatabase) -> Def { let loc = self.loc(db); match loc.kind { - DefKind::Module => { - let module = Module::from_module_id(db, loc.source_root_id, loc.module_id); - Def::Module(module) - } DefKind::Function => { let function = Function::new(self); Def::Function(function) @@ -221,8 +213,7 @@ impl DefId { /// For a module, returns that module; for any other def, returns the containing module. pub fn module(self, db: &impl HirDatabase) -> Module { - let loc = self.loc(db); - Module::from_module_id(db, loc.source_root_id, loc.module_id) + self.loc(db).module } /// Returns the containing crate. @@ -232,8 +223,7 @@ impl DefId { /// Returns the containing impl block, if this is an impl item. pub fn impl_block(self, db: &impl HirDatabase) -> Option { - let loc = self.loc(db); - let module_impls = db.impls_in_module(loc.source_root_id, loc.module_id); + let module_impls = db.impls_in_module(self.loc(db).module); ImplBlock::containing(module_impls, self) } } diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 551d0d149..ba8b84da2 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -3,14 +3,12 @@ use rustc_hash::FxHashMap; use ra_arena::{Arena, RawId, impl_arena_id}; use ra_syntax::ast::{self, AstNode}; -use ra_db::{SourceRootId}; use crate::{ DefId, DefLoc, DefKind, SourceItemId, SourceFileItems, - Function, HirInterner, + Function, HirFileId, HirInterner, db::HirDatabase, type_ref::TypeRef, - module_tree::ModuleId, }; use crate::code_model_api::{Module, ModuleSource}; @@ -67,13 +65,13 @@ pub struct ImplData { impl ImplData { pub(crate) fn from_ast( db: &impl AsRef, + file_id: HirFileId, file_items: &SourceFileItems, - module: &Module, + module: Module, node: &ast::ImplBlock, ) -> Self { let target_trait = node.target_trait().map(TypeRef::from_ast); let target_type = TypeRef::from_ast_opt(node.target_type()); - let module_loc = module.def_id.loc(db); let items = if let Some(item_list) = node.item_list() { item_list .impl_items() @@ -85,13 +83,13 @@ impl ImplData { }; let item_id = file_items.id_of_unchecked(item_node.syntax()); let source_item_id = SourceItemId { - file_id: module_loc.source_item_id.file_id, + file_id, item_id: Some(item_id), }; let def_loc = DefLoc { + module, kind, source_item_id, - ..module_loc }; let def_id = def_loc.id(db); match item_node.kind() { @@ -168,6 +166,7 @@ impl ModuleImplBlocks { fn collect(&mut self, db: &impl HirDatabase, module: Module) { let (file_id, module_source) = module.definition_source(db); + let file_id: HirFileId = file_id.into(); let node = match &module_source { ModuleSource::SourceFile(node) => node.syntax(), ModuleSource::Module(node) => node @@ -176,10 +175,11 @@ impl ModuleImplBlocks { .syntax(), }; - let source_file_items = db.file_items(file_id.into()); + let source_file_items = db.file_items(file_id); for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { - let impl_block = ImplData::from_ast(db, &source_file_items, &module, impl_block_ast); + let impl_block = + ImplData::from_ast(db, file_id, &source_file_items, module, impl_block_ast); let id = self.impls.alloc(impl_block); for impl_item in &self.impls[id].items { self.impls_by_def.insert(impl_item.def_id(), id); @@ -188,13 +188,8 @@ impl ModuleImplBlocks { } } -pub(crate) fn impls_in_module( - db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, -) -> Arc { +pub(crate) fn impls_in_module(db: &impl HirDatabase, module: Module) -> Arc { let mut result = ModuleImplBlocks::new(); - let module = Module::from_module_id(db, source_root_id, module_id); result.collect(db, module); Arc::new(result) } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 87b5a8b8a..a6246a5e9 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -52,7 +52,7 @@ pub use self::{ pub use self::code_model_api::{ Crate, CrateDependency, Def, - Module, ModuleSource, Problem, + Module, ModuleDef, ModuleSource, Problem, Struct, Enum, EnumVariant, Function, FnSignature, ScopeEntryWithSyntax, StructField, diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 4145c8048..361366f6a 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs @@ -35,10 +35,6 @@ impl MockDatabase { let file_id = db.add_file(WORKSPACE, &mut source_root, "/main.rs", text); db.query_mut(ra_db::SourceRootQuery) .set(WORKSPACE, Arc::new(source_root.clone())); - - let mut crate_graph = CrateGraph::default(); - crate_graph.add_crate_root(file_id); - db.set_crate_graph(crate_graph); (db, source_root, file_id) } @@ -97,6 +93,8 @@ impl MockDatabase { text: &str, ) -> FileId { assert!(path.starts_with('/')); + let is_crate_root = path == "/lib.rs" || path == "/main.rs"; + let path = RelativePathBuf::from_path(&path[1..]).unwrap(); let file_id = FileId(self.file_counter); self.file_counter += 1; @@ -107,6 +105,12 @@ impl MockDatabase { self.query_mut(ra_db::FileSourceRootQuery) .set(file_id, source_root_id); source_root.files.insert(path, file_id); + + if is_crate_root { + let mut crate_graph = CrateGraph::default(); + crate_graph.add_crate_root(file_id); + self.set_crate_graph(crate_graph); + } file_id } @@ -202,6 +206,7 @@ salsa::database_storage! { fn file_relative_path() for ra_db::FileRelativePathQuery; fn file_source_root() for ra_db::FileSourceRootQuery; fn source_root() for ra_db::SourceRootQuery; + fn source_root_crates() for ra_db::SourceRootCratesQuery; fn local_roots() for ra_db::LocalRootsQuery; fn library_roots() for ra_db::LibraryRootsQuery; fn crate_graph() for ra_db::CrateGraphQuery; diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs index b201bf69b..c00834c4c 100644 --- a/crates/ra_hir/src/module_tree.rs +++ b/crates/ra_hir/src/module_tree.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use rustc_hash::{FxHashMap, FxHashSet}; use arrayvec::ArrayVec; use relative_path::RelativePathBuf; -use ra_db::{FileId, SourceRootId, SourceRoot}; +use ra_db::{FileId, SourceRoot, CrateId}; use ra_syntax::{ SyntaxNode, TreeArc, algo::generate, @@ -126,13 +126,10 @@ struct LinkData { } impl ModuleTree { - pub(crate) fn module_tree_query( - db: &impl HirDatabase, - source_root: SourceRootId, - ) -> Arc { + pub(crate) fn module_tree_query(db: &impl HirDatabase, crate_id: CrateId) -> Arc { db.check_canceled(); let mut res = ModuleTree::default(); - res.init(db, source_root); + res.init_crate(db, crate_id); Arc::new(res) } @@ -145,24 +142,21 @@ impl ModuleTree { Some(res) } - fn init(&mut self, db: &impl HirDatabase, source_root: SourceRootId) { + fn init_crate(&mut self, db: &impl HirDatabase, crate_id: CrateId) { + let crate_graph = db.crate_graph(); + let file_id = crate_graph.crate_root(crate_id); + let source_root_id = db.file_source_root(file_id); + let mut roots = FxHashMap::default(); let mut visited = FxHashSet::default(); - let source_root = db.source_root(source_root); - for &file_id in source_root.files.values() { - let source = SourceItemId { - file_id: file_id.into(), - item_id: None, - }; - if visited.contains(&source) { - continue; // TODO: use explicit crate_roots here - } - assert!(!roots.contains_key(&file_id)); - let module_id = - self.init_subtree(db, &source_root, &mut visited, &mut roots, None, source); - roots.insert(file_id, module_id); - } + let source_root = db.source_root(source_root_id); + let source = SourceItemId { + file_id: file_id.into(), + item_id: None, + }; + let module_id = self.init_subtree(db, &source_root, &mut visited, &mut roots, None, source); + roots.insert(file_id, module_id); } fn init_subtree( diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 1d163edf7..a3bc98958 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -16,19 +16,19 @@ //! structure itself is modified. pub(crate) mod lower; -use crate::nameres::lower::*; - use std::sync::Arc; +use ra_db::CrateId; use rustc_hash::{FxHashMap, FxHashSet}; -use ra_db::SourceRootId; use crate::{ - DefId, DefLoc, DefKind, + Module, ModuleDef, Path, PathKind, HirDatabase, Crate, Name, module_tree::{ModuleId, ModuleTree}, +//FIXME: deglobify + nameres::lower::*, }; /// `ItemMap` is the result of name resolution. It contains, for each @@ -58,7 +58,7 @@ impl ModuleScope { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Resolution { /// None for unresolved - pub def_id: PerNs, + pub def_id: PerNs, /// ident by which this is imported into local scope. pub import: Option, } @@ -152,7 +152,7 @@ impl PerNs { pub(crate) struct Resolver<'a, DB> { db: &'a DB, input: &'a FxHashMap>, - source_root: SourceRootId, + krate: CrateId, module_tree: Arc, processed_imports: FxHashSet<(ModuleId, ImportId)>, result: ItemMap, @@ -165,13 +165,13 @@ where pub(crate) fn new( db: &'a DB, input: &'a FxHashMap>, - source_root: SourceRootId, - module_tree: Arc, + krate: CrateId, ) -> Resolver<'a, DB> { + let module_tree = db.module_tree(krate); Resolver { db, input, - source_root, + krate, module_tree, processed_imports: FxHashSet::default(), result: ItemMap::default(), @@ -210,7 +210,7 @@ where let krate = Crate::new(crate_id); for dep in krate.dependencies(self.db) { if let Some(module) = dep.krate.root_module(self.db) { - let def_id = module.def_id; + let def_id = module.into(); self.add_module_item( &mut module_items, dep.name.clone(), @@ -244,20 +244,22 @@ where // Populate modules for (name, module_id) in module_id.children(&self.module_tree) { - let def_loc = DefLoc { - kind: DefKind::Module, - source_root_id: self.source_root, + let module = Module { module_id, - source_item_id: module_id.source(&self.module_tree), + krate: self.krate, }; - let def_id = def_loc.id(self.db); - self.add_module_item(&mut module_items, name, PerNs::types(def_id)); + self.add_module_item(&mut module_items, name, PerNs::types(module.into())); } self.result.per_module.insert(module_id, module_items); } - fn add_module_item(&self, module_items: &mut ModuleScope, name: Name, def_id: PerNs) { + fn add_module_item( + &self, + module_items: &mut ModuleScope, + name: Name, + def_id: PerNs, + ) { let resolution = Resolution { def_id, import: None, @@ -329,17 +331,11 @@ where ); return false; }; - curr = match type_def_id.loc(self.db) { - DefLoc { - kind: DefKind::Module, - module_id: target_module_id, - source_root_id, - .. - } => { - if source_root_id == self.source_root { - target_module_id + curr = match type_def_id { + ModuleDef::Module(module) => { + if module.krate == self.krate { + module.module_id } else { - let module = crate::code_model_api::Module::new(type_def_id); let path = Path { segments: import.path.segments[i + 1..].iter().cloned().collect(), kind: PathKind::Crate, @@ -359,7 +355,7 @@ where "resolved import {:?} ({:?}) cross-source root to {:?}", last_segment.name, import, - def_id.map(|did| did.loc(self.db)) + def_id, ); return true; } else { @@ -372,7 +368,7 @@ where log::debug!( "path segment {:?} resolved to non-module {:?}, but is not last", segment.name, - type_def_id.loc(self.db) + type_def_id, ); return true; // this resolved to a non-module, so the path won't ever resolve } @@ -382,7 +378,7 @@ where "resolved import {:?} ({:?}) within source root to {:?}", segment.name, import, - def_id.map(|did| did.loc(self.db)) + def_id, ); self.update(module_id, |items| { let res = Resolution { diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 4eea6ff1d..6f003bd66 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs @@ -4,14 +4,13 @@ use ra_syntax::{ SyntaxKind, AstNode, SourceFile, TreeArc, AstPtr, ast::{self, ModuleItemOwner, NameOwner}, }; -use ra_db::SourceRootId; use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; use rustc_hash::FxHashMap; use crate::{ SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, - HirFileId, MacroCallLoc, AsName, PerNs, DefId, DefKind, DefLoc, - module_tree::ModuleId + HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, + ModuleDef, Module, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -32,7 +31,7 @@ pub(super) struct ImportData { /// can avoid redoing name resolution. #[derive(Debug, Default, PartialEq, Eq)] pub struct LoweredModule { - pub(crate) declarations: FxHashMap>, + pub(crate) declarations: FxHashMap>, pub(super) imports: Arena, } @@ -59,37 +58,31 @@ impl ImportSourceMap { impl LoweredModule { pub(crate) fn lower_module_module_query( db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, ) -> Arc { - db.lower_module(source_root_id, module_id).0 + db.lower_module(module).0 } pub(crate) fn lower_module_source_map_query( db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, ) -> Arc { - db.lower_module(source_root_id, module_id).1 + db.lower_module(module).1 } pub(crate) fn lower_module_query( db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, ) -> (Arc, Arc) { - let module_tree = db.module_tree(source_root_id); - let source = module_id.source(&module_tree); - let file_id = source.file_id; - let source = ModuleSource::from_source_item_id(db, source); + let (file_id, source) = module.definition_source(db); + let file_id: HirFileId = file_id.into(); let mut source_map = ImportSourceMap::default(); let mut res = LoweredModule::default(); match source { ModuleSource::SourceFile(it) => res.fill( &mut source_map, db, - source_root_id, - module_id, + module, file_id, &mut it.items_with_macros(), ), @@ -98,8 +91,7 @@ impl LoweredModule { res.fill( &mut source_map, db, - source_root_id, - module_id, + module, file_id, &mut item_list.items_with_macros(), ) @@ -113,8 +105,7 @@ impl LoweredModule { &mut self, source_map: &mut ImportSourceMap, db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, file_id: HirFileId, items: &mut Iterator, ) { @@ -123,21 +114,12 @@ impl LoweredModule { for item in items { match item { ast::ItemOrMacro::Item(it) => { - self.add_def_id( - source_map, - db, - source_root_id, - module_id, - file_id, - &file_items, - it, - ); + self.add_def_id(source_map, db, module, file_id, &file_items, it); } ast::ItemOrMacro::Macro(macro_call) => { let item_id = file_items.id_of_unchecked(macro_call.syntax()); let loc = MacroCallLoc { - source_root_id, - module_id, + module, source_item_id: SourceItemId { file_id, item_id: Some(item_id), @@ -148,15 +130,7 @@ impl LoweredModule { let file_items = db.file_items(file_id); //FIXME: expand recursively for item in db.hir_source_file(file_id).items() { - self.add_def_id( - source_map, - db, - source_root_id, - module_id, - file_id, - &file_items, - item, - ); + self.add_def_id(source_map, db, module, file_id, &file_items, item); } } } @@ -167,8 +141,7 @@ impl LoweredModule { &mut self, source_map: &mut ImportSourceMap, db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, file_id: HirFileId, file_items: &SourceFileItems, item: &ast::ModuleItem, @@ -199,7 +172,7 @@ impl LoweredModule { } }; if let Some(name) = name { - let def_id = assign_def_id(db, source_root_id, module_id, file_id, file_items, item); + let def_id = assign_def_id(db, module, file_id, file_items, item); self.declarations.insert(name.as_name(), def_id); } } @@ -219,12 +192,11 @@ impl LoweredModule { fn assign_def_id( db: &impl HirDatabase, - source_root_id: SourceRootId, - module_id: ModuleId, + module: Module, file_id: HirFileId, file_items: &SourceFileItems, item: &ast::ModuleItem, -) -> PerNs { +) -> PerNs { // depending on the item kind, the location can define something in // the values namespace, the types namespace, or both let kind = DefKind::for_syntax_kind(item.syntax().kind()); @@ -232,14 +204,13 @@ fn assign_def_id( let item_id = file_items.id_of_unchecked(item.syntax()); let def_loc = DefLoc { kind: k, - source_root_id, - module_id, + module, source_item_id: SourceItemId { file_id, item_id: Some(item_id), }, }; - def_loc.id(db) + def_loc.id(db).into() }); def_id } @@ -248,7 +219,6 @@ impl DefKind { fn for_syntax_kind(kind: SyntaxKind) -> PerNs { match kind { SyntaxKind::FN_DEF => PerNs::values(DefKind::Function), - SyntaxKind::MODULE => PerNs::types(DefKind::Module), SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor), SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum), SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait), diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index e92007453..9322bf08c 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use ra_db::{FilesDatabase, CrateGraph, SourceRootId, salsa::Database}; +use ra_db::{CrateGraph, SourceRootId, salsa::Database}; use relative_path::RelativePath; use test_utils::{assert_eq_text, covers}; @@ -13,10 +13,10 @@ use crate::{ fn item_map(fixture: &str) -> (Arc, ModuleId) { let (db, pos) = MockDatabase::with_position(fixture); - let source_root = db.file_source_root(pos.file_id); let module = crate::source_binder::module_from_position(&db, pos).unwrap(); - let module_id = module.def_id.loc(&db).module_id; - (db.item_map(source_root), module_id) + let krate = module.krate(&db).unwrap(); + let module_id = module.module_id; + (db.item_map(krate.crate_id), module_id) } fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { @@ -238,14 +238,13 @@ fn item_map_across_crates() { db.set_crate_graph(crate_graph); - let source_root = db.file_source_root(main_id); let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - let module_id = module.def_id.loc(&db).module_id; - let item_map = db.item_map(source_root); + let krate = module.krate(&db).unwrap(); + let item_map = db.item_map(krate.crate_id); check_module_item_map( &item_map, - module_id, + module.module_id, " Baz: t v test_crate: t @@ -292,12 +291,12 @@ fn import_across_source_roots() { db.set_crate_graph(crate_graph); let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - let module_id = module.def_id.loc(&db).module_id; - let item_map = db.item_map(source_root); + let krate = module.krate(&db).unwrap(); + let item_map = db.item_map(krate.crate_id); check_module_item_map( &item_map, - module_id, + module.module_id, " C: t v test_crate: t @@ -333,14 +332,13 @@ fn reexport_across_crates() { db.set_crate_graph(crate_graph); - let source_root = db.file_source_root(main_id); let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - let module_id = module.def_id.loc(&db).module_id; - let item_map = db.item_map(source_root); + let krate = module.krate(&db).unwrap(); + let item_map = db.item_map(krate.crate_id); check_module_item_map( &item_map, - module_id, + module.module_id, " Baz: t v test_crate: t @@ -350,10 +348,11 @@ fn reexport_across_crates() { fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { let (mut db, pos) = MockDatabase::with_position(initial); - let source_root = db.file_source_root(pos.file_id); + let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); + let krate = module.krate(&db).unwrap(); { let events = db.log_executed(|| { - db.item_map(source_root); + db.item_map(krate.crate_id); }); assert!(format!("{:?}", events).contains("item_map")) } @@ -362,7 +361,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { { let events = db.log_executed(|| { - db.item_map(source_root); + db.item_map(krate.crate_id); }); assert!( !format!("{:?}", events).contains("item_map"), diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 074153862..a8ed887b3 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs @@ -7,11 +7,11 @@ use rustc_hash::FxHashMap; use ra_syntax::{ AstNode, SyntaxNode, TreeArc, }; -use ra_db::SourceRootId; +use ra_db::{CrateId}; use crate::{ SourceFileItems, SourceItemId, DefId, HirFileId, - FnScopes, + FnScopes, Module, db::HirDatabase, nameres::{ItemMap, Resolver}, }; @@ -41,15 +41,23 @@ pub(super) fn file_item( } } -pub(super) fn item_map(db: &impl HirDatabase, source_root: SourceRootId) -> Arc { +pub(super) fn item_map(db: &impl HirDatabase, crate_id: CrateId) -> Arc { let start = Instant::now(); - let module_tree = db.module_tree(source_root); + let module_tree = db.module_tree(crate_id); let input = module_tree .modules() - .map(|id| (id, db.lower_module_module(source_root, id))) + .map(|module_id| { + ( + module_id, + db.lower_module_module(Module { + krate: crate_id, + module_id, + }), + ) + }) .collect::>(); - let resolver = Resolver::new(db, &input, source_root, module_tree); + let resolver = Resolver::new(db, &input, crate_id); let res = resolver.resolve(); let elapsed = start.elapsed(); log::info!("item_map: {:?}", elapsed); diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index bde0be37b..c3bd31d6b 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -13,7 +13,7 @@ use ra_syntax::{ }; use crate::{ - HirDatabase, Function, SourceItemId, + HirDatabase, Function, SourceItemId, ModuleDef, DefKind, DefLoc, AsName, Module, }; @@ -84,9 +84,13 @@ pub fn module_from_child_node( fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Option { let source_root_id = db.file_source_root(source.file_id.as_original_file()); - let module_tree = db.module_tree(source_root_id); - let module_id = module_tree.find_module_by_source(source)?; - Some(Module::from_module_id(db, source_root_id, module_id)) + db.source_root_crates(source_root_id) + .iter() + .find_map(|&krate| { + let module_tree = db.module_tree(krate); + let module_id = module_tree.find_module_by_source(source)?; + Some(Module { krate, module_id }) + }) } pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option { @@ -110,8 +114,8 @@ pub fn function_from_module( module: &Module, fn_def: &ast::FnDef, ) -> Function { - let loc = module.def_id.loc(db); - let file_id = loc.source_item_id.file_id; + let (file_id, _) = module.definition_source(db); + let file_id = file_id.into(); let file_items = db.file_items(file_id); let item_id = file_items.id_of(file_id, fn_def.syntax()); let source_item_id = SourceItemId { @@ -119,9 +123,8 @@ pub fn function_from_module( item_id: Some(item_id), }; let def_loc = DefLoc { + module: module.clone(), kind: DefKind::Function, - source_root_id: loc.source_root_id, - module_id: loc.module_id, source_item_id, }; Function::new(def_loc.id(db)) @@ -141,14 +144,17 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te Some(it) => it, None => return Vec::new(), }; - let loc = module.def_id.loc(db); - let items = db.lower_module_module(loc.source_root_id, loc.module_id); + let items = db.lower_module_module(module); let mut res = Vec::new(); for macro_call_id in items .declarations .iter() - .filter_map(|(_, it)| it.take_types()) + .filter_map(|(_, it)| it.clone().take_types()) + .filter_map(|it| match it { + ModuleDef::Def(it) => Some(it), + _ => None, + }) .filter_map(|it| it.loc(db).source_item_id.file_id.as_macro_call_id()) { if let Some(exp) = db.expand_macro_invocation(macro_call_id) { diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index e690ae158..4c96579ee 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -32,7 +32,7 @@ use rustc_hash::FxHashMap; use crate::{ Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, - FnSignature, FnScopes, + FnSignature, FnScopes, ModuleDef, db::HirDatabase, type_ref::{TypeRef, Mutability}, name::KnownName, @@ -382,8 +382,8 @@ impl Ty { // Resolve in module (in type namespace) let resolved = match module.resolve_path(db, path).take_types() { - Some(r) => r, - None => return Ty::Unknown, + Some(ModuleDef::Def(r)) => r, + None | Some(ModuleDef::Module(_)) => return Ty::Unknown, }; let ty = db.type_for_def(resolved); let substs = Ty::substs_from_path(db, module, impl_block, generics, path, resolved); @@ -663,10 +663,6 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty { let def = def_id.resolve(db); match def { - Def::Module(..) => { - log::debug!("trying to get type for module {:?}", def_id); - Ty::Unknown - } Def::Function(f) => type_for_fn(db, f), Def::Struct(s) => type_for_struct(db, s), Def::Enum(e) => type_for_enum(db, e), @@ -1063,7 +1059,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }; // resolve in module - let resolved = self.module.resolve_path(self.db, &path).take_values()?; + let resolved = match self.module.resolve_path(self.db, &path).take_values()? { + ModuleDef::Def(it) => it, + ModuleDef::Module(_) => return None, + }; let ty = self.db.type_for_def(resolved); let ty = self.insert_type_vars(ty); Some(ty) @@ -1075,7 +1074,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { None => return (Ty::Unknown, None), }; let def_id = match self.module.resolve_path(self.db, &path).take_types() { - Some(def_id) => def_id, + Some(ModuleDef::Def(def_id)) => def_id, _ => return (Ty::Unknown, None), }; // TODO remove the duplication between here and `Ty::from_path`? @@ -1216,6 +1215,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .module .resolve_path(self.db, &path) .take_values() + .and_then(|module_def| match module_def { + ModuleDef::Def(it) => Some(it), + ModuleDef::Module(_) => None, + }) .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), Pat::Bind { mode, diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 9f65c5fe1..a5567a78f 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -6,8 +6,6 @@ use std::sync::Arc; use rustc_hash::FxHashMap; -use ra_db::SourceRootId; - use crate::{ HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}, @@ -37,7 +35,7 @@ impl TyFingerprint { #[derive(Debug, PartialEq, Eq)] pub struct CrateImplBlocks { /// To make sense of the ModuleIds, we need the source root. - source_root_id: SourceRootId, + krate: Crate, impls: FxHashMap>, } @@ -53,14 +51,17 @@ impl CrateImplBlocks { .into_iter() .flat_map(|i| i.iter()) .map(move |(module_id, impl_id)| { - let module_impl_blocks = db.impls_in_module(self.source_root_id, *module_id); + let module = Module { + krate: self.krate.crate_id, + module_id: *module_id, + }; + let module_impl_blocks = db.impls_in_module(module); ImplBlock::from_id(module_impl_blocks, *impl_id) }) } - fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) { - let module_id = module.def_id.loc(db).module_id; - let module_impl_blocks = db.impls_in_module(self.source_root_id, module_id); + fn collect_recursive(&mut self, db: &impl HirDatabase, module: &Module) { + let module_impl_blocks = db.impls_in_module(module.clone()); for (impl_id, impl_data) in module_impl_blocks.impls.iter() { let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id); @@ -81,13 +82,13 @@ impl CrateImplBlocks { self.impls .entry(target_ty_fp) .or_insert_with(Vec::new) - .push((module_id, impl_id)); + .push((module.module_id, impl_id)); } } } for child in module.children(db) { - self.collect_recursive(db, child); + self.collect_recursive(db, &child); } } @@ -95,15 +96,12 @@ impl CrateImplBlocks { db: &impl HirDatabase, krate: Crate, ) -> Arc { - let crate_graph = db.crate_graph(); - let file_id = crate_graph.crate_root(krate.crate_id); - let source_root_id = db.file_source_root(file_id); let mut crate_impl_blocks = CrateImplBlocks { - source_root_id, + krate: krate.clone(), impls: FxHashMap::default(), }; if let Some(module) = krate.root_module(db) { - crate_impl_blocks.collect_recursive(db, module); + crate_impl_blocks.collect_recursive(db, &module); } Arc::new(crate_impl_blocks) } diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index e44b76c4a..0d7942496 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -13,8 +13,8 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { Some(it) => it, None => return, }; - match def_id.resolve(ctx.db) { - hir::Def::Module(module) => { + match def_id { + hir::ModuleDef::Module(module) => { let module_scope = module.scope(ctx.db); for (name, res) in module_scope.entries() { CompletionItem::new( @@ -26,21 +26,24 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { .add_to(acc); } } - hir::Def::Enum(e) => { - e.variants(ctx.db) - .into_iter() - .for_each(|(variant_name, variant)| { - CompletionItem::new( - CompletionKind::Reference, - ctx.source_range(), - variant_name.to_string(), - ) - .kind(CompletionItemKind::EnumVariant) - .set_documentation(variant.docs(ctx.db)) - .add_to(acc) - }); - } - _ => return, + + hir::ModuleDef::Def(def_id) => match def_id.resolve(ctx.db) { + hir::Def::Enum(e) => { + e.variants(ctx.db) + .into_iter() + .for_each(|(variant_name, variant)| { + CompletionItem::new( + CompletionKind::Reference, + ctx.source_range(), + variant_name.to_string(), + ) + .kind(CompletionItemKind::EnumVariant) + .set_documentation(variant.docs(ctx.db)) + .add_to(acc) + }); + } + _ => return, + }, }; } diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 18c151932..5d6718a8d 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -1,6 +1,4 @@ -use hir::{Docs, Documentation, PerNs}; - -use crate::completion::completion_context::CompletionContext; +use hir::{Docs, Documentation}; use ra_syntax::{ ast::{self, AstNode}, TextRange, @@ -8,6 +6,8 @@ use ra_syntax::{ use ra_text_edit::TextEdit; use test_utils::tested_by; +use crate::completion::completion_context::CompletionContext; + /// `CompletionItem` describes a single completion variant in the editor pop-up. /// It is basically a POD with various properties. To construct a /// `CompletionItem`, use `new` method and the `Builder` struct. @@ -209,41 +209,26 @@ impl Builder { ctx: &CompletionContext, resolution: &hir::Resolution, ) -> Builder { - let resolved = resolution.def_id.map(|d| d.resolve(ctx.db)); - let (kind, docs) = match resolved { - PerNs { - types: Some(hir::Def::Module(..)), - .. - } => (CompletionItemKind::Module, None), - PerNs { - types: Some(hir::Def::Struct(s)), - .. - } => (CompletionItemKind::Struct, s.docs(ctx.db)), - PerNs { - types: Some(hir::Def::Enum(e)), - .. - } => (CompletionItemKind::Enum, e.docs(ctx.db)), - PerNs { - types: Some(hir::Def::Trait(t)), - .. - } => (CompletionItemKind::Trait, t.docs(ctx.db)), - PerNs { - types: Some(hir::Def::Type(t)), - .. - } => (CompletionItemKind::TypeAlias, t.docs(ctx.db)), - PerNs { - values: Some(hir::Def::Const(c)), - .. - } => (CompletionItemKind::Const, c.docs(ctx.db)), - PerNs { - values: Some(hir::Def::Static(s)), - .. - } => (CompletionItemKind::Static, s.docs(ctx.db)), - PerNs { - values: Some(hir::Def::Function(function)), - .. - } => return self.from_function(ctx, function), - _ => return self, + let def = resolution + .def_id + .take_types() + .or(resolution.def_id.take_values()); + let def = match def { + None => return self, + Some(it) => it, + }; + let (kind, docs) = match def { + hir::ModuleDef::Module(_) => (CompletionItemKind::Module, None), + hir::ModuleDef::Def(def_id) => match def_id.resolve(ctx.db) { + hir::Def::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), + hir::Def::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), + hir::Def::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), + hir::Def::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), + hir::Def::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), + hir::Def::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), + hir::Def::Function(function) => return self.from_function(ctx, function), + _ => return self, + }, }; self.kind = Some(kind); self.documentation = docs; diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs index ba0eb1cb8..bff6b7237 100644 --- a/crates/ra_ide_api/src/db.rs +++ b/crates/ra_ide_api/src/db.rs @@ -72,6 +72,7 @@ salsa::database_storage! { fn file_relative_path() for ra_db::FileRelativePathQuery; fn file_source_root() for ra_db::FileSourceRootQuery; fn source_root() for ra_db::SourceRootQuery; + fn source_root_crates() for ra_db::SourceRootCratesQuery; fn local_roots() for ra_db::LocalRootsQuery; fn library_roots() for ra_db::LibraryRootsQuery; fn crate_graph() for ra_db::CrateGraphQuery; diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index b1becca03..323bb1cc1 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -67,7 +67,7 @@ pub(crate) fn reference_definition( .node_expr(expr) .and_then(|it| infer_result.method_resolution(it)) { - if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) { + if let Some(target) = NavigationTarget::from_def(db, hir::ModuleDef::Def(def_id)) { return Exact(target); } }; @@ -84,7 +84,7 @@ pub(crate) fn reference_definition( { let resolved = module.resolve_path(db, &path); if let Some(def_id) = resolved.take_types().or(resolved.take_values()) { - if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) { + if let Some(target) = NavigationTarget::from_def(db, def_id) { return Exact(target); } } diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 21c15c0c0..1eb177665 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -97,7 +97,17 @@ impl NavigationTarget { } // TODO once Def::Item is gone, this should be able to always return a NavigationTarget - pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Option { + pub(crate) fn from_def( + db: &RootDatabase, + module_def: hir::ModuleDef, + ) -> Option { + let def = match module_def { + hir::ModuleDef::Def(def_id) => def_id.resolve(db), + hir::ModuleDef::Module(module) => { + return Some(NavigationTarget::from_module(db, module)); + } + }; + let res = match def { Def::Struct(s) => { let (file_id, node) = s.source(db); @@ -131,7 +141,6 @@ impl NavigationTarget { let (file_id, node) = f.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) } - Def::Module(m) => NavigationTarget::from_module(db, m), Def::Item => return None, }; Some(res) diff --git a/crates/ra_ide_api/src/rename.rs b/crates/ra_ide_api/src/rename.rs index 53dc273c6..5b767addd 100644 --- a/crates/ra_ide_api/src/rename.rs +++ b/crates/ra_ide_api/src/rename.rs @@ -57,7 +57,6 @@ fn rename_mod( ) -> Option { let mut source_file_edits = Vec::new(); let mut file_system_edits = Vec::new(); - if let Some(module) = module_from_declaration(db, position.file_id, &ast_module) { let (file_id, module_source) = module.definition_source(db); match module_source { @@ -223,11 +222,15 @@ mod tests { fn test_rename_mod() { let (analysis, position) = analysis_and_position( " - //- /bar.rs - mod fo<|>o; - //- /bar/foo.rs - // emtpy - ", + //- /lib.rs + mod bar; + + //- /bar.rs + mod foo<|>; + + //- /bar/foo.rs + // emtpy + ", ); let new_name = "foo2"; let source_change = analysis.rename(position, new_name).unwrap(); @@ -238,11 +241,11 @@ mod tests { fn test_rename_mod_in_dir() { let (analysis, position) = analysis_and_position( " - //- /lib.rs - mod fo<|>o; - //- /foo/mod.rs - // emtpy - ", + //- /lib.rs + mod fo<|>o; + //- /foo/mod.rs + // emtpy + ", ); let new_name = "foo2"; let source_change = analysis.rename(position, new_name).unwrap(); diff --git a/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap b/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap index 3267d1ac5..890426db7 100644 --- a/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap +++ b/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap @@ -1,8 +1,8 @@ --- -created: "2019-01-22T14:45:00.975229300+00:00" -creator: insta@0.4.0 +created: "2019-01-24T08:39:53.759318522+00:00" +creator: insta@0.5.2 expression: "&source_change" -source: "crates\\ra_ide_api\\src\\rename.rs" +source: crates/ra_ide_api/src/rename.rs --- Some( SourceChange { @@ -10,7 +10,7 @@ Some( source_file_edits: [ SourceFileEdit { file_id: FileId( - 1 + 2 ), edit: TextEdit { atoms: [ @@ -25,7 +25,7 @@ Some( file_system_edits: [ MoveFile { src: FileId( - 2 + 3 ), dst_source_root: SourceRootId( 0 -- cgit v1.2.3