From d8b0379e1063941331253905795699a918233ef9 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Tue, 4 Dec 2018 23:44:00 +0300
Subject: Add functions to DefId

---
 .../src/completion/reference_completion.rs         |  2 +-
 crates/ra_analysis/src/db.rs                       |  9 +----
 crates/ra_analysis/src/imp.rs                      | 41 ++++++++++++++--------
 crates/ra_analysis/src/lib.rs                      |  2 +-
 crates/ra_hir/src/db.rs                            |  4 +--
 crates/ra_hir/src/function/mod.rs                  | 41 ++++++++++++----------
 crates/ra_hir/src/lib.rs                           | 20 ++---------
 crates/ra_hir/src/mock.rs                          |  9 +----
 crates/ra_hir/src/module/mod.rs                    | 23 ++++++++++--
 crates/ra_hir/src/query_definitions.rs             | 22 ++++++------
 10 files changed, 90 insertions(+), 83 deletions(-)

diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs
index 8ea7478a8..f483ed045 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 df2ef293d..b8d774eb5 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<SourceItemId, FnId>,
     defs: LocationIntener<DefLoc, DefId>,
 }
 
@@ -58,12 +57,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
     }
 }
 
-impl AsRef<LocationIntener<hir::SourceItemId, FnId>> for RootDatabase {
-    fn as_ref(&self) -> &LocationIntener<hir::SourceItemId, FnId> {
-        &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 942b5b945..fe1dfefea 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::<ast::NameRef>(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<Vec<(FileId, TextRange)>> {
         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<Option<(ast::BindPat<'a>, hir::Function)>> {
             let syntax = source_file.syntax();
             if let Some(binding) = find_node_at_offset::<ast::BindPat>(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::<ast::NameRef>(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::<ast::NameRef>(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::<ast::BindPat>(syntax, resolved.range().end())?;
-            Some((binding, descr))
+            let binding = ctry!(find_node_at_offset::<ast::BindPat>(
+                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 12df580ba..90528edfd 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<Vec<(FileId, TextRange)>> {
-        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 2f01bae6d..ff41fd326 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<LocationIntener<DefLoc, DefId>>
-    + AsRef<LocationIntener<SourceItemId, FnId>>
 {
     fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> {
         type FnScopesQuery;
diff --git a/crates/ra_hir/src/function/mod.rs b/crates/ra_hir/src/function/mod.rs
index c8af2e54f..a6757601e 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<Option<Function>> {
+        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<Function> {
+    ) -> Cancelable<Option<Function>> {
         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<Function> {
+    ) -> Cancelable<Option<Function>> {
         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<Function> {
-        let fn_def = node.ancestors().find_map(ast::FnDef::cast)?;
-        let res = Function::guess_from_source(db, file_id, fn_def);
-        Some(res)
+    ) -> Cancelable<Option<Function>> {
+        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<FnScopes> {
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index ffc99fd5f..dbcc5e46d 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<LocationIntener<SourceItemId, FnId>>,
-        loc: &SourceItemId,
-    ) -> FnId {
-        db.as_ref().loc2id(loc)
-    }
-    pub fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> 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 8e256b89f..e855df11d 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<SourceItemId, FnId>,
     defs: LocationIntener<DefLoc, DefId>,
 }
 
@@ -117,12 +116,6 @@ impl AsRef<LocationIntener<DefLoc, DefId>> for MockDatabase {
     }
 }
 
-impl AsRef<LocationIntener<SourceItemId, FnId>> for MockDatabase {
-    fn as_ref(&self) -> &LocationIntener<SourceItemId, FnId> {
-        &self.id_maps.fns
-    }
-}
-
 impl MockDatabase {
     pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> {
         *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 08ce7c8d1..11e6e8e75 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<ModuleTree>,
-    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<Option<Module>> {
+        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 59318f307..e4d721601 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()
 }
 
-- 
cgit v1.2.3