diff options
Diffstat (limited to 'crates/ra_hir_ty/src/utils.rs')
-rw-r--r-- | crates/ra_hir_ty/src/utils.rs | 82 |
1 files changed, 81 insertions, 1 deletions
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index e4ba890ef..2c458867f 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs | |||
@@ -5,9 +5,10 @@ use std::sync::Arc; | |||
5 | use hir_def::{ | 5 | use hir_def::{ |
6 | adt::VariantData, | 6 | adt::VariantData, |
7 | db::DefDatabase, | 7 | db::DefDatabase, |
8 | generics::{GenericParamData, GenericParams}, | ||
8 | resolver::{HasResolver, TypeNs}, | 9 | resolver::{HasResolver, TypeNs}, |
9 | type_ref::TypeRef, | 10 | type_ref::TypeRef, |
10 | TraitId, TypeAliasId, VariantId, | 11 | ContainerId, GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId, VariantId, |
11 | }; | 12 | }; |
12 | use hir_expand::name::{self, Name}; | 13 | use hir_expand::name::{self, Name}; |
13 | 14 | ||
@@ -82,3 +83,82 @@ pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] { | |||
82 | } | 83 | } |
83 | Arc::get_mut(a).unwrap() | 84 | Arc::get_mut(a).unwrap() |
84 | } | 85 | } |
86 | |||
87 | pub(crate) fn generics(db: &impl DefDatabase, def: GenericDefId) -> Generics { | ||
88 | let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def))); | ||
89 | Generics { def, params: db.generic_params(def), parent_generics } | ||
90 | } | ||
91 | |||
92 | pub(crate) struct Generics { | ||
93 | def: GenericDefId, | ||
94 | pub(crate) params: Arc<GenericParams>, | ||
95 | parent_generics: Option<Box<Generics>>, | ||
96 | } | ||
97 | |||
98 | impl Generics { | ||
99 | pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (u32, &'a GenericParamData)> + 'a { | ||
100 | self.parent_generics | ||
101 | .as_ref() | ||
102 | .into_iter() | ||
103 | .flat_map(|it| it.params.params.iter()) | ||
104 | .chain(self.params.params.iter()) | ||
105 | .enumerate() | ||
106 | .map(|(i, (_local_id, p))| (i as u32, p)) | ||
107 | } | ||
108 | |||
109 | pub(crate) fn iter_parent<'a>( | ||
110 | &'a self, | ||
111 | ) -> impl Iterator<Item = (u32, &'a GenericParamData)> + 'a { | ||
112 | self.parent_generics | ||
113 | .as_ref() | ||
114 | .into_iter() | ||
115 | .flat_map(|it| it.params.params.iter()) | ||
116 | .enumerate() | ||
117 | .map(|(i, (_local_id, p))| (i as u32, p)) | ||
118 | } | ||
119 | |||
120 | pub(crate) fn count_parent_params(&self) -> usize { | ||
121 | self.parent_generics.as_ref().map_or(0, |p| p.count_params_including_parent()) | ||
122 | } | ||
123 | |||
124 | pub(crate) fn count_params_including_parent(&self) -> usize { | ||
125 | let parent_count = self.count_parent_params(); | ||
126 | parent_count + self.params.params.len() | ||
127 | } | ||
128 | pub(crate) fn param_idx(&self, param: GenericParamId) -> u32 { | ||
129 | self.find_param(param).0 | ||
130 | } | ||
131 | pub(crate) fn param_name(&self, param: GenericParamId) -> Name { | ||
132 | self.find_param(param).1.name.clone() | ||
133 | } | ||
134 | fn find_param(&self, param: GenericParamId) -> (u32, &GenericParamData) { | ||
135 | if param.parent == self.def { | ||
136 | let (idx, (_local_id, data)) = self | ||
137 | .params | ||
138 | .params | ||
139 | .iter() | ||
140 | .enumerate() | ||
141 | .find(|(_, (idx, _))| *idx == param.local_id) | ||
142 | .unwrap(); | ||
143 | |||
144 | return ((self.count_parent_params() + idx) as u32, data); | ||
145 | } | ||
146 | self.parent_generics.as_ref().unwrap().find_param(param) | ||
147 | } | ||
148 | } | ||
149 | |||
150 | fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> { | ||
151 | let container = match def { | ||
152 | GenericDefId::FunctionId(it) => it.lookup(db).container, | ||
153 | GenericDefId::TypeAliasId(it) => it.lookup(db).container, | ||
154 | GenericDefId::ConstId(it) => it.lookup(db).container, | ||
155 | GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), | ||
156 | GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None, | ||
157 | }; | ||
158 | |||
159 | match container { | ||
160 | ContainerId::ImplId(it) => Some(it.into()), | ||
161 | ContainerId::TraitId(it) => Some(it.into()), | ||
162 | ContainerId::ModuleId(_) => None, | ||
163 | } | ||
164 | } | ||