diff options
author | Jade <[email protected]> | 2021-06-07 05:48:06 +0100 |
---|---|---|
committer | Jade <[email protected]> | 2021-06-07 05:52:00 +0100 |
commit | 34ce05781fbca1bc6b717cce3bee6bd9923248b2 (patch) | |
tree | 062f9e4fdb3e675c5a361e3f14a5659a6f4bb810 /crates/ide | |
parent | 8a57c736404abac81a6de20b0e90c19021e040b9 (diff) |
feat: goto def on impl items also goes to the defn in the trait
It was trivial to extend this to associated consts/associated types and
I just didn't think of it.
Diffstat (limited to 'crates/ide')
-rw-r--r-- | crates/ide/src/goto_definition.rs | 74 |
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, <) { | 63 | ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, <) { |
@@ -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 | /// ``` |
110 | fn try_find_trait_fn_definition(db: &RootDatabase, def: &Definition) -> Option<NavigationTarget> { | 110 | fn 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 | ||
129 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | 131 | fn 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#" | ||
1317 | trait Twait { | ||
1318 | const NOMS: bool; | ||
1319 | // ^^^^ | ||
1320 | } | ||
1321 | |||
1322 | struct Stwuct; | ||
1323 | |||
1324 | impl 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#" | ||
1335 | trait Twait { | ||
1336 | type IsBad; | ||
1337 | // ^^^^^ | ||
1338 | } | ||
1339 | |||
1340 | struct Stwuct; | ||
1341 | |||
1342 | impl Twait for Stwuct { | ||
1343 | type IsBad$0 = !; | ||
1344 | } | ||
1345 | "#, | ||
1346 | ); | ||
1347 | } | ||
1310 | } | 1348 | } |