diff options
-rw-r--r-- | crates/hir/src/code_model.rs | 12 | ||||
-rw-r--r-- | crates/ide/src/hover.rs | 71 |
2 files changed, 66 insertions, 17 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index a7a38d43a..071e553a8 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -1276,6 +1276,18 @@ impl TypeParam { | |||
1276 | } | 1276 | } |
1277 | } | 1277 | } |
1278 | 1278 | ||
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 | |||
1279 | pub fn default(self, db: &dyn HirDatabase) -> Option<Type> { | 1291 | pub fn default(self, db: &dyn HirDatabase) -> Option<Type> { |
1280 | let params = db.generic_defaults(self.id.parent); | 1292 | let params = db.generic_defaults(self.id.parent); |
1281 | let local_idx = hir_ty::param_idx(db, self.id)?; | 1293 | let local_idx = hir_ty::param_idx(db, self.id)?; |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 932279a06..f2ad95cb6 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -228,11 +228,6 @@ fn runnable_action( | |||
228 | } | 228 | } |
229 | 229 | ||
230 | fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { | 230 | 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 | }; | ||
236 | let mut targets: Vec<ModuleDef> = Vec::new(); | 231 | let mut targets: Vec<ModuleDef> = Vec::new(); |
237 | let mut push_new_def = |item: ModuleDef| { | 232 | let mut push_new_def = |item: ModuleDef| { |
238 | if !targets.contains(&item) { | 233 | if !targets.contains(&item) { |
@@ -240,17 +235,27 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { | |||
240 | } | 235 | } |
241 | }; | 236 | }; |
242 | 237 | ||
243 | ty.walk(db, |t| { | 238 | if let Definition::TypeParam(it) = def { |
244 | if let Some(adt) = t.as_adt() { | 239 | it.trait_bounds(db).into_iter().for_each(|it| push_new_def(it.into())); |
245 | push_new_def(adt.into()); | 240 | } else { |
246 | } else if let Some(trait_) = t.as_dyn_trait() { | 241 | let ty = match def { |
247 | push_new_def(trait_.into()); | 242 | Definition::Local(it) => it.ty(db), |
248 | } else if let Some(traits) = t.as_impl_traits(db) { | 243 | Definition::ConstParam(it) => it.ty(db), |
249 | traits.into_iter().for_each(|it| push_new_def(it.into())); | 244 | _ => return None, |
250 | } else if let Some(trait_) = t.as_associated_type_parent_trait(db) { | 245 | }; |
251 | push_new_def(trait_.into()); | 246 | |
252 | } | 247 | ty.walk(db, |t| { |
253 | }); | 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 | } | ||
254 | 259 | ||
255 | let targets = targets | 260 | let targets = targets |
256 | .into_iter() | 261 | .into_iter() |
@@ -3086,7 +3091,7 @@ fn main() { let s<|>t = test().get(); } | |||
3086 | struct Bar; | 3091 | struct Bar; |
3087 | struct Foo<const BAR: Bar>; | 3092 | struct Foo<const BAR: Bar>; |
3088 | 3093 | ||
3089 | impl<const BAR: Bar> Foo<BAR<|>> {} | 3094 | impl<const BAR: Bar> Foo<BAR<|>> {} |
3090 | "#, | 3095 | "#, |
3091 | expect![[r#" | 3096 | expect![[r#" |
3092 | [ | 3097 | [ |
@@ -3113,6 +3118,38 @@ impl<const BAR: Bar> Foo<BAR<|>> {} | |||
3113 | } | 3118 | } |
3114 | 3119 | ||
3115 | #[test] | 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 | |||
3152 | #[test] | ||
3116 | fn hover_displays_normalized_crate_names() { | 3153 | fn hover_displays_normalized_crate_names() { |
3117 | check( | 3154 | check( |
3118 | r#" | 3155 | r#" |