aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs29
-rw-r--r--crates/ra_ide_api/src/hover.rs22
-rw-r--r--crates/ra_ide_api/src/navigation_target.rs16
3 files changed, 62 insertions, 5 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 9ec179593..364263d9b 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -47,9 +47,10 @@ pub(crate) fn reference_definition(
47 name_ref: &ast::NameRef, 47 name_ref: &ast::NameRef,
48) -> ReferenceResult { 48) -> ReferenceResult {
49 use self::ReferenceResult::*; 49 use self::ReferenceResult::*;
50 if let Some(function) = 50
51 hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()) 51 let function = hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax());
52 { 52
53 if let Some(function) = function {
53 // Check if it is a method 54 // Check if it is a method
54 if let Some(method_call) = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast) { 55 if let Some(method_call) = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast) {
55 tested_by!(goto_definition_works_for_methods); 56 tested_by!(goto_definition_works_for_methods);
@@ -122,9 +123,29 @@ pub(crate) fn reference_definition(
122 Some(Resolution::SelfType(_impl_block)) => { 123 Some(Resolution::SelfType(_impl_block)) => {
123 // TODO: go to the implemented type 124 // TODO: go to the implemented type
124 } 125 }
125 None => {} 126 None => {
127 // If we failed to resolve then check associated items
128 if let Some(function) = function {
129 // Should we do this above and then grab path from the PathExpr?
130 if let Some(path_expr) =
131 name_ref.syntax().ancestors().find_map(ast::PathExpr::cast)
132 {
133 let infer_result = function.infer(db);
134 let source_map = function.body_source_map(db);
135 let expr = ast::Expr::cast(path_expr.syntax()).unwrap();
136
137 if let Some(res) = source_map
138 .node_expr(expr)
139 .and_then(|it| infer_result.assoc_resolutions_for_expr(it.into()))
140 {
141 return Exact(NavigationTarget::from_impl_item(db, res));
142 }
143 }
144 }
145 }
126 } 146 }
127 } 147 }
148
128 // If that fails try the index based approach. 149 // If that fails try the index based approach.
129 let navs = crate::symbol_index::index_resolve(db, name_ref) 150 let navs = crate::symbol_index::index_resolve(db, name_ref)
130 .into_iter() 151 .into_iter()
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index 8ec60090d..bcd052c8b 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -512,4 +512,26 @@ mod tests {
512 let hover = analysis.hover(position).unwrap().unwrap(); 512 let hover = analysis.hover(position).unwrap().unwrap();
513 assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); 513 assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing"));
514 } 514 }
515
516 #[test]
517 fn test_hover_infer_associated_method_exact() {
518 let (analysis, position) = single_file_with_position(
519 "
520 struct Thing { x: u32 }
521
522 impl Thing {
523 fn new() -> Thing {
524 Thing { x: 0 }
525 }
526 }
527
528 fn main() {
529 let foo_test = Thing::new<|>();
530 }
531 ",
532 );
533 let hover = analysis.hover(position).unwrap().unwrap();
534 assert_eq!(trim_markup_opt(hover.info.first()), Some("fn new() -> Thing"));
535 assert_eq!(hover.info.is_exact(), true);
536 }
515} 537}
diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs
index 6538081ac..d806cb368 100644
--- a/crates/ra_ide_api/src/navigation_target.rs
+++ b/crates/ra_ide_api/src/navigation_target.rs
@@ -3,7 +3,7 @@ use ra_syntax::{
3 SyntaxNode, SyntaxNodePtr, AstNode, SmolStr, TextRange, ast, 3 SyntaxNode, SyntaxNodePtr, AstNode, SmolStr, TextRange, ast,
4 SyntaxKind::{self, NAME}, 4 SyntaxKind::{self, NAME},
5}; 5};
6use hir::{ModuleSource, FieldSource, Name}; 6use hir::{ModuleSource, FieldSource, Name, ImplItem};
7 7
8use crate::{FileSymbol, db::RootDatabase}; 8use crate::{FileSymbol, db::RootDatabase};
9 9
@@ -174,6 +174,20 @@ impl NavigationTarget {
174 ) 174 )
175 } 175 }
176 176
177 pub(crate) fn from_impl_item(db: &RootDatabase, impl_item: hir::ImplItem) -> NavigationTarget {
178 match impl_item {
179 ImplItem::Method(f) => NavigationTarget::from_function(db, f),
180 ImplItem::Const(c) => {
181 let (file_id, node) = c.source(db);
182 NavigationTarget::from_named(file_id.original_file(db), &*node)
183 }
184 ImplItem::TypeAlias(a) => {
185 let (file_id, node) = a.source(db);
186 NavigationTarget::from_named(file_id.original_file(db), &*node)
187 }
188 }
189 }
190
177 #[cfg(test)] 191 #[cfg(test)]
178 pub(crate) fn assert_match(&self, expected: &str) { 192 pub(crate) fn assert_match(&self, expected: &str) {
179 let actual = self.debug_render(); 193 let actual = self.debug_render();