From 49da9a3e814a42a2f4dea0cd79dbdae86bea5ce4 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 1 Mar 2019 18:26:49 -0500 Subject: Make goto definition/hover resolve constructors --- crates/ra_ide_api/src/goto_definition.rs | 29 +++++++++++++++++++++++++---- crates/ra_ide_api/src/hover.rs | 22 ++++++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 9ec179593..e4febe8cc 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( name_ref: &ast::NameRef, ) -> ReferenceResult { use self::ReferenceResult::*; - if let Some(function) = - hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()) - { + + let function = hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()); + + if let Some(function) = function { // Check if it is a method if let Some(method_call) = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast) { tested_by!(goto_definition_works_for_methods); @@ -122,9 +123,29 @@ pub(crate) fn reference_definition( Some(Resolution::SelfType(_impl_block)) => { // TODO: go to the implemented type } - None => {} + None => { + // If we failed to resolve then check associated items + if let Some(function) = function { + // Should we do this above and then grab path from the PathExpr? + if let Some(path_expr) = + name_ref.syntax().ancestors().find_map(ast::PathExpr::cast) + { + let infer_result = function.infer(db); + let syntax_mapping = function.body_syntax_mapping(db); + let expr = ast::Expr::cast(path_expr.syntax()).unwrap(); + + if let Some(func) = syntax_mapping + .node_expr(expr) + .and_then(|it| infer_result.assoc_fn_resolutions(it)) + { + return Exact(NavigationTarget::from_function(db, func)); + } + } + } + } } } + // If that fails try the index based approach. let navs = crate::symbol_index::index_resolve(db, name_ref) .into_iter() diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 8ec60090d..0f13777d7 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -512,4 +512,26 @@ mod tests { let hover = analysis.hover(position).unwrap().unwrap(); assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); } + + #[test] + fn test_hover_infer_associated_method_exact() { + let (analysis, position) = single_file_with_position( + " + struct Thing { x: u32 } + + impl Thing { + fn new() -> Thing { + Thing { x: 0 } + } + } + + fn main() { + let foo_test = Thing::new<|>(); + } + ", + ); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(hover.info.first(), Some("```rust\nfn new() -> Thing\n```")); + assert_eq!(hover.info.is_exact(), true); + } } -- cgit v1.2.3 From 3d8d880c59bee2f6aa21800b8b147aff47d6b0b8 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Sat, 2 Mar 2019 14:05:37 -0500 Subject: Use ImplItems instead of just Function --- crates/ra_ide_api/src/goto_definition.rs | 21 ++++++++++++++++----- crates/ra_ide_api/src/hover.rs | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index e4febe8cc..3b66483cb 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -5,7 +5,7 @@ use ra_syntax::{ SyntaxNode, }; use test_utils::tested_by; -use hir::Resolution; +use hir::{ImplItem, Resolution}; use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; @@ -131,14 +131,25 @@ pub(crate) fn reference_definition( name_ref.syntax().ancestors().find_map(ast::PathExpr::cast) { let infer_result = function.infer(db); - let syntax_mapping = function.body_syntax_mapping(db); + let source_map = function.body_source_map(db); let expr = ast::Expr::cast(path_expr.syntax()).unwrap(); - if let Some(func) = syntax_mapping + if let Some(res) = source_map .node_expr(expr) - .and_then(|it| infer_result.assoc_fn_resolutions(it)) + .and_then(|it| infer_result.assoc_resolutions(it.into())) { - return Exact(NavigationTarget::from_function(db, func)); + match res { + ImplItem::Method(f) => { + return Exact(NavigationTarget::from_function(db, f)); + } + ImplItem::Const(c) => { + let (file, node) = c.source(db); + let file = file.original_file(db); + let node = &*node; + return Exact(NavigationTarget::from_named(file, node)); + } + _ => {} + } } } } diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 0f13777d7..bcd052c8b 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -531,7 +531,7 @@ mod tests { ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(hover.info.first(), Some("```rust\nfn new() -> Thing\n```")); + assert_eq!(trim_markup_opt(hover.info.first()), Some("fn new() -> Thing")); assert_eq!(hover.info.is_exact(), true); } } -- cgit v1.2.3 From e1b59bfe0b00157a97f167b4857418b914ec1fd3 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Sat, 2 Mar 2019 14:57:40 -0500 Subject: Add NavigationTarget::from_impl_item --- crates/ra_ide_api/src/goto_definition.rs | 15 ++------------- crates/ra_ide_api/src/navigation_target.rs | 21 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 14 deletions(-) (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 3b66483cb..f16c3bda4 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -5,7 +5,7 @@ use ra_syntax::{ SyntaxNode, }; use test_utils::tested_by; -use hir::{ImplItem, Resolution}; +use hir::Resolution; use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; @@ -138,18 +138,7 @@ pub(crate) fn reference_definition( .node_expr(expr) .and_then(|it| infer_result.assoc_resolutions(it.into())) { - match res { - ImplItem::Method(f) => { - return Exact(NavigationTarget::from_function(db, f)); - } - ImplItem::Const(c) => { - let (file, node) = c.source(db); - let file = file.original_file(db); - let node = &*node; - return Exact(NavigationTarget::from_named(file, node)); - } - _ => {} - } + return Exact(NavigationTarget::from_impl_item(db, res)); } } } diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 6538081ac..ff8d2f15b 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::{ SyntaxNode, SyntaxNodePtr, AstNode, SmolStr, TextRange, ast, SyntaxKind::{self, NAME}, }; -use hir::{ModuleSource, FieldSource, Name}; +use hir::{ModuleSource, FieldSource, Name, ImplItem}; use crate::{FileSymbol, db::RootDatabase}; @@ -174,6 +174,25 @@ impl NavigationTarget { ) } + pub(crate) fn from_impl_item( + db: &RootDatabase, + impl_item: hir::ImplItem, + ) -> NavigationTarget { + match impl_item { + ImplItem::Method(f) => { + NavigationTarget::from_function(db, f) + } + ImplItem::Const(c) => { + let (file_id, node) = c.source(db); + NavigationTarget::from_named(file_id.original_file(db), &*node) + } + ImplItem::TypeAlias(a) => { + let (file_id, node) = a.source(db); + NavigationTarget::from_named(file_id.original_file(db), &*node) + } + } + } + #[cfg(test)] pub(crate) fn assert_match(&self, expected: &str) { let actual = self.debug_render(); -- cgit v1.2.3 From 79f61dcb0e3de873c4685c9abaaf4ec5af748000 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Mon, 4 Mar 2019 08:34:41 -0500 Subject: Format --- crates/ra_ide_api/src/navigation_target.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index ff8d2f15b..d806cb368 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs @@ -174,14 +174,9 @@ impl NavigationTarget { ) } - pub(crate) fn from_impl_item( - db: &RootDatabase, - impl_item: hir::ImplItem, - ) -> NavigationTarget { + pub(crate) fn from_impl_item(db: &RootDatabase, impl_item: hir::ImplItem) -> NavigationTarget { match impl_item { - ImplItem::Method(f) => { - NavigationTarget::from_function(db, f) - } + ImplItem::Method(f) => NavigationTarget::from_function(db, f), ImplItem::Const(c) => { let (file_id, node) = c.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) -- cgit v1.2.3 From 1578375b89848b98a4d5187aaf794bc227d1eda6 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Mon, 4 Mar 2019 09:49:18 -0500 Subject: Make ExpOrPatId private --- crates/ra_ide_api/src/goto_definition.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index f16c3bda4..364263d9b 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -136,7 +136,7 @@ pub(crate) fn reference_definition( if let Some(res) = source_map .node_expr(expr) - .and_then(|it| infer_result.assoc_resolutions(it.into())) + .and_then(|it| infer_result.assoc_resolutions_for_expr(it.into())) { return Exact(NavigationTarget::from_impl_item(db, res)); } -- cgit v1.2.3