6666: Support 'go to definition' for self r=jonas-schievink a=Veykril

Also reverts #6660, instead of showing the type it now works like it does for names by returning the declaration we are already on. This for example enables VSCode to show all references(#6665) when executing `go to definition` on the declaration.

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2020-11-29 14:35:38 +00:00 committed by GitHub
commit 05f75d601f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,5 +1,6 @@
use hir::Semantics; use hir::Semantics;
use ide_db::{ use ide_db::{
base_db::FileId,
defs::{NameClass, NameRefClass}, defs::{NameClass, NameRefClass},
symbol_index, RootDatabase, symbol_index, RootDatabase,
}; };
@ -40,10 +41,17 @@ pub(crate) fn goto_definition(
vec![nav] vec![nav]
}, },
ast::SelfParam(self_param) => { ast::SelfParam(self_param) => {
let ty = sema.type_of_self(&self_param)?; vec![self_to_nav_target(self_param, position.file_id)?]
let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?; },
let nav = adt_def.to_nav(db); ast::PathSegment(segment) => {
vec![nav] 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, _ => return None,
} }
@ -63,6 +71,20 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
} }
} }
fn self_to_nav_target(self_param: ast::SelfParam, file_id: FileId) -> Option<NavigationTarget> {
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)] #[derive(Debug)]
pub(crate) enum ReferenceResult { pub(crate) enum ReferenceResult {
Exact(NavigationTarget), Exact(NavigationTarget),
@ -987,31 +1009,31 @@ fn g() -> <() as Iterator<A = (), B<|> = u8>>::A {}
} }
#[test] #[test]
fn todo_def_type_for_self() { fn goto_self_param_ty_specified() {
check( check(
r#" r#"
struct Foo {} struct Foo {}
//^^^
impl Foo { impl Foo {
fn bar(&self<|>) {} fn bar(self: &Foo) {
} //^^^^
"#, let foo = sel<|>f;
); }
}"#,
)
} }
#[test] #[test]
fn todo_def_type_for_arbitrary_self() { fn goto_self_param_on_decl() {
check( check(
r#" r#"
struct Arc<T>(T);
//^^^
struct Foo {} struct Foo {}
impl Foo { impl Foo {
fn bar(self<|>: Arc<Self>) {} fn bar(&self<|>) {
} //^^^^
"#, }
); }"#,
)
} }
} }