Fix type "items" order.

This commit is contained in:
vsrs 2020-06-10 22:56:49 +03:00
parent c50157f330
commit 283ec13fc0
2 changed files with 36 additions and 24 deletions

View file

@ -27,7 +27,7 @@ use hir_ty::{
display::{HirDisplayError, HirFormatter}, display::{HirDisplayError, HirFormatter},
expr::ExprValidator, expr::ExprValidator,
method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, OpaqueTyId, method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, OpaqueTyId,
Substs, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor,
}; };
use ra_db::{CrateId, CrateName, Edition, FileId}; use ra_db::{CrateId, CrateName, Edition, FileId};
use ra_prof::profile; use ra_prof::profile;
@ -1381,7 +1381,7 @@ impl Type {
} }
} }
/// Returns a flattened list of all the ADTs and Traits mentioned in the type /// Returns a flattened list of all ADTs and Traits mentioned in the type
pub fn flattened_type_items(&self, db: &dyn HirDatabase) -> Vec<AdtOrTrait> { pub fn flattened_type_items(&self, db: &dyn HirDatabase) -> Vec<AdtOrTrait> {
fn push_new_item(item: AdtOrTrait, acc: &mut Vec<AdtOrTrait>) { fn push_new_item(item: AdtOrTrait, acc: &mut Vec<AdtOrTrait>) {
if !acc.contains(&item) { if !acc.contains(&item) {
@ -1398,7 +1398,7 @@ impl Type {
match p { match p {
GenericPredicate::Implemented(trait_ref) => { GenericPredicate::Implemented(trait_ref) => {
push_new_item(Trait::from(trait_ref.trait_).into(), acc); push_new_item(Trait::from(trait_ref.trait_).into(), acc);
walk_types(db, &trait_ref.substs, acc); walk_substs(db, &trait_ref.substs, acc);
} }
GenericPredicate::Projection(_) => {} GenericPredicate::Projection(_) => {}
GenericPredicate::Error => (), GenericPredicate::Error => (),
@ -1406,8 +1406,11 @@ impl Type {
} }
} }
fn walk_types<T: TypeWalk>(db: &dyn HirDatabase, tw: &T, acc: &mut Vec<AdtOrTrait>) { // TypeWalk::walk does not preserve items order!
tw.walk(&mut |ty| walk_type(db, ty, acc)); fn walk_substs(db: &dyn HirDatabase, substs: &Substs, acc: &mut Vec<AdtOrTrait>) {
for ty in substs.iter() {
walk_type(db, ty, acc);
}
} }
fn walk_type(db: &dyn HirDatabase, ty: &Ty, acc: &mut Vec<AdtOrTrait>) { fn walk_type(db: &dyn HirDatabase, ty: &Ty, acc: &mut Vec<AdtOrTrait>) {
@ -1415,10 +1418,18 @@ impl Type {
Ty::Apply(ApplicationTy { ctor, parameters, .. }) => { Ty::Apply(ApplicationTy { ctor, parameters, .. }) => {
match ctor { match ctor {
TypeCtor::Adt(adt_id) => push_new_item(Adt::from(*adt_id).into(), acc), TypeCtor::Adt(adt_id) => push_new_item(Adt::from(*adt_id).into(), acc),
TypeCtor::AssociatedType(type_alias_id) => {
let trait_id = match type_alias_id.lookup(db.upcast()).container {
AssocContainerId::TraitId(it) => it,
_ => panic!("not an associated type"),
};
push_new_item(Trait::from(trait_id).into(), acc);
}
_ => (), _ => (),
} }
// adt params, tuples, etc... // adt params, tuples, etc...
walk_types(db, parameters, acc); walk_substs(db, parameters, acc);
} }
Ty::Dyn(predicates) => { Ty::Dyn(predicates) => {
push_bounds(db, predicates, acc); push_bounds(db, predicates, acc);
@ -1451,7 +1462,7 @@ impl Type {
} }
}; };
push_bounds(db, &bounds.value, acc); push_bounds(db, &bounds.value, acc);
walk_types(db, &opaque_ty.parameters, acc); walk_substs(db, &opaque_ty.parameters, acc);
} }
_ => (), _ => (),
} }

View file

@ -234,9 +234,10 @@ 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 { match def {
Definition::Local(it) => { Definition::Local(it) => {
let ty = it.ty(db); let targets = it
let v = ty.flattened_type_items(db); .ty(db)
let targets = v.into_iter() .flattened_type_items(db)
.into_iter()
.map(|it| HoverGotoTypeData { .map(|it| HoverGotoTypeData {
mod_path: adt_or_trait_mod_path(db, &it), mod_path: adt_or_trait_mod_path(db, &it),
nav: it.to_nav(db), nav: it.to_nav(db),
@ -1980,7 +1981,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
} }
#[test] #[test]
fn test_hover_arg_goto_type_action() { fn test_hover_goto_type_action_links_order() {
let (_, actions) = check_hover_result( let (_, actions) = check_hover_result(
" "
//- /lib.rs //- /lib.rs
@ -1988,10 +1989,10 @@ fn func(foo: i32) { if true { <|>foo; }; }
trait DynTrait<T> {} trait DynTrait<T> {}
struct B<T> {} struct B<T> {}
struct S {} struct S {}
fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<S>>>) {} fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
", ",
&["&impl ImplTrait<B<dyn DynTrait<S>>>"], &["&impl ImplTrait<B<dyn DynTrait<B<S>>>>"],
); );
assert_debug_snapshot!(actions, assert_debug_snapshot!(actions,
@r###" @r###"
@ -2018,20 +2019,20 @@ fn func(foo: i32) { if true { <|>foo; }; }
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "S", mod_path: "B",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 58..69, full_range: 43..57,
name: "S", name: "B",
kind: STRUCT_DEF, kind: STRUCT_DEF,
focus_range: Some( focus_range: Some(
65..66, 50..51,
), ),
container_name: None, container_name: None,
description: Some( description: Some(
"struct S", "struct B",
), ),
docs: None, docs: None,
}, },
@ -2056,20 +2057,20 @@ fn func(foo: i32) { if true { <|>foo; }; }
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "B", mod_path: "S",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 43..57, full_range: 58..69,
name: "B", name: "S",
kind: STRUCT_DEF, kind: STRUCT_DEF,
focus_range: Some( focus_range: Some(
50..51, 65..66,
), ),
container_name: None, container_name: None,
description: Some( description: Some(
"struct B", "struct S",
), ),
docs: None, docs: None,
}, },