about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/ide/src/goto_implementation.rs46
1 files changed, 45 insertions, 1 deletions
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index 05130a23765..5a8d3c3f98f 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -1,4 +1,4 @@
-use hir::{Impl, Semantics};
+use hir::{AsAssocItem, Impl, Semantics};
 use ide_db::{
     defs::{Definition, NameClass, NameRefClass},
     RootDatabase,
@@ -36,6 +36,7 @@ pub(crate) fn goto_implementation(
         }
         ast::NameLike::Lifetime(_) => None,
     }?;
+
     let def = match def {
         Definition::ModuleDef(def) => def,
         _ => return None,
@@ -48,6 +49,12 @@ pub(crate) fn goto_implementation(
             let module = sema.to_module_def(position.file_id)?;
             impls_for_ty(&sema, builtin.ty(sema.db, module))
         }
+        hir::ModuleDef::Function(f) => {
+            let assoc = f.as_assoc_item(sema.db)?;
+            let name = assoc.name(sema.db)?;
+            let trait_ = assoc.containing_trait(sema.db)?;
+            impls_for_trait_fn(&sema, trait_, name)
+        }
         _ => return None,
     };
     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
         .collect()
 }
 
+fn impls_for_trait_fn(
+    sema: &Semantics<RootDatabase>,
+    trait_: hir::Trait,
+    fun_name: hir::Name,
+) -> Vec<NavigationTarget> {
+    Impl::all_for_trait(sema.db, trait_)
+        .into_iter()
+        .filter_map(|imp| {
+            let item = imp.items(sema.db).iter().find_map(|itm| {
+                let itm_name = itm.name(sema.db)?;
+                (itm_name == fun_name).then(|| itm.clone())
+            })?;
+            item.try_to_nav(sema.db)
+        })
+        .collect()
+}
+
 #[cfg(test)]
 mod tests {
     use ide_db::base_db::FileRange;
@@ -262,4 +286,24 @@ impl bool {}
 "#,
         );
     }
+
+    #[test]
+    fn goto_implementation_trait_functions() {
+        check(
+            r#"
+trait Tr {
+    fn f$0();
+}
+
+struct S;
+
+impl Tr for S {
+    fn f() {
+     //^
+        println!("Hello, world!");
+    }
+}
+"#,
+        );
+    }
 }