aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-01-04 14:44:19 +0000
committerLukas Wirth <[email protected]>2021-01-04 14:54:45 +0000
commit54b9b03ca2e90083fd1d1fe199c5dde595423b53 (patch)
treea6f3fee61b7f920ea9a2464fbf2e3ae3c3c893c3
parentbd47e140b6f6f39743d52f72437e6eaa2bfd9de1 (diff)
Show GotoTypeAction for TypeParam
-rw-r--r--crates/hir/src/code_model.rs12
-rw-r--r--crates/ide/src/hover.rs71
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
230fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { 230fn 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(); }
3086struct Bar; 3091struct Bar;
3087struct Foo<const BAR: Bar>; 3092struct Foo<const BAR: Bar>;
3088 3093
3089impl<const BAR: Bar> Foo<BAR<|>> {} 3094impl<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#"
3124trait Foo {}
3125
3126fn 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#"