Show GotoTypeAction for TypeParam

This commit is contained in:
Lukas Wirth 2021-01-04 15:44:19 +01:00
parent bd47e140b6
commit 54b9b03ca2
2 changed files with 66 additions and 17 deletions

View file

@ -1276,6 +1276,18 @@ impl TypeParam {
} }
} }
pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
db.generic_predicates_for_param(self.id)
.into_iter()
.filter_map(|pred| match &pred.value {
hir_ty::GenericPredicate::Implemented(trait_ref) => {
Some(Trait::from(trait_ref.trait_))
}
_ => None,
})
.collect()
}
pub fn default(self, db: &dyn HirDatabase) -> Option<Type> { pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
let params = db.generic_defaults(self.id.parent); let params = db.generic_defaults(self.id.parent);
let local_idx = hir_ty::param_idx(db, self.id)?; let local_idx = hir_ty::param_idx(db, self.id)?;

View file

@ -228,11 +228,6 @@ fn runnable_action(
} }
fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
let ty = match def {
Definition::Local(it) => it.ty(db),
Definition::ConstParam(it) => it.ty(db),
_ => return None,
};
let mut targets: Vec<ModuleDef> = Vec::new(); let mut targets: Vec<ModuleDef> = Vec::new();
let mut push_new_def = |item: ModuleDef| { let mut push_new_def = |item: ModuleDef| {
if !targets.contains(&item) { if !targets.contains(&item) {
@ -240,6 +235,15 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
} }
}; };
if let Definition::TypeParam(it) = def {
it.trait_bounds(db).into_iter().for_each(|it| push_new_def(it.into()));
} else {
let ty = match def {
Definition::Local(it) => it.ty(db),
Definition::ConstParam(it) => it.ty(db),
_ => return None,
};
ty.walk(db, |t| { ty.walk(db, |t| {
if let Some(adt) = t.as_adt() { if let Some(adt) = t.as_adt() {
push_new_def(adt.into()); push_new_def(adt.into());
@ -251,6 +255,7 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
push_new_def(trait_.into()); push_new_def(trait_.into());
} }
}); });
}
let targets = targets let targets = targets
.into_iter() .into_iter()
@ -3112,6 +3117,38 @@ impl<const BAR: Bar> Foo<BAR<|>> {}
); );
} }
#[test]
fn test_hover_type_param_has_goto_type_action() {
check_actions(
r#"
trait Foo {}
fn foo<T: Foo>(t: T<|>){}
"#,
expect![[r#"
[
GoToType(
[
HoverGotoTypeData {
mod_path: "test::Foo",
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 0..12,
focus_range: 6..9,
name: "Foo",
kind: Trait,
description: "trait Foo",
},
},
],
),
]
"#]],
);
}
#[test] #[test]
fn hover_displays_normalized_crate_names() { fn hover_displays_normalized_crate_names() {
check( check(