mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-03 07:04:49 +00:00
goto where trait method impl
This commit is contained in:
parent
6fc5c3cd21
commit
1ef5e14c2c
5 changed files with 366 additions and 117 deletions
|
@ -1,7 +1,7 @@
|
|||
use std::convert::TryInto;
|
||||
|
||||
use crate::{doc_links::token_as_doc_comment, FilePosition, NavigationTarget, RangeInfo, TryToNav};
|
||||
use hir::{AsAssocItem, Semantics};
|
||||
use hir::{AsAssocItem, AssocItem, Semantics};
|
||||
use ide_db::{
|
||||
base_db::{AnchoredPath, FileId, FileLoader},
|
||||
defs::{Definition, IdentClass},
|
||||
|
@ -65,7 +65,7 @@ pub(crate) fn goto_definition(
|
|||
.definitions()
|
||||
.into_iter()
|
||||
.flat_map(|def| {
|
||||
try_find_trait_item_definition(sema.db, &def)
|
||||
try_filter_trait_item_definition(sema, &def, &token)
|
||||
.unwrap_or_else(|| def_to_nav(sema.db, def))
|
||||
})
|
||||
.collect(),
|
||||
|
@ -104,32 +104,38 @@ fn try_lookup_include_path(
|
|||
docs: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// finds the trait definition of an impl'd item
|
||||
/// finds the trait definition of an impl'd item, except function
|
||||
/// e.g.
|
||||
/// ```rust
|
||||
/// trait A { fn a(); }
|
||||
/// trait A { type a; }
|
||||
/// struct S;
|
||||
/// impl A for S { fn a(); } // <-- on this function, will get the location of a() in the trait
|
||||
/// impl A for S { type a = i32; } // <-- on this associate type, will get the location of a in the trait
|
||||
/// ```
|
||||
fn try_find_trait_item_definition(
|
||||
db: &RootDatabase,
|
||||
fn try_filter_trait_item_definition(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
def: &Definition,
|
||||
token: &SyntaxToken,
|
||||
) -> Option<Vec<NavigationTarget>> {
|
||||
let name = def.name(db)?;
|
||||
let db = sema.db;
|
||||
let assoc = def.as_assoc_item(db)?;
|
||||
|
||||
let imp = match assoc.container(db) {
|
||||
hir::AssocItemContainer::Impl(imp) => imp,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let trait_ = imp.trait_(db)?;
|
||||
trait_
|
||||
.items(db)
|
||||
.iter()
|
||||
.find_map(|itm| (itm.name(db)? == name).then(|| itm.try_to_nav(db)).flatten())
|
||||
.map(|it| vec![it])
|
||||
match assoc {
|
||||
AssocItem::Function(..) => {
|
||||
IdentClass::classify_token_to_impl(sema, &token).map(|def| def_to_nav(db, def))
|
||||
}
|
||||
AssocItem::Const(..) | AssocItem::TypeAlias(..) => {
|
||||
let imp = match assoc.container(db) {
|
||||
hir::AssocItemContainer::Impl(imp) => imp,
|
||||
_ => return None,
|
||||
};
|
||||
let trait_ = imp.trait_(db)?;
|
||||
let name = def.name(db)?;
|
||||
trait_
|
||||
.items(db)
|
||||
.iter()
|
||||
.find_map(|itm| (itm.name(db)? == name).then(|| itm.try_to_nav(db)).flatten())
|
||||
.map(|it| vec![it])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn def_to_nav(db: &RootDatabase, def: Definition) -> Vec<NavigationTarget> {
|
||||
|
@ -1331,23 +1337,98 @@ fn main() {
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_def_of_trait_impl_fn() {
|
||||
check(
|
||||
r#"
|
||||
#[cfg(test)]
|
||||
mod goto_impl_of_trait_fn {
|
||||
use super::check;
|
||||
#[test]
|
||||
fn cursor_on_impl() {
|
||||
check(
|
||||
r#"
|
||||
trait Twait {
|
||||
fn a();
|
||||
// ^
|
||||
}
|
||||
|
||||
struct Stwuct;
|
||||
|
||||
impl Twait for Stwuct {
|
||||
fn a$0();
|
||||
//^
|
||||
}
|
||||
"#,
|
||||
);
|
||||
"#,
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn method_call() {
|
||||
check(
|
||||
r#"
|
||||
trait Twait {
|
||||
fn a(&self);
|
||||
}
|
||||
|
||||
struct Stwuct;
|
||||
|
||||
impl Twait for Stwuct {
|
||||
fn a(&self){};
|
||||
//^
|
||||
}
|
||||
fn f() {
|
||||
let s = Stwuct;
|
||||
s.a$0();
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn path_call() {
|
||||
check(
|
||||
r#"
|
||||
trait Twait {
|
||||
fn a(&self);
|
||||
}
|
||||
|
||||
struct Stwuct;
|
||||
|
||||
impl Twait for Stwuct {
|
||||
fn a(&self){};
|
||||
//^
|
||||
}
|
||||
fn f() {
|
||||
let s = Stwuct;
|
||||
Stwuct::a$0(&s);
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn where_clause_can_work() {
|
||||
check(
|
||||
r#"
|
||||
trait G {
|
||||
fn g(&self);
|
||||
}
|
||||
trait Bound{}
|
||||
trait EA{}
|
||||
struct Gen<T>(T);
|
||||
impl <T:EA> G for Gen<T> {
|
||||
fn g(&self) {
|
||||
}
|
||||
}
|
||||
impl <T> G for Gen<T>
|
||||
where T : Bound
|
||||
{
|
||||
fn g(&self){
|
||||
//^
|
||||
}
|
||||
}
|
||||
struct A;
|
||||
impl Bound for A{}
|
||||
fn f() {
|
||||
let gen = Gen::<A>(A);
|
||||
gen.g$0();
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue