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 <lukastw97@gmail.com>
This commit is contained in:
commit
6f8af890ed
@ -1276,6 +1276,18 @@ pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)?;
|
||||||
@ -1343,6 +1355,12 @@ pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|||||||
pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
|
pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
|
||||||
self.id.parent.into()
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
@ -182,16 +182,18 @@ fn to_action(nav_target: NavigationTarget) -> HoverAction {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
match def {
|
let adt = match def {
|
||||||
Definition::ModuleDef(it) => match it {
|
Definition::ModuleDef(ModuleDef::Trait(it)) => return it.try_to_nav(db).map(to_action),
|
||||||
ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.try_to_nav(db)?)),
|
Definition::ModuleDef(ModuleDef::Adt(it)) => Some(it),
|
||||||
ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.try_to_nav(db)?)),
|
Definition::SelfType(it) => it.target_ty(db).as_adt(),
|
||||||
ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.try_to_nav(db)?)),
|
|
||||||
ModuleDef::Trait(it) => Some(to_action(it.try_to_nav(db)?)),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
_ => None,
|
_ => None,
|
||||||
|
}?;
|
||||||
|
match adt {
|
||||||
|
Adt::Struct(it) => it.try_to_nav(db),
|
||||||
|
Adt::Union(it) => it.try_to_nav(db),
|
||||||
|
Adt::Enum(it) => it.try_to_nav(db),
|
||||||
}
|
}
|
||||||
|
.map(to_action)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runnable_action(
|
fn runnable_action(
|
||||||
@ -226,45 +228,46 @@ fn runnable_action(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
|
fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
|
||||||
match def {
|
let mut targets: Vec<ModuleDef> = Vec::new();
|
||||||
Definition::Local(it) => {
|
let mut push_new_def = |item: ModuleDef| {
|
||||||
let mut targets: Vec<ModuleDef> = Vec::new();
|
if !targets.contains(&item) {
|
||||||
let mut push_new_def = |item: ModuleDef| {
|
targets.push(item);
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
_ => None,
|
};
|
||||||
|
|
||||||
|
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| {
|
||||||
|
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))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hover_markup(
|
fn hover_markup(
|
||||||
@ -2174,6 +2177,25 @@ fn test_hover_enum_has_impl_action() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_hover_self_has_impl_action() {
|
||||||
|
check_actions(
|
||||||
|
r#"struct foo where Self<|>:;"#,
|
||||||
|
expect![[r#"
|
||||||
|
[
|
||||||
|
Implementation(
|
||||||
|
FilePosition {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
offset: 7,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hover_test_has_action() {
|
fn test_hover_test_has_action() {
|
||||||
check_actions(
|
check_actions(
|
||||||
@ -3062,6 +3084,71 @@ fn test() -> impl Foo { S {} }
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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 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(
|
||||||
|
Loading…
Reference in New Issue
Block a user