diff options
Diffstat (limited to 'crates/ra_hir/src/semantics/source_to_def.rs')
-rw-r--r-- | crates/ra_hir/src/semantics/source_to_def.rs | 276 |
1 files changed, 0 insertions, 276 deletions
diff --git a/crates/ra_hir/src/semantics/source_to_def.rs b/crates/ra_hir/src/semantics/source_to_def.rs deleted file mode 100644 index d1994e2e7..000000000 --- a/crates/ra_hir/src/semantics/source_to_def.rs +++ /dev/null | |||
@@ -1,276 +0,0 @@ | |||
1 | //! Maps *syntax* of various definitions to their semantic ids. | ||
2 | |||
3 | use hir_def::{ | ||
4 | child_by_source::ChildBySource, | ||
5 | dyn_map::DynMap, | ||
6 | expr::PatId, | ||
7 | keys::{self, Key}, | ||
8 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId, | ||
9 | ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, | ||
10 | }; | ||
11 | use hir_expand::{name::AsName, AstId, MacroDefKind}; | ||
12 | use ra_db::FileId; | ||
13 | use ra_prof::profile; | ||
14 | use ra_syntax::{ | ||
15 | ast::{self, NameOwner}, | ||
16 | match_ast, AstNode, SyntaxNode, | ||
17 | }; | ||
18 | use rustc_hash::FxHashMap; | ||
19 | use stdx::impl_from; | ||
20 | |||
21 | use crate::{db::HirDatabase, InFile, MacroDefId}; | ||
22 | |||
23 | pub(super) type SourceToDefCache = FxHashMap<ChildContainer, DynMap>; | ||
24 | |||
25 | pub(super) struct SourceToDefCtx<'a, 'b> { | ||
26 | pub(super) db: &'b dyn HirDatabase, | ||
27 | pub(super) cache: &'a mut SourceToDefCache, | ||
28 | } | ||
29 | |||
30 | impl SourceToDefCtx<'_, '_> { | ||
31 | pub(super) fn file_to_def(&mut self, file: FileId) -> Option<ModuleId> { | ||
32 | let _p = profile("SourceBinder::to_module_def"); | ||
33 | let (krate, local_id) = self.db.relevant_crates(file).iter().find_map(|&crate_id| { | ||
34 | let crate_def_map = self.db.crate_def_map(crate_id); | ||
35 | let local_id = crate_def_map.modules_for_file(file).next()?; | ||
36 | Some((crate_id, local_id)) | ||
37 | })?; | ||
38 | Some(ModuleId { krate, local_id }) | ||
39 | } | ||
40 | |||
41 | pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> { | ||
42 | let _p = profile("module_to_def"); | ||
43 | let parent_declaration = src | ||
44 | .as_ref() | ||
45 | .map(|it| it.syntax()) | ||
46 | .cloned() | ||
47 | .ancestors_with_macros(self.db.upcast()) | ||
48 | .skip(1) | ||
49 | .find_map(|it| { | ||
50 | let m = ast::Module::cast(it.value.clone())?; | ||
51 | Some(it.with_value(m)) | ||
52 | }); | ||
53 | |||
54 | let parent_module = match parent_declaration { | ||
55 | Some(parent_declaration) => self.module_to_def(parent_declaration), | ||
56 | None => { | ||
57 | let file_id = src.file_id.original_file(self.db.upcast()); | ||
58 | self.file_to_def(file_id) | ||
59 | } | ||
60 | }?; | ||
61 | |||
62 | let child_name = src.value.name()?.as_name(); | ||
63 | let def_map = self.db.crate_def_map(parent_module.krate); | ||
64 | let child_id = *def_map[parent_module.local_id].children.get(&child_name)?; | ||
65 | Some(ModuleId { krate: parent_module.krate, local_id: child_id }) | ||
66 | } | ||
67 | |||
68 | pub(super) fn trait_to_def(&mut self, src: InFile<ast::Trait>) -> Option<TraitId> { | ||
69 | self.to_def(src, keys::TRAIT) | ||
70 | } | ||
71 | pub(super) fn impl_to_def(&mut self, src: InFile<ast::Impl>) -> Option<ImplId> { | ||
72 | self.to_def(src, keys::IMPL) | ||
73 | } | ||
74 | pub(super) fn fn_to_def(&mut self, src: InFile<ast::Fn>) -> Option<FunctionId> { | ||
75 | self.to_def(src, keys::FUNCTION) | ||
76 | } | ||
77 | pub(super) fn struct_to_def(&mut self, src: InFile<ast::Struct>) -> Option<StructId> { | ||
78 | self.to_def(src, keys::STRUCT) | ||
79 | } | ||
80 | pub(super) fn enum_to_def(&mut self, src: InFile<ast::Enum>) -> Option<EnumId> { | ||
81 | self.to_def(src, keys::ENUM) | ||
82 | } | ||
83 | pub(super) fn union_to_def(&mut self, src: InFile<ast::Union>) -> Option<UnionId> { | ||
84 | self.to_def(src, keys::UNION) | ||
85 | } | ||
86 | pub(super) fn static_to_def(&mut self, src: InFile<ast::Static>) -> Option<StaticId> { | ||
87 | self.to_def(src, keys::STATIC) | ||
88 | } | ||
89 | pub(super) fn const_to_def(&mut self, src: InFile<ast::Const>) -> Option<ConstId> { | ||
90 | self.to_def(src, keys::CONST) | ||
91 | } | ||
92 | pub(super) fn type_alias_to_def(&mut self, src: InFile<ast::TypeAlias>) -> Option<TypeAliasId> { | ||
93 | self.to_def(src, keys::TYPE_ALIAS) | ||
94 | } | ||
95 | pub(super) fn record_field_to_def(&mut self, src: InFile<ast::RecordField>) -> Option<FieldId> { | ||
96 | self.to_def(src, keys::RECORD_FIELD) | ||
97 | } | ||
98 | pub(super) fn tuple_field_to_def(&mut self, src: InFile<ast::TupleField>) -> Option<FieldId> { | ||
99 | self.to_def(src, keys::TUPLE_FIELD) | ||
100 | } | ||
101 | pub(super) fn enum_variant_to_def( | ||
102 | &mut self, | ||
103 | src: InFile<ast::Variant>, | ||
104 | ) -> Option<EnumVariantId> { | ||
105 | self.to_def(src, keys::VARIANT) | ||
106 | } | ||
107 | pub(super) fn bind_pat_to_def( | ||
108 | &mut self, | ||
109 | src: InFile<ast::BindPat>, | ||
110 | ) -> Option<(DefWithBodyId, PatId)> { | ||
111 | let container = self.find_pat_container(src.as_ref().map(|it| it.syntax()))?; | ||
112 | let (_body, source_map) = self.db.body_with_source_map(container); | ||
113 | let src = src.map(ast::Pat::from); | ||
114 | let pat_id = source_map.node_pat(src.as_ref())?; | ||
115 | Some((container, pat_id)) | ||
116 | } | ||
117 | |||
118 | fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>( | ||
119 | &mut self, | ||
120 | src: InFile<Ast>, | ||
121 | key: Key<Ast, ID>, | ||
122 | ) -> Option<ID> { | ||
123 | let container = self.find_container(src.as_ref().map(|it| it.syntax()))?; | ||
124 | let db = self.db; | ||
125 | let dyn_map = | ||
126 | &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); | ||
127 | dyn_map[key].get(&src).copied() | ||
128 | } | ||
129 | |||
130 | pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> { | ||
131 | let container: ChildContainer = | ||
132 | self.find_type_param_container(src.as_ref().map(|it| it.syntax()))?.into(); | ||
133 | let db = self.db; | ||
134 | let dyn_map = | ||
135 | &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); | ||
136 | dyn_map[keys::TYPE_PARAM].get(&src).copied() | ||
137 | } | ||
138 | |||
139 | // FIXME: use DynMap as well? | ||
140 | pub(super) fn macro_call_to_def(&mut self, src: InFile<ast::MacroCall>) -> Option<MacroDefId> { | ||
141 | let kind = MacroDefKind::Declarative; | ||
142 | let file_id = src.file_id.original_file(self.db.upcast()); | ||
143 | let krate = self.file_to_def(file_id)?.krate; | ||
144 | let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); | ||
145 | let ast_id = Some(AstId::new(src.file_id, file_ast_id)); | ||
146 | Some(MacroDefId { krate: Some(krate), ast_id, kind, local_inner: false }) | ||
147 | } | ||
148 | |||
149 | pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { | ||
150 | for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { | ||
151 | let res: ChildContainer = match_ast! { | ||
152 | match (container.value) { | ||
153 | ast::Module(it) => { | ||
154 | let def = self.module_to_def(container.with_value(it))?; | ||
155 | def.into() | ||
156 | }, | ||
157 | ast::Trait(it) => { | ||
158 | let def = self.trait_to_def(container.with_value(it))?; | ||
159 | def.into() | ||
160 | }, | ||
161 | ast::Impl(it) => { | ||
162 | let def = self.impl_to_def(container.with_value(it))?; | ||
163 | def.into() | ||
164 | }, | ||
165 | ast::Fn(it) => { | ||
166 | let def = self.fn_to_def(container.with_value(it))?; | ||
167 | DefWithBodyId::from(def).into() | ||
168 | }, | ||
169 | ast::Struct(it) => { | ||
170 | let def = self.struct_to_def(container.with_value(it))?; | ||
171 | VariantId::from(def).into() | ||
172 | }, | ||
173 | ast::Enum(it) => { | ||
174 | let def = self.enum_to_def(container.with_value(it))?; | ||
175 | def.into() | ||
176 | }, | ||
177 | ast::Union(it) => { | ||
178 | let def = self.union_to_def(container.with_value(it))?; | ||
179 | VariantId::from(def).into() | ||
180 | }, | ||
181 | ast::Static(it) => { | ||
182 | let def = self.static_to_def(container.with_value(it))?; | ||
183 | DefWithBodyId::from(def).into() | ||
184 | }, | ||
185 | ast::Const(it) => { | ||
186 | let def = self.const_to_def(container.with_value(it))?; | ||
187 | DefWithBodyId::from(def).into() | ||
188 | }, | ||
189 | ast::TypeAlias(it) => { | ||
190 | let def = self.type_alias_to_def(container.with_value(it))?; | ||
191 | def.into() | ||
192 | }, | ||
193 | _ => continue, | ||
194 | } | ||
195 | }; | ||
196 | return Some(res); | ||
197 | } | ||
198 | |||
199 | let def = self.file_to_def(src.file_id.original_file(self.db.upcast()))?; | ||
200 | Some(def.into()) | ||
201 | } | ||
202 | |||
203 | fn find_type_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> { | ||
204 | for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { | ||
205 | let res: GenericDefId = match_ast! { | ||
206 | match (container.value) { | ||
207 | ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(), | ||
208 | ast::Struct(it) => self.struct_to_def(container.with_value(it))?.into(), | ||
209 | ast::Enum(it) => self.enum_to_def(container.with_value(it))?.into(), | ||
210 | ast::Trait(it) => self.trait_to_def(container.with_value(it))?.into(), | ||
211 | ast::TypeAlias(it) => self.type_alias_to_def(container.with_value(it))?.into(), | ||
212 | ast::Impl(it) => self.impl_to_def(container.with_value(it))?.into(), | ||
213 | _ => continue, | ||
214 | } | ||
215 | }; | ||
216 | return Some(res); | ||
217 | } | ||
218 | None | ||
219 | } | ||
220 | |||
221 | fn find_pat_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> { | ||
222 | for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { | ||
223 | let res: DefWithBodyId = match_ast! { | ||
224 | match (container.value) { | ||
225 | ast::Const(it) => self.const_to_def(container.with_value(it))?.into(), | ||
226 | ast::Static(it) => self.static_to_def(container.with_value(it))?.into(), | ||
227 | ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(), | ||
228 | _ => continue, | ||
229 | } | ||
230 | }; | ||
231 | return Some(res); | ||
232 | } | ||
233 | None | ||
234 | } | ||
235 | } | ||
236 | |||
237 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | ||
238 | pub(crate) enum ChildContainer { | ||
239 | DefWithBodyId(DefWithBodyId), | ||
240 | ModuleId(ModuleId), | ||
241 | TraitId(TraitId), | ||
242 | ImplId(ImplId), | ||
243 | EnumId(EnumId), | ||
244 | VariantId(VariantId), | ||
245 | TypeAliasId(TypeAliasId), | ||
246 | /// XXX: this might be the same def as, for example an `EnumId`. However, | ||
247 | /// here the children generic parameters, and not, eg enum variants. | ||
248 | GenericDefId(GenericDefId), | ||
249 | } | ||
250 | impl_from! { | ||
251 | DefWithBodyId, | ||
252 | ModuleId, | ||
253 | TraitId, | ||
254 | ImplId, | ||
255 | EnumId, | ||
256 | VariantId, | ||
257 | TypeAliasId, | ||
258 | GenericDefId | ||
259 | for ChildContainer | ||
260 | } | ||
261 | |||
262 | impl ChildContainer { | ||
263 | fn child_by_source(self, db: &dyn HirDatabase) -> DynMap { | ||
264 | let db = db.upcast(); | ||
265 | match self { | ||
266 | ChildContainer::DefWithBodyId(it) => it.child_by_source(db), | ||
267 | ChildContainer::ModuleId(it) => it.child_by_source(db), | ||
268 | ChildContainer::TraitId(it) => it.child_by_source(db), | ||
269 | ChildContainer::ImplId(it) => it.child_by_source(db), | ||
270 | ChildContainer::EnumId(it) => it.child_by_source(db), | ||
271 | ChildContainer::VariantId(it) => it.child_by_source(db), | ||
272 | ChildContainer::TypeAliasId(_) => DynMap::default(), | ||
273 | ChildContainer::GenericDefId(it) => it.child_by_source(db), | ||
274 | } | ||
275 | } | ||
276 | } | ||