diff options
author | Jade <[email protected]> | 2021-05-25 13:46:15 +0100 |
---|---|---|
committer | Jade <[email protected]> | 2021-05-25 13:46:15 +0100 |
commit | 3e4dfaf97af127ed85ecac809fe4dbaad4c7531c (patch) | |
tree | 703e4be5b26d7e4042f5bb67e70d133d27f882aa /crates | |
parent | ff585e4730a867e7bb68c65ff45867a501841ae4 (diff) |
feat: go to implementation on trait functions
Fix #8537.
GIF:
https://user-images.githubusercontent.com/6652840/119501981-45a45c00-bd1e-11eb-8336-9145f2888643.gif
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ide/src/goto_implementation.rs | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs index 05130a237..5a8d3c3f9 100644 --- a/crates/ide/src/goto_implementation.rs +++ b/crates/ide/src/goto_implementation.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use hir::{Impl, Semantics}; | 1 | use hir::{AsAssocItem, Impl, Semantics}; |
2 | use ide_db::{ | 2 | use ide_db::{ |
3 | defs::{Definition, NameClass, NameRefClass}, | 3 | defs::{Definition, NameClass, NameRefClass}, |
4 | RootDatabase, | 4 | RootDatabase, |
@@ -36,6 +36,7 @@ pub(crate) fn goto_implementation( | |||
36 | } | 36 | } |
37 | ast::NameLike::Lifetime(_) => None, | 37 | ast::NameLike::Lifetime(_) => None, |
38 | }?; | 38 | }?; |
39 | |||
39 | let def = match def { | 40 | let def = match def { |
40 | Definition::ModuleDef(def) => def, | 41 | Definition::ModuleDef(def) => def, |
41 | _ => return None, | 42 | _ => return None, |
@@ -48,6 +49,12 @@ pub(crate) fn goto_implementation( | |||
48 | let module = sema.to_module_def(position.file_id)?; | 49 | let module = sema.to_module_def(position.file_id)?; |
49 | impls_for_ty(&sema, builtin.ty(sema.db, module)) | 50 | impls_for_ty(&sema, builtin.ty(sema.db, module)) |
50 | } | 51 | } |
52 | hir::ModuleDef::Function(f) => { | ||
53 | let assoc = f.as_assoc_item(sema.db)?; | ||
54 | let name = assoc.name(sema.db)?; | ||
55 | let trait_ = assoc.containing_trait(sema.db)?; | ||
56 | impls_for_trait_fn(&sema, trait_, name) | ||
57 | } | ||
51 | _ => return None, | 58 | _ => return None, |
52 | }; | 59 | }; |
53 | Some(RangeInfo { range: node.syntax().text_range(), info: navs }) | 60 | Some(RangeInfo { range: node.syntax().text_range(), info: navs }) |
@@ -64,6 +71,23 @@ fn impls_for_trait(sema: &Semantics<RootDatabase>, trait_: hir::Trait) -> Vec<Na | |||
64 | .collect() | 71 | .collect() |
65 | } | 72 | } |
66 | 73 | ||
74 | fn impls_for_trait_fn( | ||
75 | sema: &Semantics<RootDatabase>, | ||
76 | trait_: hir::Trait, | ||
77 | fun_name: hir::Name, | ||
78 | ) -> Vec<NavigationTarget> { | ||
79 | Impl::all_for_trait(sema.db, trait_) | ||
80 | .into_iter() | ||
81 | .filter_map(|imp| { | ||
82 | let item = imp.items(sema.db).iter().find_map(|itm| { | ||
83 | let itm_name = itm.name(sema.db)?; | ||
84 | (itm_name == fun_name).then(|| itm.clone()) | ||
85 | })?; | ||
86 | item.try_to_nav(sema.db) | ||
87 | }) | ||
88 | .collect() | ||
89 | } | ||
90 | |||
67 | #[cfg(test)] | 91 | #[cfg(test)] |
68 | mod tests { | 92 | mod tests { |
69 | use ide_db::base_db::FileRange; | 93 | use ide_db::base_db::FileRange; |
@@ -262,4 +286,24 @@ impl bool {} | |||
262 | "#, | 286 | "#, |
263 | ); | 287 | ); |
264 | } | 288 | } |
289 | |||
290 | #[test] | ||
291 | fn goto_implementation_trait_functions() { | ||
292 | check( | ||
293 | r#" | ||
294 | trait Tr { | ||
295 | fn f$0(); | ||
296 | } | ||
297 | |||
298 | struct S; | ||
299 | |||
300 | impl Tr for S { | ||
301 | fn f() { | ||
302 | //^ | ||
303 | println!("Hello, world!"); | ||
304 | } | ||
305 | } | ||
306 | "#, | ||
307 | ); | ||
308 | } | ||
265 | } | 309 | } |