diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs index 8ea7478a8d..f483ed0455 100644 --- a/crates/ra_analysis/src/completion/reference_completion.rs +++ b/crates/ra_analysis/src/completion/reference_completion.rs @@ -163,7 +163,7 @@ fn complete_path( }; let target_module = match def_id.resolve(db)? { Def::Module(it) => it, - Def::Item => return Ok(()), + _ => return Ok(()), }; let module_scope = target_module.scope(db)?; let completions = module_scope.entries().map(|(name, _res)| CompletionItem { diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index df2ef293d1..b8d774eb58 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use salsa::{self, Database}; use ra_db::{LocationIntener, BaseDatabase}; -use hir::{self, DefId, DefLoc, FnId, SourceItemId}; +use hir::{self, DefId, DefLoc}; use crate::{ symbol_index, @@ -15,7 +15,6 @@ pub(crate) struct RootDatabase { #[derive(Debug, Default)] struct IdMaps { - fns: LocationIntener, defs: LocationIntener, } @@ -58,12 +57,6 @@ impl AsRef> for RootDatabase { } } -impl AsRef> for RootDatabase { - fn as_ref(&self) -> &LocationIntener { - &self.id_maps.fns - } -} - salsa::database_storage! { pub(crate) struct RootDatabaseStorage for RootDatabase { impl ra_db::FilesDatabase { diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 942b5b9459..fe1dfefea1 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -210,7 +210,7 @@ impl AnalysisImpl { let syntax = file.syntax(); if let Some(name_ref) = find_node_at_offset::(syntax, position.offset) { if let Some(fn_descr) = - hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref) + hir::Function::guess_for_name_ref(&*self.db, position.file_id, name_ref)? { let scope = fn_descr.scope(&*self.db); // First try to resolve the symbol locally @@ -257,11 +257,11 @@ impl AnalysisImpl { Ok(vec![]) } - pub fn find_all_refs(&self, position: FilePosition) -> Vec<(FileId, TextRange)> { + pub fn find_all_refs(&self, position: FilePosition) -> Cancelable> { let file = self.db.source_file(position.file_id); // Find the binding associated with the offset - let (binding, descr) = match find_binding(&self.db, &file, position) { - None => return Vec::new(), + let (binding, descr) = match find_binding(&self.db, &file, position)? { + None => return Ok(Vec::new()), Some(it) => it, }; @@ -274,25 +274,36 @@ impl AnalysisImpl { .map(|ref_desc| (position.file_id, ref_desc.range)), ); - return ret; + return Ok(ret); fn find_binding<'a>( db: &db::RootDatabase, source_file: &'a SourceFileNode, position: FilePosition, - ) -> Option<(ast::BindPat<'a>, hir::Function)> { + ) -> Cancelable, hir::Function)>> { let syntax = source_file.syntax(); if let Some(binding) = find_node_at_offset::(syntax, position.offset) { - let descr = hir::Function::guess_for_bind_pat(db, position.file_id, binding)?; - return Some((binding, descr)); + let descr = ctry!(hir::Function::guess_for_bind_pat( + db, + position.file_id, + binding + )?); + return Ok(Some((binding, descr))); }; - let name_ref = find_node_at_offset::(syntax, position.offset)?; - let descr = hir::Function::guess_for_name_ref(db, position.file_id, name_ref)?; + let name_ref = ctry!(find_node_at_offset::(syntax, position.offset)); + let descr = ctry!(hir::Function::guess_for_name_ref( + db, + position.file_id, + name_ref + )?); let scope = descr.scope(db); - let resolved = scope.resolve_local_name(name_ref)?; + let resolved = ctry!(scope.resolve_local_name(name_ref)); let resolved = resolved.ptr().resolve(source_file); - let binding = find_node_at_offset::(syntax, resolved.range().end())?; - Some((binding, descr)) + let binding = ctry!(find_node_at_offset::( + syntax, + resolved.range().end() + )); + Ok(Some((binding, descr))) } } @@ -408,7 +419,9 @@ impl AnalysisImpl { if fs.kind == FN_DEF { let fn_file = self.db.source_file(fn_file_id); if let Some(fn_def) = find_node_at_offset(fn_file.syntax(), fs.node_range.start()) { - let descr = hir::Function::guess_from_source(&*self.db, fn_file_id, fn_def); + let descr = ctry!(hir::Function::guess_from_source( + &*self.db, fn_file_id, fn_def + )?); if let Some(descriptor) = descr.signature_info(&*self.db) { // If we have a calling expression let's find which argument we are on let mut current_parameter = None; diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 12df580ba8..90528edfde 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -248,7 +248,7 @@ impl Analysis { self.imp.approximately_resolve_symbol(position) } pub fn find_all_refs(&self, position: FilePosition) -> Cancelable> { - Ok(self.imp.find_all_refs(position)) + self.imp.find_all_refs(position) } pub fn doc_comment_for( &self, diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 2f01bae6d1..ff41fd326a 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -7,10 +7,11 @@ use ra_syntax::{ use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable}; use crate::{ - DefLoc, DefId, FnId, + DefLoc, DefId, SourceFileItems, SourceItemId, query_definitions, FnScopes, + function::FnId, module::{ModuleId, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems}}, }; @@ -19,7 +20,6 @@ salsa::query_group! { pub trait HirDatabase: SyntaxDatabase + AsRef> - + AsRef> { fn fn_scopes(fn_id: FnId) -> Arc { type FnScopesQuery; diff --git a/crates/ra_hir/src/function/mod.rs b/crates/ra_hir/src/function/mod.rs index c8af2e54f9..a6757601e1 100644 --- a/crates/ra_hir/src/function/mod.rs +++ b/crates/ra_hir/src/function/mod.rs @@ -12,19 +12,15 @@ use ra_syntax::{ use ra_db::FileId; use crate::{ - FnId, HirDatabase, SourceItemId, + Cancelable, + DefLoc, DefKind, DefId, HirDatabase, SourceItemId, + Module, }; pub use self::scope::FnScopes; -impl FnId { - pub fn get(db: &impl HirDatabase, file_id: FileId, fn_def: ast::FnDef) -> FnId { - let file_items = db.file_items(file_id); - let item_id = file_items.id_of(fn_def.syntax()); - let item_id = SourceItemId { file_id, item_id }; - FnId::from_loc(db, &item_id) - } -} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct FnId(pub(crate) DefId); pub struct Function { fn_id: FnId, @@ -35,16 +31,26 @@ impl Function { db: &impl HirDatabase, file_id: FileId, fn_def: ast::FnDef, - ) -> Function { - let fn_id = FnId::get(db, file_id, fn_def); - Function { fn_id } + ) -> Cancelable> { + let module = ctry!(Module::guess_from_child_node(db, file_id, fn_def.syntax())?); + let file_items = db.file_items(file_id); + let item_id = file_items.id_of(fn_def.syntax()); + let source_item_id = SourceItemId { file_id, item_id }; + let def_loc = DefLoc { + kind: DefKind::Function, + source_root_id: module.source_root_id, + module_id: module.module_id, + source_item_id, + }; + let fn_id = FnId(def_loc.id(db)); + Ok(Some(Function { fn_id })) } pub fn guess_for_name_ref( db: &impl HirDatabase, file_id: FileId, name_ref: ast::NameRef, - ) -> Option { + ) -> Cancelable> { Function::guess_for_node(db, file_id, name_ref.syntax()) } @@ -52,7 +58,7 @@ impl Function { db: &impl HirDatabase, file_id: FileId, bind_pat: ast::BindPat, - ) -> Option { + ) -> Cancelable> { Function::guess_for_node(db, file_id, bind_pat.syntax()) } @@ -60,10 +66,9 @@ impl Function { db: &impl HirDatabase, file_id: FileId, node: SyntaxNodeRef, - ) -> Option { - let fn_def = node.ancestors().find_map(ast::FnDef::cast)?; - let res = Function::guess_from_source(db, file_id, fn_def); - Some(res) + ) -> Cancelable> { + let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast)); + Function::guess_from_source(db, file_id, fn_def) } pub fn scope(&self, db: &impl HirDatabase) -> Arc { diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index ffc99fd5f3..dbcc5e46da 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -41,22 +41,6 @@ pub use self::{ pub use self::function::FnSignatureInfo; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct FnId(u32); -ra_db::impl_numeric_id!(FnId); - -impl FnId { - pub fn from_loc( - db: &impl AsRef>, - loc: &SourceItemId, - ) -> FnId { - db.as_ref().loc2id(loc) - } - pub fn loc(self, db: &impl AsRef>) -> SourceItemId { - db.as_ref().id2loc(self) - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct DefId(u32); ra_db::impl_numeric_id!(DefId); @@ -64,6 +48,7 @@ ra_db::impl_numeric_id!(DefId); #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub(crate) enum DefKind { Module, + Function, Item, } @@ -89,6 +74,7 @@ impl DefLoc { pub enum Def { Module(Module), + Function(Function), Item, } @@ -100,7 +86,7 @@ impl DefId { let descr = Module::new(db, loc.source_root_id, loc.module_id)?; Def::Module(descr) } - DefKind::Item => Def::Item, + DefKind::Item | DefKind::Function => Def::Item, }; Ok(res) } diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 8e256b89fe..e855df11d1 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs @@ -6,7 +6,7 @@ use ra_db::{LocationIntener, BaseDatabase, FilePosition, mock::FileMap, FileId, use relative_path::RelativePathBuf; use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; -use crate::{db, DefId, DefLoc, FnId, SourceItemId}; +use crate::{db, DefId, DefLoc}; #[derive(Debug)] pub(crate) struct MockDatabase { @@ -65,7 +65,6 @@ impl MockDatabase { #[derive(Debug, Default)] struct IdMaps { - fns: LocationIntener, defs: LocationIntener, } @@ -117,12 +116,6 @@ impl AsRef> for MockDatabase { } } -impl AsRef> for MockDatabase { - fn as_ref(&self) -> &LocationIntener { - &self.id_maps.fns - } -} - impl MockDatabase { pub(crate) fn log(&self, f: impl FnOnce()) -> Vec> { *self.events.lock() = Some(Vec::new()); diff --git a/crates/ra_hir/src/module/mod.rs b/crates/ra_hir/src/module/mod.rs index 08ce7c8d1f..11e6e8e75a 100644 --- a/crates/ra_hir/src/module/mod.rs +++ b/crates/ra_hir/src/module/mod.rs @@ -8,7 +8,7 @@ use ra_editor::find_node_at_offset; use ra_syntax::{ algo::generate, ast::{self, AstNode, NameOwner}, - SmolStr, SyntaxNode, + SmolStr, SyntaxNode, SyntaxNodeRef, }; use ra_db::{SourceRootId, FileId, FilePosition, Cancelable}; use relative_path::RelativePathBuf; @@ -25,8 +25,8 @@ pub use self::nameres::ModuleScope; #[derive(Debug, Clone)] pub struct Module { tree: Arc, - source_root_id: SourceRootId, - module_id: ModuleId, + pub(crate) source_root_id: SourceRootId, + pub(crate) module_id: ModuleId, } impl Module { @@ -57,6 +57,23 @@ impl Module { Module::guess_from_source(db, module_source) } + pub fn guess_from_child_node( + db: &impl HirDatabase, + file_id: FileId, + node: SyntaxNodeRef, + ) -> Cancelable> { + let module_source = if let Some(m) = node + .ancestors() + .filter_map(ast::Module::cast) + .find(|it| !it.has_semi()) + { + ModuleSource::new_inline(db, file_id, m) + } else { + ModuleSource::new_file(db, file_id) + }; + Module::guess_from_source(db, module_source) + } + fn guess_from_source( db: &impl HirDatabase, module_source: ModuleSource, diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 59318f307b..e4d721601d 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs @@ -11,21 +11,21 @@ use ra_syntax::{ use ra_db::{SourceRootId, FileId, Cancelable,}; use crate::{ - FnId, - SourceFileItems, SourceItemId, - db::HirDatabase, - function::FnScopes, - module::{ - ModuleSource, ModuleSourceNode, ModuleId, - imp::Submodule, - nameres::{InputModuleItems, ItemMap, Resolver}, - }, + SourceFileItems, SourceItemId, DefKind, + db::HirDatabase, + function::{FnScopes, FnId}, + module::{ + ModuleSource, ModuleSourceNode, ModuleId, + imp::Submodule, + nameres::{InputModuleItems, ItemMap, Resolver}, + }, }; /// Resolve `FnId` to the corresponding `SyntaxNode` pub(super) fn fn_syntax(db: &impl HirDatabase, fn_id: FnId) -> FnDefNode { - let item_id = fn_id.loc(db); - let syntax = db.file_item(item_id); + let def_loc = fn_id.0.loc(db); + assert!(def_loc.kind == DefKind::Function); + let syntax = db.file_item(def_loc.source_item_id); FnDef::cast(syntax.borrowed()).unwrap().owned() }