-use hir::{Impl, Semantics};
+use hir::{AsAssocItem, Impl, Semantics};
use ide_db::{
defs::{Definition, NameClass, NameRefClass},
RootDatabase,
//
// | VS Code | kbd:[Ctrl+F12]
// |===
+//
+// image::https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif[]
pub(crate) fn goto_implementation(
db: &RootDatabase,
position: FilePosition,
let node = sema.find_node_at_offset_with_descend(&syntax, position.offset)?;
let def = match &node {
ast::NameLike::Name(name) => {
- NameClass::classify(&sema, name).map(|class| class.referenced_or_defined(sema.db))
+ NameClass::classify(&sema, name).map(|class| class.defined_or_referenced_local())
}
ast::NameLike::NameRef(name_ref) => {
- NameRefClass::classify(&sema, name_ref).map(|class| class.referenced(sema.db))
+ NameRefClass::classify(&sema, name_ref).map(|class| class.referenced_local())
}
ast::NameLike::Lifetime(_) => None,
}?;
+
let def = match def {
Definition::ModuleDef(def) => def,
_ => return None,
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_or_trait_impl(sema.db)?;
+ impls_for_trait_item(&sema, trait_, name)
+ }
+ hir::ModuleDef::Const(c) => {
+ let assoc = c.as_assoc_item(sema.db)?;
+ let name = assoc.name(sema.db)?;
+ let trait_ = assoc.containing_trait_or_trait_impl(sema.db)?;
+ impls_for_trait_item(&sema, trait_, name)
+ }
_ => return None,
};
Some(RangeInfo { range: node.syntax().text_range(), info: navs })
.collect()
}
+fn impls_for_trait_item(
+ 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)
+ })?;
+ item.try_to_nav(sema.db)
+ })
+ .collect()
+}
+
#[cfg(test)]
mod tests {
use ide_db::base_db::FileRange;
fn goto_implementation_to_builtin_derive() {
check(
r#"
+//- minicore: copy, derive
#[derive(Copy)]
//^^^^^^^^^^^^^^^
struct Foo$0;
-
-mod marker {
- trait Copy {}
-}
-#[rustc_builtin_macro]
-macro Copy {}
"#,
);
}
#[lang = "bool"]
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!");
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_implementation_trait_assoc_const() {
+ check(
+ r#"
+trait Tr {
+ const C$0: usize;
+}
+
+struct S;
+
+impl Tr for S {
+ const C: usize = 4;
+ //^
+}
"#,
);
}