aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/utils.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/utils.rs')
-rw-r--r--crates/ra_hir_ty/src/utils.rs82
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;
5use hir_def::{ 5use 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};
12use hir_expand::name::{self, Name}; 13use 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
87pub(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
92pub(crate) struct Generics {
93 def: GenericDefId,
94 pub(crate) params: Arc<GenericParams>,
95 parent_generics: Option<Box<Generics>>,
96}
97
98impl 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
150fn 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}