mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 13:25:09 +00:00
Go To Implementation for Trait
This commit is contained in:
parent
4c0ab7db85
commit
f0fdc9d5c0
3 changed files with 140 additions and 26 deletions
|
@ -15,9 +15,27 @@ pub(crate) fn goto_implementation(
|
|||
let syntax = file.syntax();
|
||||
|
||||
let module = source_binder::module_from_position(db, position)?;
|
||||
let krate = module.krate(db)?;
|
||||
|
||||
let node = find_node_at_offset::<ast::NominalDef>(syntax, position.offset)?;
|
||||
if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(syntax, position.offset) {
|
||||
return Some(RangeInfo::new(
|
||||
nominal_def.syntax().range(),
|
||||
impls_for_def(db, nominal_def, module)?,
|
||||
));
|
||||
} else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(syntax, position.offset) {
|
||||
return Some(RangeInfo::new(
|
||||
trait_def.syntax().range(),
|
||||
impls_for_trait(db, trait_def, module)?,
|
||||
));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn impls_for_def(
|
||||
db: &RootDatabase,
|
||||
node: &ast::NominalDef,
|
||||
module: hir::Module,
|
||||
) -> Option<Vec<NavigationTarget>> {
|
||||
let ty = match node.kind() {
|
||||
ast::NominalDefKind::StructDef(def) => {
|
||||
source_binder::struct_from_module(db, module, &def).ty(db)
|
||||
|
@ -27,13 +45,33 @@ pub(crate) fn goto_implementation(
|
|||
}
|
||||
};
|
||||
|
||||
let krate = module.krate(db)?;
|
||||
let impls = db.impls_in_crate(krate);
|
||||
|
||||
let navs = impls
|
||||
.lookup_impl_blocks(db, &ty)
|
||||
.map(|(module, imp)| NavigationTarget::from_impl_block(db, module, &imp));
|
||||
Some(
|
||||
impls
|
||||
.lookup_impl_blocks(db, &ty)
|
||||
.map(|(module, imp)| NavigationTarget::from_impl_block(db, module, &imp))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
Some(RangeInfo::new(node.syntax().range(), navs.collect()))
|
||||
fn impls_for_trait(
|
||||
db: &RootDatabase,
|
||||
node: &ast::TraitDef,
|
||||
module: hir::Module,
|
||||
) -> Option<Vec<NavigationTarget>> {
|
||||
let tr = source_binder::trait_from_module(db, module, node);
|
||||
|
||||
let krate = module.krate(db)?;
|
||||
let impls = db.impls_in_crate(krate);
|
||||
|
||||
Some(
|
||||
impls
|
||||
.lookup_impl_blocks_for_trait(db, &tr)
|
||||
.map(|(module, imp)| NavigationTarget::from_impl_block(db, module, &imp))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -117,4 +155,38 @@ mod tests {
|
|||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_implementation_for_trait() {
|
||||
check_goto(
|
||||
"
|
||||
//- /lib.rs
|
||||
trait T<|> {}
|
||||
struct Foo;
|
||||
impl T for Foo {}
|
||||
",
|
||||
&["impl IMPL_BLOCK FileId(1) [23; 40)"],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_implementation_for_trait_multiple_files() {
|
||||
check_goto(
|
||||
"
|
||||
//- /lib.rs
|
||||
trait T<|> {};
|
||||
struct Foo;
|
||||
mod a;
|
||||
mod b;
|
||||
//- /a.rs
|
||||
impl crate::T for crate::Foo {}
|
||||
//- /b.rs
|
||||
impl crate::T for crate::Foo {}
|
||||
",
|
||||
&[
|
||||
"impl IMPL_BLOCK FileId(2) [0; 31)",
|
||||
"impl IMPL_BLOCK FileId(3) [0; 31)",
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue