Skip to content

Commit 34ce057

Browse files
committed
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.
1 parent 8a57c73 commit 34ce057

File tree

1 file changed

+56
-18
lines changed

1 file changed

+56
-18
lines changed

crates/ide/src/goto_definition.rs

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub(crate) fn goto_definition(
5757
},
5858
ast::Name(name) => {
5959
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)
6161
.or_else(|| def.try_to_nav(sema.db))
6262
},
6363
ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) {
@@ -100,30 +100,32 @@ fn try_lookup_include_path(
100100
})
101101
}
102102

103-
/// finds the trait definition of an impl'd function
103+
/// finds the trait definition of an impl'd item
104104
/// e.g.
105105
/// ```rust
106106
/// trait A { fn a(); }
107107
/// struct S;
108108
/// impl A for S { fn a(); } // <-- on this function, will get the location of a() in the trait
109109
/// ```
110-
fn try_find_trait_fn_definition(db: &RootDatabase, def: &Definition) -> Option<NavigationTarget> {
111-
match def {
112-
Definition::ModuleDef(ModuleDef::Function(f)) => {
113-
let name = def.name(db)?;
114-
let assoc = f.as_assoc_item(db)?;
115-
let imp = match assoc.container(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-
}
110+
fn try_find_trait_item_definition(db: &RootDatabase, def: &Definition) -> Option<NavigationTarget> {
111+
let name = def.name(db)?;
112+
let assoc = match def {
113+
Definition::ModuleDef(ModuleDef::Function(f)) => f.as_assoc_item(db),
114+
Definition::ModuleDef(ModuleDef::Const(c)) => c.as_assoc_item(db),
115+
Definition::ModuleDef(ModuleDef::TypeAlias(ty)) => ty.as_assoc_item(db),
125116
_ => 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())
127129
}
128130

129131
fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
@@ -1304,6 +1306,42 @@ struct Stwuct;
13041306
impl Twait for Stwuct {
13051307
fn a$0();
13061308
}
1309+
"#,
1310+
);
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+
}
13071345
"#,
13081346
);
13091347
}

0 commit comments

Comments
 (0)