Skip to content

Commit 6f8af89

Browse files
bors[bot]Veykril
andauthored
Merge #7154
7154: Show goto type actions for Const and TypeParams r=matklad a=Veykril Shows goto type actions for type parameters: ![Code_6hn3rowu9M](https://user-images.githubusercontent.com/3757771/103547890-42aaeb00-4ea5-11eb-8ac7-f166869af5f8.png) Shows goto type actions for const parameters: ![Code_8UFCcbZL3z](https://user-images.githubusercontent.com/3757771/103547891-43438180-4ea5-11eb-91e8-50681e4d831e.png) Also shows implementations for `Self`: ![Code_eQj1pWfser](https://user-images.githubusercontent.com/3757771/103547892-43438180-4ea5-11eb-9122-461f2e0fdd01.png) Co-authored-by: Lukas Wirth <[email protected]>
2 parents b4ab804 + 54b9b03 commit 6f8af89

File tree

2 files changed

+150
-45
lines changed

2 files changed

+150
-45
lines changed

crates/hir/src/code_model.rs

Lines changed: 18 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)?;
@@ -1343,6 +1355,12 @@ impl ConstParam {
13431355
pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
13441356
self.id.parent.into()
13451357
}
1358+
1359+
pub fn ty(self, db: &dyn HirDatabase) -> Type {
1360+
let def = self.id.parent;
1361+
let krate = def.module(db.upcast()).krate;
1362+
Type::new(db, krate, def, db.const_param_ty(self.id))
1363+
}
13461364
}
13471365

13481366
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

crates/ide/src/hover.rs

Lines changed: 132 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -182,16 +182,18 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov
182182
})
183183
}
184184

185-
match def {
186-
Definition::ModuleDef(it) => match it {
187-
ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.try_to_nav(db)?)),
188-
ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.try_to_nav(db)?)),
189-
ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.try_to_nav(db)?)),
190-
ModuleDef::Trait(it) => Some(to_action(it.try_to_nav(db)?)),
191-
_ => None,
192-
},
185+
let adt = match def {
186+
Definition::ModuleDef(ModuleDef::Trait(it)) => return it.try_to_nav(db).map(to_action),
187+
Definition::ModuleDef(ModuleDef::Adt(it)) => Some(it),
188+
Definition::SelfType(it) => it.target_ty(db).as_adt(),
193189
_ => None,
190+
}?;
191+
match adt {
192+
Adt::Struct(it) => it.try_to_nav(db),
193+
Adt::Union(it) => it.try_to_nav(db),
194+
Adt::Enum(it) => it.try_to_nav(db),
194195
}
196+
.map(to_action)
195197
}
196198

197199
fn runnable_action(
@@ -226,45 +228,46 @@ fn runnable_action(
226228
}
227229

228230
fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
229-
match def {
230-
Definition::Local(it) => {
231-
let mut targets: Vec<ModuleDef> = Vec::new();
232-
let mut push_new_def = |item: ModuleDef| {
233-
if !targets.contains(&item) {
234-
targets.push(item);
235-
}
236-
};
237-
238-
it.ty(db).walk(db, |t| {
239-
if let Some(adt) = t.as_adt() {
240-
push_new_def(adt.into());
241-
} else if let Some(trait_) = t.as_dyn_trait() {
242-
push_new_def(trait_.into());
243-
} else if let Some(traits) = t.as_impl_traits(db) {
244-
traits.into_iter().for_each(|it| push_new_def(it.into()));
245-
} else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
246-
push_new_def(trait_.into());
247-
}
248-
});
249-
250-
let targets = targets
251-
.into_iter()
252-
.filter_map(|it| {
253-
Some(HoverGotoTypeData {
254-
mod_path: render_path(
255-
db,
256-
it.module(db)?,
257-
it.name(db).map(|name| name.to_string()),
258-
),
259-
nav: it.try_to_nav(db)?,
260-
})
261-
})
262-
.collect();
263-
264-
Some(HoverAction::GoToType(targets))
231+
let mut targets: Vec<ModuleDef> = Vec::new();
232+
let mut push_new_def = |item: ModuleDef| {
233+
if !targets.contains(&item) {
234+
targets.push(item);
265235
}
266-
_ => None,
236+
};
237+
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+
});
267258
}
259+
260+
let targets = targets
261+
.into_iter()
262+
.filter_map(|it| {
263+
Some(HoverGotoTypeData {
264+
mod_path: render_path(db, it.module(db)?, it.name(db).map(|name| name.to_string())),
265+
nav: it.try_to_nav(db)?,
266+
})
267+
})
268+
.collect();
269+
270+
Some(HoverAction::GoToType(targets))
268271
}
269272

270273
fn hover_markup(
@@ -2174,6 +2177,25 @@ fn foo() { let bar = Bar; bar.fo<|>o(); }
21742177
);
21752178
}
21762179

2180+
#[test]
2181+
fn test_hover_self_has_impl_action() {
2182+
check_actions(
2183+
r#"struct foo where Self<|>:;"#,
2184+
expect![[r#"
2185+
[
2186+
Implementation(
2187+
FilePosition {
2188+
file_id: FileId(
2189+
0,
2190+
),
2191+
offset: 7,
2192+
},
2193+
),
2194+
]
2195+
"#]],
2196+
);
2197+
}
2198+
21772199
#[test]
21782200
fn test_hover_test_has_action() {
21792201
check_actions(
@@ -3062,6 +3084,71 @@ fn main() { let s<|>t = test().get(); }
30623084
);
30633085
}
30643086

3087+
#[test]
3088+
fn test_hover_const_param_has_goto_type_action() {
3089+
check_actions(
3090+
r#"
3091+
struct Bar;
3092+
struct Foo<const BAR: Bar>;
3093+
3094+
impl<const BAR: Bar> Foo<BAR<|>> {}
3095+
"#,
3096+
expect![[r#"
3097+
[
3098+
GoToType(
3099+
[
3100+
HoverGotoTypeData {
3101+
mod_path: "test::Bar",
3102+
nav: NavigationTarget {
3103+
file_id: FileId(
3104+
0,
3105+
),
3106+
full_range: 0..11,
3107+
focus_range: 7..10,
3108+
name: "Bar",
3109+
kind: Struct,
3110+
description: "struct Bar",
3111+
},
3112+
},
3113+
],
3114+
),
3115+
]
3116+
"#]],
3117+
);
3118+
}
3119+
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+
30653152
#[test]
30663153
fn hover_displays_normalized_crate_names() {
30673154
check(

0 commit comments

Comments
 (0)