From 37438c3335cedc6d89e47cc123a5c23dabaef2a2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 28 Nov 2020 22:50:59 +0100 Subject: Support 'go to definition' for self --- crates/ide/src/goto_definition.rs | 56 +++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 17 deletions(-) (limited to 'crates/ide') diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index d41dd3d92..b9810457f 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -1,5 +1,6 @@ use hir::Semantics; use ide_db::{ + base_db::FileId, defs::{NameClass, NameRefClass}, symbol_index, RootDatabase, }; @@ -40,10 +41,17 @@ pub(crate) fn goto_definition( vec![nav] }, ast::SelfParam(self_param) => { - let ty = sema.type_of_self(&self_param)?; - let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?; - let nav = adt_def.to_nav(db); - vec![nav] + vec![self_to_nav_target(self_param, position.file_id)?] + }, + ast::PathSegment(segment) => { + segment.self_token()?; + let path = segment.parent_path(); + if path.qualifier().is_some() && !ast::PathExpr::can_cast(path.syntax().parent()?.kind()) { + return None; + } + let func = segment.syntax().ancestors().find_map(ast::Fn::cast)?; + let self_param = func.param_list()?.self_param()?; + vec![self_to_nav_target(self_param, position.file_id)?] }, _ => return None, } @@ -63,6 +71,20 @@ fn pick_best(tokens: TokenAtOffset) -> Option { } } +fn self_to_nav_target(self_param: ast::SelfParam, file_id: FileId) -> Option { + let self_token = self_param.self_token()?; + Some(NavigationTarget { + file_id, + full_range: self_param.syntax().text_range(), + focus_range: Some(self_token.text_range()), + name: self_token.text().clone(), + kind: self_token.kind(), + container_name: None, + description: None, + docs: None, + }) +} + #[derive(Debug)] pub(crate) enum ReferenceResult { Exact(NavigationTarget), @@ -987,31 +1009,31 @@ fn g() -> <() as Iterator = u8>>::A {} } #[test] - fn todo_def_type_for_self() { + fn goto_self_param_ty_specified() { check( r#" struct Foo {} - //^^^ impl Foo { - fn bar(&self<|>) {} -} -"#, - ); + fn bar(self: &Foo) { + //^^^^ + let foo = sel<|>f; + } +}"#, + ) } #[test] - fn todo_def_type_for_arbitrary_self() { + fn goto_self_param_on_decl() { check( r#" -struct Arc(T); - //^^^ struct Foo {} impl Foo { - fn bar(self<|>: Arc) {} -} -"#, - ); + fn bar(&self<|>) { + //^^^^ + } +}"#, + ) } } -- cgit v1.2.3