From a6590ce2318676210b6b5a197b76b5861a3407c9 Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Tue, 8 Jan 2019 00:30:49 +0100
Subject: Use name resolution for goto definition

---
 crates/ra_hir/src/code_model_api.rs           | 49 ++++++++++++++++++++++++---
 crates/ra_hir/src/code_model_impl/function.rs | 23 +++++++++----
 crates/ra_hir/src/expr.rs                     |  2 +-
 crates/ra_hir/src/ids.rs                      |  8 ++++-
 4 files changed, 70 insertions(+), 12 deletions(-)

(limited to 'crates/ra_hir/src')

diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 725bc7d80..e69f546ff 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -2,10 +2,10 @@ use std::sync::Arc;
 
 use relative_path::RelativePathBuf;
 use ra_db::{CrateId, Cancelable, FileId};
-use ra_syntax::{ast, TreePtr, SyntaxNode};
+use ra_syntax::{ast, TreePtr, SyntaxNode, AstNode};
 
 use crate::{
-    Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty,
+    Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId,
     type_ref::TypeRef,
     nameres::ModuleScope,
     db::HirDatabase,
@@ -181,6 +181,19 @@ impl Struct {
             .collect();
         Ok(res)
     }
+
+    pub fn source(
+        &self,
+        db: &impl HirDatabase,
+    ) -> Cancelable<(HirFileId, TreePtr<ast::StructDef>)> {
+        let (file_id, syntax) = self.def_id.source(db);
+        Ok((
+            file_id,
+            ast::StructDef::cast(&syntax)
+                .expect("struct def should point to StructDef node")
+                .to_owned(),
+        ))
+    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -204,6 +217,16 @@ impl Enum {
     pub fn variants(&self, db: &impl HirDatabase) -> Cancelable<Vec<(Name, EnumVariant)>> {
         Ok(db.enum_data(self.def_id)?.variants.clone())
     }
+
+    pub fn source(&self, db: &impl HirDatabase) -> Cancelable<(HirFileId, TreePtr<ast::EnumDef>)> {
+        let (file_id, syntax) = self.def_id.source(db);
+        Ok((
+            file_id,
+            ast::EnumDef::cast(&syntax)
+                .expect("enum def should point to EnumDef node")
+                .to_owned(),
+        ))
+    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -231,6 +254,19 @@ impl EnumVariant {
     pub fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> {
         Ok(db.enum_variant_data(self.def_id)?.variant_data.clone())
     }
+
+    pub fn source(
+        &self,
+        db: &impl HirDatabase,
+    ) -> Cancelable<(HirFileId, TreePtr<ast::EnumVariant>)> {
+        let (file_id, syntax) = self.def_id.source(db);
+        Ok((
+            file_id,
+            ast::EnumVariant::cast(&syntax)
+                .expect("variant def should point to EnumVariant node")
+                .to_owned(),
+        ))
+    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -241,11 +277,16 @@ pub struct Function {
 /// The declared signature of a function.
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct FnSignature {
+    pub(crate) name: Name,
     pub(crate) args: Vec<TypeRef>,
     pub(crate) ret_type: TypeRef,
 }
 
 impl FnSignature {
+    pub fn name(&self) -> &Name {
+        &self.name
+    }
+
     pub fn args(&self) -> &[TypeRef] {
         &self.args
     }
@@ -260,8 +301,8 @@ impl Function {
         self.def_id
     }
 
-    pub fn source(&self, db: &impl HirDatabase) -> TreePtr<ast::FnDef> {
-        self.source_impl(db)
+    pub fn source(&self, db: &impl HirDatabase) -> Cancelable<(HirFileId, TreePtr<ast::FnDef>)> {
+        Ok(self.source_impl(db))
     }
 
     pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Cancelable<Arc<BodySyntaxMapping>> {
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs
index 13c57ed21..1bd4cc802 100644
--- a/crates/ra_hir/src/code_model_impl/function.rs
+++ b/crates/ra_hir/src/code_model_impl/function.rs
@@ -5,11 +5,11 @@ use std::sync::Arc;
 use ra_db::Cancelable;
 use ra_syntax::{
     TreePtr,
-    ast::{self, AstNode},
+    ast::{self, AstNode, NameOwner},
 };
 
 use crate::{
-    DefId, DefKind, HirDatabase, Name, Function, FnSignature, Module,
+    DefId, DefKind, HirDatabase, Name, AsName, Function, FnSignature, Module, HirFileId,
     type_ref::{TypeRef, Mutability},
     expr::Body,
     impl_block::ImplBlock,
@@ -22,11 +22,14 @@ impl Function {
         Function { def_id }
     }
 
-    pub(crate) fn source_impl(&self, db: &impl HirDatabase) -> TreePtr<ast::FnDef> {
+    pub(crate) fn source_impl(&self, db: &impl HirDatabase) -> (HirFileId, TreePtr<ast::FnDef>) {
         let def_loc = self.def_id.loc(db);
         assert!(def_loc.kind == DefKind::Function);
         let syntax = db.file_item(def_loc.source_item_id);
-        ast::FnDef::cast(&syntax).unwrap().to_owned()
+        (
+            def_loc.source_item_id.file_id,
+            ast::FnDef::cast(&syntax).unwrap().to_owned(),
+        )
     }
 
     pub(crate) fn body(&self, db: &impl HirDatabase) -> Cancelable<Arc<Body>> {
@@ -46,7 +49,11 @@ impl Function {
 impl FnSignature {
     pub(crate) fn fn_signature_query(db: &impl HirDatabase, def_id: DefId) -> Arc<FnSignature> {
         let func = Function::new(def_id);
-        let node = func.source(db);
+        let node = func.source_impl(db).1; // TODO we're using source_impl here to avoid returning Cancelable... this is a bit hacky
+        let name = node
+            .name()
+            .map(|n| n.as_name())
+            .unwrap_or_else(Name::missing);
         let mut args = Vec::new();
         if let Some(param_list) = node.param_list() {
             if let Some(self_param) = param_list.self_param() {
@@ -76,7 +83,11 @@ impl FnSignature {
         } else {
             TypeRef::unit()
         };
-        let sig = FnSignature { args, ret_type };
+        let sig = FnSignature {
+            name,
+            args,
+            ret_type,
+        };
         Arc::new(sig)
     }
 }
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index ebb83d084..e5596cbaa 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -762,7 +762,7 @@ pub(crate) fn body_syntax_mapping(
     let def = def_id.resolve(db)?;
 
     let body_syntax_mapping = match def {
-        Def::Function(f) => collect_fn_body_syntax(&f.source(db)),
+        Def::Function(f) => collect_fn_body_syntax(&f.source(db)?.1),
         // TODO: consts, etc.
         _ => panic!("Trying to get body for item type without body"),
     };
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index db0107e53..c75ef4ae7 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -34,7 +34,7 @@ pub struct HirFileId(HirFileIdRepr);
 impl HirFileId {
     /// For macro-expansion files, returns the file original source file the
     /// expansionoriginated from.
-    pub(crate) fn original_file(self, db: &impl HirDatabase) -> FileId {
+    pub fn original_file(self, db: &impl HirDatabase) -> FileId {
         match self.0 {
             HirFileIdRepr::File(file_id) => file_id,
             HirFileIdRepr::Macro(macro_call_id) => {
@@ -179,6 +179,12 @@ impl DefId {
         Ok(res)
     }
 
+    pub(crate) fn source(self, db: &impl HirDatabase) -> (HirFileId, TreePtr<SyntaxNode>) {
+        let loc = self.loc(db);
+        let syntax = db.file_item(loc.source_item_id);
+        (loc.source_item_id.file_id, syntax)
+    }
+
     /// For a module, returns that module; for any other def, returns the containing module.
     pub fn module(self, db: &impl HirDatabase) -> Cancelable<Module> {
         let loc = self.loc(db);
-- 
cgit v1.2.3