From eedc08300c427b854db56f8fe1f1866ed398d5ee Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 13 Jan 2019 18:56:57 +0300 Subject: goto defenition works for type-inferred methods --- crates/ra_ide_api/src/goto_definition.rs | 51 ++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'crates/ra_ide_api/src/goto_definition.rs') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index e2537758d..332a2fb8d 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -47,15 +47,34 @@ pub(crate) fn reference_definition( name_ref: &ast::NameRef, ) -> Cancelable { use self::ReferenceResult::*; - if let Some(fn_descr) = + if let Some(function) = hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax())? { - let scope = fn_descr.scopes(db)?; + let scope = function.scopes(db)?; // First try to resolve the symbol locally if let Some(entry) = scope.resolve_local_name(name_ref) { let nav = NavigationTarget::from_scope_entry(file_id, &entry); return Ok(Exact(nav)); }; + + // Next check if it is a method + if let Some(method_call) = name_ref + .syntax() + .parent() + .and_then(ast::MethodCallExpr::cast) + { + let infer_result = function.infer(db)?; + let syntax_mapping = function.body_syntax_mapping(db)?; + let expr = ast::Expr::cast(method_call.syntax()).unwrap(); + if let Some(def_id) = syntax_mapping + .node_expr(expr) + .and_then(|it| infer_result.method_resolution(it)) + { + if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)?)? { + return Ok(Exact(target)); + } + }; + } } // Then try module name resolution if let Some(module) = @@ -167,4 +186,32 @@ mod tests { "foo SOURCE_FILE FileId(2) [0; 10)", ); } + + #[test] + fn goto_definition_works_for_methods() { + check_goto( + " + //- /lib.rs + struct Foo; + impl Foo { + fn frobnicate(&self) { } + } + + fn bar(foo: &Foo) { + foo.frobnicate<|>(); + } + ", + "frobnicate FN_DEF FileId(1) [27; 52) [30; 40)", + ); + + check_goto( + " + //- /lib.rs + mod <|>foo; + //- /foo/mod.rs + // empty + ", + "foo SOURCE_FILE FileId(2) [0; 10)", + ); + } } -- cgit v1.2.3