about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/code_model.rs6
-rw-r--r--crates/ide/src/hover.rs103
2 files changed, 72 insertions, 37 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index a2255508e36..a7a38d43a3b 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -1343,6 +1343,12 @@ impl ConstParam {
     pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
         self.id.parent.into()
     }
+
+    pub fn ty(self, db: &dyn HirDatabase) -> Type {
+        let def = self.id.parent;
+        let krate = def.module(db.upcast()).krate;
+        Type::new(db, krate, def, db.const_param_ty(self.id))
+    }
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 399e3e484a1..932279a0639 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -228,45 +228,41 @@ fn runnable_action(
 }
 
 fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
-    match def {
-        Definition::Local(it) => {
-            let mut targets: Vec<ModuleDef> = Vec::new();
-            let mut push_new_def = |item: ModuleDef| {
-                if !targets.contains(&item) {
-                    targets.push(item);
-                }
-            };
+    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 push_new_def = |item: ModuleDef| {
+        if !targets.contains(&item) {
+            targets.push(item);
+        }
+    };
 
-            it.ty(db).walk(db, |t| {
-                if let Some(adt) = t.as_adt() {
-                    push_new_def(adt.into());
-                } else if let Some(trait_) = t.as_dyn_trait() {
-                    push_new_def(trait_.into());
-                } else if let Some(traits) = t.as_impl_traits(db) {
-                    traits.into_iter().for_each(|it| push_new_def(it.into()));
-                } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
-                    push_new_def(trait_.into());
-                }
-            });
-
-            let targets = targets
-                .into_iter()
-                .filter_map(|it| {
-                    Some(HoverGotoTypeData {
-                        mod_path: render_path(
-                            db,
-                            it.module(db)?,
-                            it.name(db).map(|name| name.to_string()),
-                        ),
-                        nav: it.try_to_nav(db)?,
-                    })
-                })
-                .collect();
-
-            Some(HoverAction::GoToType(targets))
+    ty.walk(db, |t| {
+        if let Some(adt) = t.as_adt() {
+            push_new_def(adt.into());
+        } else if let Some(trait_) = t.as_dyn_trait() {
+            push_new_def(trait_.into());
+        } else if let Some(traits) = t.as_impl_traits(db) {
+            traits.into_iter().for_each(|it| push_new_def(it.into()));
+        } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
+            push_new_def(trait_.into());
         }
-        _ => None,
-    }
+    });
+
+    let targets = targets
+        .into_iter()
+        .filter_map(|it| {
+            Some(HoverGotoTypeData {
+                mod_path: render_path(db, it.module(db)?, it.name(db).map(|name| name.to_string())),
+                nav: it.try_to_nav(db)?,
+            })
+        })
+        .collect();
+
+    Some(HoverAction::GoToType(targets))
 }
 
 fn hover_markup(
@@ -3084,6 +3080,39 @@ fn main() { let s<|>t = test().get(); }
     }
 
     #[test]
+    fn test_hover_const_param_has_goto_type_action() {
+        check_actions(
+            r#"
+struct Bar;
+struct Foo<const BAR: Bar>;
+
+impl<const BAR: Bar> Foo<BAR<|>> {} 
+"#,
+            expect![[r#"
+                [
+                    GoToType(
+                        [
+                            HoverGotoTypeData {
+                                mod_path: "test::Bar",
+                                nav: NavigationTarget {
+                                    file_id: FileId(
+                                        0,
+                                    ),
+                                    full_range: 0..11,
+                                    focus_range: 7..10,
+                                    name: "Bar",
+                                    kind: Struct,
+                                    description: "struct Bar",
+                                },
+                            },
+                        ],
+                    ),
+                ]
+            "#]],
+        );
+    }
+
+    #[test]
     fn hover_displays_normalized_crate_names() {
         check(
             r#"