diff options
author | Lukas Wirth <[email protected]> | 2020-11-28 21:50:59 +0000 |
---|---|---|
committer | Lukas Wirth <[email protected]> | 2020-11-29 11:28:47 +0000 |
commit | 37438c3335cedc6d89e47cc123a5c23dabaef2a2 (patch) | |
tree | 2655046584291d7da76899c14a14533d7ebcf081 | |
parent | a6f26ded0037a3efb5625ac3482a2f4ec9eb01a3 (diff) |
Support 'go to definition' for self
-rw-r--r-- | crates/ide/src/goto_definition.rs | 56 |
1 files changed, 39 insertions, 17 deletions
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 @@ | |||
1 | use hir::Semantics; | 1 | use hir::Semantics; |
2 | use ide_db::{ | 2 | use ide_db::{ |
3 | base_db::FileId, | ||
3 | defs::{NameClass, NameRefClass}, | 4 | defs::{NameClass, NameRefClass}, |
4 | symbol_index, RootDatabase, | 5 | symbol_index, RootDatabase, |
5 | }; | 6 | }; |
@@ -40,10 +41,17 @@ pub(crate) fn goto_definition( | |||
40 | vec![nav] | 41 | vec![nav] |
41 | }, | 42 | }, |
42 | ast::SelfParam(self_param) => { | 43 | ast::SelfParam(self_param) => { |
43 | let ty = sema.type_of_self(&self_param)?; | 44 | vec![self_to_nav_target(self_param, position.file_id)?] |
44 | let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?; | 45 | }, |
45 | let nav = adt_def.to_nav(db); | 46 | ast::PathSegment(segment) => { |
46 | vec![nav] | 47 | segment.self_token()?; |
48 | let path = segment.parent_path(); | ||
49 | if path.qualifier().is_some() && !ast::PathExpr::can_cast(path.syntax().parent()?.kind()) { | ||
50 | return None; | ||
51 | } | ||
52 | let func = segment.syntax().ancestors().find_map(ast::Fn::cast)?; | ||
53 | let self_param = func.param_list()?.self_param()?; | ||
54 | vec![self_to_nav_target(self_param, position.file_id)?] | ||
47 | }, | 55 | }, |
48 | _ => return None, | 56 | _ => return None, |
49 | } | 57 | } |
@@ -63,6 +71,20 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | |||
63 | } | 71 | } |
64 | } | 72 | } |
65 | 73 | ||
74 | fn self_to_nav_target(self_param: ast::SelfParam, file_id: FileId) -> Option<NavigationTarget> { | ||
75 | let self_token = self_param.self_token()?; | ||
76 | Some(NavigationTarget { | ||
77 | file_id, | ||
78 | full_range: self_param.syntax().text_range(), | ||
79 | focus_range: Some(self_token.text_range()), | ||
80 | name: self_token.text().clone(), | ||
81 | kind: self_token.kind(), | ||
82 | container_name: None, | ||
83 | description: None, | ||
84 | docs: None, | ||
85 | }) | ||
86 | } | ||
87 | |||
66 | #[derive(Debug)] | 88 | #[derive(Debug)] |
67 | pub(crate) enum ReferenceResult { | 89 | pub(crate) enum ReferenceResult { |
68 | Exact(NavigationTarget), | 90 | Exact(NavigationTarget), |
@@ -987,31 +1009,31 @@ fn g() -> <() as Iterator<A = (), B<|> = u8>>::A {} | |||
987 | } | 1009 | } |
988 | 1010 | ||
989 | #[test] | 1011 | #[test] |
990 | fn todo_def_type_for_self() { | 1012 | fn goto_self_param_ty_specified() { |
991 | check( | 1013 | check( |
992 | r#" | 1014 | r#" |
993 | struct Foo {} | 1015 | struct Foo {} |
994 | //^^^ | ||
995 | 1016 | ||
996 | impl Foo { | 1017 | impl Foo { |
997 | fn bar(&self<|>) {} | 1018 | fn bar(self: &Foo) { |
998 | } | 1019 | //^^^^ |
999 | "#, | 1020 | let foo = sel<|>f; |
1000 | ); | 1021 | } |
1022 | }"#, | ||
1023 | ) | ||
1001 | } | 1024 | } |
1002 | 1025 | ||
1003 | #[test] | 1026 | #[test] |
1004 | fn todo_def_type_for_arbitrary_self() { | 1027 | fn goto_self_param_on_decl() { |
1005 | check( | 1028 | check( |
1006 | r#" | 1029 | r#" |
1007 | struct Arc<T>(T); | ||
1008 | //^^^ | ||
1009 | struct Foo {} | 1030 | struct Foo {} |
1010 | 1031 | ||
1011 | impl Foo { | 1032 | impl Foo { |
1012 | fn bar(self<|>: Arc<Self>) {} | 1033 | fn bar(&self<|>) { |
1013 | } | 1034 | //^^^^ |
1014 | "#, | 1035 | } |
1015 | ); | 1036 | }"#, |
1037 | ) | ||
1016 | } | 1038 | } |
1017 | } | 1039 | } |