Skip to content

Commit c50157f

Browse files
committed
Add Go to Type Definition hover action.
1 parent 4d6c6a6 commit c50157f

File tree

8 files changed

+956
-35
lines changed

8 files changed

+956
-35
lines changed

crates/ra_hir/src/code_model.rs

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ use hir_ty::{
2626
autoderef,
2727
display::{HirDisplayError, HirFormatter},
2828
expr::ExprValidator,
29-
method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty,
30-
TyDefId, TypeCtor,
29+
method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, OpaqueTyId,
30+
Substs, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk,
3131
};
3232
use ra_db::{CrateId, CrateName, Edition, FileId};
3333
use ra_prof::profile;
@@ -1380,6 +1380,87 @@ impl Type {
13801380
ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
13811381
}
13821382
}
1383+
1384+
/// Returns a flattened list of all the ADTs and Traits mentioned in the type
1385+
pub fn flattened_type_items(&self, db: &dyn HirDatabase) -> Vec<AdtOrTrait> {
1386+
fn push_new_item(item: AdtOrTrait, acc: &mut Vec<AdtOrTrait>) {
1387+
if !acc.contains(&item) {
1388+
acc.push(item);
1389+
}
1390+
}
1391+
1392+
fn push_bounds(
1393+
db: &dyn HirDatabase,
1394+
predicates: &[GenericPredicate],
1395+
acc: &mut Vec<AdtOrTrait>,
1396+
) {
1397+
for p in predicates.iter() {
1398+
match p {
1399+
GenericPredicate::Implemented(trait_ref) => {
1400+
push_new_item(Trait::from(trait_ref.trait_).into(), acc);
1401+
walk_types(db, &trait_ref.substs, acc);
1402+
}
1403+
GenericPredicate::Projection(_) => {}
1404+
GenericPredicate::Error => (),
1405+
}
1406+
}
1407+
}
1408+
1409+
fn walk_types<T: TypeWalk>(db: &dyn HirDatabase, tw: &T, acc: &mut Vec<AdtOrTrait>) {
1410+
tw.walk(&mut |ty| walk_type(db, ty, acc));
1411+
}
1412+
1413+
fn walk_type(db: &dyn HirDatabase, ty: &Ty, acc: &mut Vec<AdtOrTrait>) {
1414+
match ty.strip_references() {
1415+
Ty::Apply(ApplicationTy { ctor, parameters, .. }) => {
1416+
match ctor {
1417+
TypeCtor::Adt(adt_id) => push_new_item(Adt::from(*adt_id).into(), acc),
1418+
_ => (),
1419+
}
1420+
// adt params, tuples, etc...
1421+
walk_types(db, parameters, acc);
1422+
}
1423+
Ty::Dyn(predicates) => {
1424+
push_bounds(db, predicates, acc);
1425+
}
1426+
Ty::Placeholder(id) => {
1427+
let generic_params = db.generic_params(id.parent);
1428+
let param_data = &generic_params.types[id.local_id];
1429+
match param_data.provenance {
1430+
hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
1431+
let predicates: Vec<_> = db
1432+
.generic_predicates_for_param(*id)
1433+
.into_iter()
1434+
.map(|pred| pred.value.clone())
1435+
.collect();
1436+
push_bounds(db, &predicates, acc);
1437+
}
1438+
_ => (),
1439+
}
1440+
}
1441+
Ty::Opaque(opaque_ty) => {
1442+
let bounds = match opaque_ty.opaque_ty_id {
1443+
OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
1444+
let datas = db
1445+
.return_type_impl_traits(func)
1446+
.expect("impl trait id without data");
1447+
let data = (*datas)
1448+
.as_ref()
1449+
.map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
1450+
data.clone().subst(&opaque_ty.parameters)
1451+
}
1452+
};
1453+
push_bounds(db, &bounds.value, acc);
1454+
walk_types(db, &opaque_ty.parameters, acc);
1455+
}
1456+
_ => (),
1457+
}
1458+
}
1459+
1460+
let mut res: Vec<AdtOrTrait> = Vec::new(); // not a Set to preserve the order
1461+
walk_type(db, &self.ty.value, &mut res);
1462+
res
1463+
}
13831464
}
13841465

13851466
impl HirDisplay for Type {
@@ -1488,3 +1569,26 @@ pub trait HasVisibility {
14881569
vis.is_visible_from(db.upcast(), module.id)
14891570
}
14901571
}
1572+
1573+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1574+
pub enum AdtOrTrait {
1575+
Adt(Adt),
1576+
Trait(Trait),
1577+
}
1578+
impl_froms!(AdtOrTrait: Adt, Trait);
1579+
1580+
impl AdtOrTrait {
1581+
pub fn module(self, db: &dyn HirDatabase) -> Module {
1582+
match self {
1583+
AdtOrTrait::Adt(adt) => adt.module(db),
1584+
AdtOrTrait::Trait(trait_) => trait_.module(db),
1585+
}
1586+
}
1587+
1588+
pub fn name(self, db: &dyn HirDatabase) -> Name {
1589+
match self {
1590+
AdtOrTrait::Adt(adt) => adt.name(db),
1591+
AdtOrTrait::Trait(trait_) => trait_.name(db),
1592+
}
1593+
}
1594+
}

crates/ra_hir/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ mod has_source;
5151

5252
pub use crate::{
5353
code_model::{
54-
Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Const, Crate, CrateDependency,
55-
DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function, GenericDef, HasAttrs,
56-
HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct,
57-
Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
54+
Adt, AdtOrTrait, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Const, Crate,
55+
CrateDependency, DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function,
56+
GenericDef, HasAttrs, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef,
57+
Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
5858
},
5959
has_source::HasSource,
6060
semantics::{original_range, PathResolution, Semantics, SemanticsScope},

crates/ra_hir_ty/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,10 +1052,10 @@ pub enum OpaqueTyId {
10521052

10531053
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
10541054
pub struct ReturnTypeImplTraits {
1055-
pub(crate) impl_traits: Vec<ReturnTypeImplTrait>,
1055+
pub impl_traits: Vec<ReturnTypeImplTrait>,
10561056
}
10571057

10581058
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1059-
pub(crate) struct ReturnTypeImplTrait {
1060-
pub(crate) bounds: Binders<Vec<GenericPredicate>>,
1059+
pub struct ReturnTypeImplTrait {
1060+
pub bounds: Binders<Vec<GenericPredicate>>,
10611061
}

crates/ra_ide/src/display/navigation_target.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,15 @@ impl ToNav for hir::Adt {
321321
}
322322
}
323323

324+
impl ToNav for hir::AdtOrTrait {
325+
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
326+
match self {
327+
hir::AdtOrTrait::Adt(adt) => adt.to_nav(db),
328+
hir::AdtOrTrait::Trait(trait_) => trait_.to_nav(db),
329+
}
330+
}
331+
}
332+
324333
impl ToNav for hir::AssocItem {
325334
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
326335
match self {

0 commit comments

Comments
 (0)