aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r--crates/ra_hir/src/code_model.rs54
1 files changed, 52 insertions, 2 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index f7efc1b66..4739246cb 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1,8 +1,11 @@
1pub(crate) mod src; 1pub(crate) mod src;
2pub(crate) mod docs; 2pub(crate) mod docs;
3 3
4use std::iter;
4use std::sync::Arc; 5use std::sync::Arc;
5 6
7use itertools::Itertools;
8
6use ra_db::{CrateId, Edition, FileId, SourceRootId}; 9use ra_db::{CrateId, Edition, FileId, SourceRootId};
7use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 10use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
8 11
@@ -820,7 +823,43 @@ impl Trait {
820 self.trait_data(db).items().to_vec() 823 self.trait_data(db).items().to_vec()
821 } 824 }
822 825
823 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: Name) -> Option<TypeAlias> { 826 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
827 let resolver = self.resolver(db);
828 // returning the iterator directly doesn't easily work because of
829 // lifetime problems, but since there usually shouldn't be more than a
830 // few direct traits this should be fine (we could even use some kind of
831 // SmallVec if performance is a concern)
832 self.generic_params(db)
833 .where_predicates
834 .iter()
835 .filter_map(|pred| match &pred.type_ref {
836 TypeRef::Path(p) if p.as_ident() == Some(&crate::name::SELF_TYPE) => {
837 pred.bound.as_path()
838 }
839 _ => None,
840 })
841 .filter_map(|path| {
842 match resolver.resolve_path_without_assoc_items(db, path).take_types() {
843 Some(crate::Resolution::Def(ModuleDef::Trait(t))) => Some(t),
844 _ => None,
845 }
846 })
847 .collect()
848 }
849
850 /// Returns an iterator over the whole super trait hierarchy (not including
851 /// the trait itself). (This iterator may be infinite in case of circular
852 /// super trait dependencies, which are possible in malformed code.)
853 pub fn all_super_traits<'a>(
854 self,
855 db: &'a impl HirDatabase,
856 ) -> impl Iterator<Item = Trait> + 'a {
857 self.direct_super_traits(db).into_iter().flat_map(move |t| {
858 iter::once(t).chain(Box::new(t.all_super_traits(db)) as Box<dyn Iterator<Item = Trait>>)
859 })
860 }
861
862 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
824 let trait_data = self.trait_data(db); 863 let trait_data = self.trait_data(db);
825 trait_data 864 trait_data
826 .items() 865 .items()
@@ -829,7 +868,18 @@ impl Trait {
829 TraitItem::TypeAlias(t) => Some(*t), 868 TraitItem::TypeAlias(t) => Some(*t),
830 _ => None, 869 _ => None,
831 }) 870 })
832 .find(|t| t.name(db) == name) 871 .find(|t| &t.name(db) == name)
872 }
873
874 pub fn associated_type_by_name_including_super_traits(
875 self,
876 db: &impl HirDatabase,
877 name: &Name,
878 ) -> Option<TypeAlias> {
879 iter::once(self)
880 .chain(self.all_super_traits(db))
881 .unique()
882 .find_map(|t| t.associated_type_by_name(db, name))
833 } 883 }
834 884
835 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { 885 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {