Skip to content

Commit 54b9b03

Browse files
committed
Show GotoTypeAction for TypeParam
1 parent bd47e14 commit 54b9b03

File tree

2 files changed

+66
-17
lines changed

2 files changed

+66
-17
lines changed

crates/hir/src/code_model.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,18 @@ impl TypeParam {
12761276
}
12771277
}
12781278

1279+
pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
1280+
db.generic_predicates_for_param(self.id)
1281+
.into_iter()
1282+
.filter_map(|pred| match &pred.value {
1283+
hir_ty::GenericPredicate::Implemented(trait_ref) => {
1284+
Some(Trait::from(trait_ref.trait_))
1285+
}
1286+
_ => None,
1287+
})
1288+
.collect()
1289+
}
1290+
12791291
pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
12801292
let params = db.generic_defaults(self.id.parent);
12811293
let local_idx = hir_ty::param_idx(db, self.id)?;

crates/ide/src/hover.rs

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -228,29 +228,34 @@ fn runnable_action(
228228
}
229229

230230
fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
231-
let ty = match def {
232-
Definition::Local(it) => it.ty(db),
233-
Definition::ConstParam(it) => it.ty(db),
234-
_ => return None,
235-
};
236231
let mut targets: Vec<ModuleDef> = Vec::new();
237232
let mut push_new_def = |item: ModuleDef| {
238233
if !targets.contains(&item) {
239234
targets.push(item);
240235
}
241236
};
242237

243-
ty.walk(db, |t| {
244-
if let Some(adt) = t.as_adt() {
245-
push_new_def(adt.into());
246-
} else if let Some(trait_) = t.as_dyn_trait() {
247-
push_new_def(trait_.into());
248-
} else if let Some(traits) = t.as_impl_traits(db) {
249-
traits.into_iter().for_each(|it| push_new_def(it.into()));
250-
} else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
251-
push_new_def(trait_.into());
252-
}
253-
});
238+
if let Definition::TypeParam(it) = def {
239+
it.trait_bounds(db).into_iter().for_each(|it| push_new_def(it.into()));
240+
} else {
241+
let ty = match def {
242+
Definition::Local(it) => it.ty(db),
243+
Definition::ConstParam(it) => it.ty(db),
244+
_ => return None,
245+
};
246+
247+
ty.walk(db, |t| {
248+
if let Some(adt) = t.as_adt() {
249+
push_new_def(adt.into());
250+
} else if let Some(trait_) = t.as_dyn_trait() {
251+
push_new_def(trait_.into());
252+
} else if let Some(traits) = t.as_impl_traits(db) {
253+
traits.into_iter().for_each(|it| push_new_def(it.into()));
254+
} else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
255+
push_new_def(trait_.into());
256+
}
257+
});
258+
}
254259

255260
let targets = targets
256261
.into_iter()
@@ -3086,7 +3091,7 @@ fn main() { let s<|>t = test().get(); }
30863091
struct Bar;
30873092
struct Foo<const BAR: Bar>;
30883093
3089-
impl<const BAR: Bar> Foo<BAR<|>> {}
3094+
impl<const BAR: Bar> Foo<BAR<|>> {}
30903095
"#,
30913096
expect![[r#"
30923097
[
@@ -3112,6 +3117,38 @@ impl<const BAR: Bar> Foo<BAR<|>> {}
31123117
);
31133118
}
31143119

3120+
#[test]
3121+
fn test_hover_type_param_has_goto_type_action() {
3122+
check_actions(
3123+
r#"
3124+
trait Foo {}
3125+
3126+
fn foo<T: Foo>(t: T<|>){}
3127+
"#,
3128+
expect![[r#"
3129+
[
3130+
GoToType(
3131+
[
3132+
HoverGotoTypeData {
3133+
mod_path: "test::Foo",
3134+
nav: NavigationTarget {
3135+
file_id: FileId(
3136+
0,
3137+
),
3138+
full_range: 0..12,
3139+
focus_range: 6..9,
3140+
name: "Foo",
3141+
kind: Trait,
3142+
description: "trait Foo",
3143+
},
3144+
},
3145+
],
3146+
),
3147+
]
3148+
"#]],
3149+
);
3150+
}
3151+
31153152
#[test]
31163153
fn hover_displays_normalized_crate_names() {
31173154
check(

0 commit comments

Comments
 (0)