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/src') 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