aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/goto_definition.rs74
1 files changed, 56 insertions, 18 deletions
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index c236039f4..2d36c34e9 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -57,7 +57,7 @@ pub(crate) fn goto_definition(
57 }, 57 },
58 ast::Name(name) => { 58 ast::Name(name) => {
59 let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db); 59 let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db);
60 try_find_trait_fn_definition(&sema.db, &def) 60 try_find_trait_item_definition(&sema.db, &def)
61 .or_else(|| def.try_to_nav(sema.db)) 61 .or_else(|| def.try_to_nav(sema.db))
62 }, 62 },
63 ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) { 63 ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) {
@@ -100,30 +100,32 @@ fn try_lookup_include_path(
100 }) 100 })
101} 101}
102 102
103/// finds the trait definition of an impl'd function 103/// finds the trait definition of an impl'd item
104/// e.g. 104/// e.g.
105/// ```rust 105/// ```rust
106/// trait A { fn a(); } 106/// trait A { fn a(); }
107/// struct S; 107/// struct S;
108/// impl A for S { fn a(); } // <-- on this function, will get the location of a() in the trait 108/// impl A for S { fn a(); } // <-- on this function, will get the location of a() in the trait
109/// ``` 109/// ```
110fn try_find_trait_fn_definition(db: &RootDatabase, def: &Definition) -> Option<NavigationTarget> { 110fn try_find_trait_item_definition(db: &RootDatabase, def: &Definition) -> Option<NavigationTarget> {
111 match def { 111 let name = def.name(db)?;
112 Definition::ModuleDef(ModuleDef::Function(f)) => { 112 let assoc = match def {
113 let name = def.name(db)?; 113 Definition::ModuleDef(ModuleDef::Function(f)) => f.as_assoc_item(db),
114 let assoc = f.as_assoc_item(db)?; 114 Definition::ModuleDef(ModuleDef::Const(c)) => c.as_assoc_item(db),
115 let imp = match assoc.container(db) { 115 Definition::ModuleDef(ModuleDef::TypeAlias(ty)) => ty.as_assoc_item(db),
116 hir::AssocItemContainer::Impl(imp) => imp,
117 _ => return None,
118 };
119 let trait_ = imp.trait_(db)?;
120 trait_
121 .items(db)
122 .iter()
123 .find_map(|itm| (itm.name(db)? == name).then(|| itm.try_to_nav(db)).flatten())
124 }
125 _ => None, 116 _ => None,
126 } 117 }?;
118
119 let imp = match assoc.container(db) {
120 hir::AssocItemContainer::Impl(imp) => imp,
121 _ => return None,
122 };
123
124 let trait_ = imp.trait_(db)?;
125 trait_
126 .items(db)
127 .iter()
128 .find_map(|itm| (itm.name(db)? == name).then(|| itm.try_to_nav(db)).flatten())
127} 129}
128 130
129fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { 131fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
@@ -1307,4 +1309,40 @@ impl Twait for Stwuct {
1307"#, 1309"#,
1308 ); 1310 );
1309 } 1311 }
1312
1313 #[test]
1314 fn goto_def_of_trait_impl_const() {
1315 check(
1316 r#"
1317trait Twait {
1318 const NOMS: bool;
1319 // ^^^^
1320}
1321
1322struct Stwuct;
1323
1324impl Twait for Stwuct {
1325 const NOMS$0: bool = true;
1326}
1327"#,
1328 );
1329 }
1330
1331 #[test]
1332 fn goto_def_of_trait_impl_type_alias() {
1333 check(
1334 r#"
1335trait Twait {
1336 type IsBad;
1337 // ^^^^^
1338}
1339
1340struct Stwuct;
1341
1342impl Twait for Stwuct {
1343 type IsBad$0 = !;
1344}
1345"#,
1346 );
1347 }
1310} 1348}