diff options
author | Seivan Heidari <[email protected]> | 2019-12-23 14:35:31 +0000 |
---|---|---|
committer | Seivan Heidari <[email protected]> | 2019-12-23 14:35:31 +0000 |
commit | b21d9337d9200e2cfdc90b386591c72c302dc03e (patch) | |
tree | f81f5c08f821115cee26fa4d3ceaae88c7807fd5 /crates/ra_hir_def/src/data.rs | |
parent | 18a0937585b836ec5ed054b9ae48e0156ab6d9ef (diff) | |
parent | ce07a2daa9e53aa86a769f8641b14c2878444fbc (diff) |
Merge branch 'master' into feature/themes
Diffstat (limited to 'crates/ra_hir_def/src/data.rs')
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 154 |
1 files changed, 111 insertions, 43 deletions
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index fee10b237..1aa9a9b7d 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -3,16 +3,17 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_expand::{ | 5 | use hir_expand::{ |
6 | name::{self, AsName, Name}, | 6 | name::{name, AsName, Name}, |
7 | AstId, | 7 | AstId, InFile, |
8 | }; | 8 | }; |
9 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | 9 | use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner}; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | db::DefDatabase, | 12 | db::DefDatabase, |
13 | src::HasSource, | ||
13 | type_ref::{Mutability, TypeRef}, | 14 | type_ref::{Mutability, TypeRef}, |
14 | AssocItemId, AstItemDef, ConstId, ConstLoc, ContainerId, FunctionId, FunctionLoc, HasSource, | 15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, |
15 | ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc, | 16 | ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, |
16 | }; | 17 | }; |
17 | 18 | ||
18 | #[derive(Debug, Clone, PartialEq, Eq)] | 19 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -36,7 +37,7 @@ impl FunctionData { | |||
36 | let self_type = if let Some(type_ref) = self_param.ascribed_type() { | 37 | let self_type = if let Some(type_ref) = self_param.ascribed_type() { |
37 | TypeRef::from_ast(type_ref) | 38 | TypeRef::from_ast(type_ref) |
38 | } else { | 39 | } else { |
39 | let self_type = TypeRef::Path(name::SELF_TYPE.into()); | 40 | let self_type = TypeRef::Path(name![Self].into()); |
40 | match self_param.kind() { | 41 | match self_param.kind() { |
41 | ast::SelfParamKind::Owned => self_type, | 42 | ast::SelfParamKind::Owned => self_type, |
42 | ast::SelfParamKind::Ref => { | 43 | ast::SelfParamKind::Ref => { |
@@ -93,12 +94,12 @@ pub struct TraitData { | |||
93 | 94 | ||
94 | impl TraitData { | 95 | impl TraitData { |
95 | pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: TraitId) -> Arc<TraitData> { | 96 | pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: TraitId) -> Arc<TraitData> { |
96 | let src = tr.source(db); | 97 | let src = tr.lookup(db).source(db); |
97 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 98 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
98 | let auto = src.value.is_auto(); | 99 | let auto = src.value.is_auto(); |
99 | let ast_id_map = db.ast_id_map(src.file_id); | 100 | let ast_id_map = db.ast_id_map(src.file_id); |
100 | 101 | ||
101 | let container = ContainerId::TraitId(tr); | 102 | let container = AssocContainerId::TraitId(tr); |
102 | let items = if let Some(item_list) = src.value.item_list() { | 103 | let items = if let Some(item_list) = src.value.item_list() { |
103 | item_list | 104 | item_list |
104 | .impl_items() | 105 | .impl_items() |
@@ -166,46 +167,24 @@ pub struct ImplData { | |||
166 | 167 | ||
167 | impl ImplData { | 168 | impl ImplData { |
168 | pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc<ImplData> { | 169 | pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc<ImplData> { |
169 | let src = id.source(db); | 170 | let impl_loc = id.lookup(db); |
170 | let items = db.ast_id_map(src.file_id); | 171 | let src = impl_loc.source(db); |
171 | 172 | ||
172 | let target_trait = src.value.target_trait().map(TypeRef::from_ast); | 173 | let target_trait = src.value.target_trait().map(TypeRef::from_ast); |
173 | let target_type = TypeRef::from_ast_opt(src.value.target_type()); | 174 | let target_type = TypeRef::from_ast_opt(src.value.target_type()); |
174 | let is_negative = src.value.is_negative(); | 175 | let is_negative = src.value.is_negative(); |
176 | let module_id = impl_loc.container.module(db); | ||
175 | 177 | ||
176 | let items = if let Some(item_list) = src.value.item_list() { | 178 | let mut items = Vec::new(); |
177 | item_list | 179 | if let Some(item_list) = src.value.item_list() { |
178 | .impl_items() | 180 | items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id)); |
179 | .map(|item_node| match item_node { | 181 | items.extend(collect_impl_items_in_macros( |
180 | ast::ImplItem::FnDef(it) => { | 182 | db, |
181 | let def = FunctionLoc { | 183 | module_id, |
182 | container: ContainerId::ImplId(id), | 184 | &src.with_value(item_list), |
183 | ast_id: AstId::new(src.file_id, items.ast_id(&it)), | 185 | id, |
184 | } | 186 | )); |
185 | .intern(db); | 187 | } |
186 | def.into() | ||
187 | } | ||
188 | ast::ImplItem::ConstDef(it) => { | ||
189 | let def = ConstLoc { | ||
190 | container: ContainerId::ImplId(id), | ||
191 | ast_id: AstId::new(src.file_id, items.ast_id(&it)), | ||
192 | } | ||
193 | .intern(db); | ||
194 | def.into() | ||
195 | } | ||
196 | ast::ImplItem::TypeAliasDef(it) => { | ||
197 | let def = TypeAliasLoc { | ||
198 | container: ContainerId::ImplId(id), | ||
199 | ast_id: AstId::new(src.file_id, items.ast_id(&it)), | ||
200 | } | ||
201 | .intern(db); | ||
202 | def.into() | ||
203 | } | ||
204 | }) | ||
205 | .collect() | ||
206 | } else { | ||
207 | Vec::new() | ||
208 | }; | ||
209 | 188 | ||
210 | let res = ImplData { target_trait, target_type, items, is_negative }; | 189 | let res = ImplData { target_trait, target_type, items, is_negative }; |
211 | Arc::new(res) | 190 | Arc::new(res) |
@@ -236,3 +215,92 @@ impl ConstData { | |||
236 | ConstData { name, type_ref } | 215 | ConstData { name, type_ref } |
237 | } | 216 | } |
238 | } | 217 | } |
218 | |||
219 | fn collect_impl_items_in_macros( | ||
220 | db: &impl DefDatabase, | ||
221 | module_id: ModuleId, | ||
222 | impl_block: &InFile<ast::ItemList>, | ||
223 | id: ImplId, | ||
224 | ) -> Vec<AssocItemId> { | ||
225 | let mut expander = Expander::new(db, impl_block.file_id, module_id); | ||
226 | let mut res = Vec::new(); | ||
227 | |||
228 | // We set a limit to protect against infinite recursion | ||
229 | let limit = 100; | ||
230 | |||
231 | for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) { | ||
232 | res.extend(collect_impl_items_in_macro(db, &mut expander, m, id, limit)) | ||
233 | } | ||
234 | |||
235 | res | ||
236 | } | ||
237 | |||
238 | fn collect_impl_items_in_macro( | ||
239 | db: &impl DefDatabase, | ||
240 | expander: &mut Expander, | ||
241 | m: ast::MacroCall, | ||
242 | id: ImplId, | ||
243 | limit: usize, | ||
244 | ) -> Vec<AssocItemId> { | ||
245 | if limit == 0 { | ||
246 | return Vec::new(); | ||
247 | } | ||
248 | |||
249 | if let Some((mark, items)) = expander.enter_expand(db, m) { | ||
250 | let items: InFile<ast::MacroItems> = expander.to_source(items); | ||
251 | let mut res = collect_impl_items( | ||
252 | db, | ||
253 | items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), | ||
254 | items.file_id, | ||
255 | id, | ||
256 | ); | ||
257 | // Recursive collect macros | ||
258 | // Note that ast::ModuleItem do not include ast::MacroCall | ||
259 | // We cannot use ModuleItemOwner::items here | ||
260 | for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { | ||
261 | res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1)) | ||
262 | } | ||
263 | expander.exit(db, mark); | ||
264 | res | ||
265 | } else { | ||
266 | Vec::new() | ||
267 | } | ||
268 | } | ||
269 | |||
270 | fn collect_impl_items( | ||
271 | db: &impl DefDatabase, | ||
272 | impl_items: impl Iterator<Item = ImplItem>, | ||
273 | file_id: crate::HirFileId, | ||
274 | id: ImplId, | ||
275 | ) -> Vec<AssocItemId> { | ||
276 | let items = db.ast_id_map(file_id); | ||
277 | |||
278 | impl_items | ||
279 | .map(|item_node| match item_node { | ||
280 | ast::ImplItem::FnDef(it) => { | ||
281 | let def = FunctionLoc { | ||
282 | container: AssocContainerId::ImplId(id), | ||
283 | ast_id: AstId::new(file_id, items.ast_id(&it)), | ||
284 | } | ||
285 | .intern(db); | ||
286 | def.into() | ||
287 | } | ||
288 | ast::ImplItem::ConstDef(it) => { | ||
289 | let def = ConstLoc { | ||
290 | container: AssocContainerId::ImplId(id), | ||
291 | ast_id: AstId::new(file_id, items.ast_id(&it)), | ||
292 | } | ||
293 | .intern(db); | ||
294 | def.into() | ||
295 | } | ||
296 | ast::ImplItem::TypeAliasDef(it) => { | ||
297 | let def = TypeAliasLoc { | ||
298 | container: AssocContainerId::ImplId(id), | ||
299 | ast_id: AstId::new(file_id, items.ast_id(&it)), | ||
300 | } | ||
301 | .intern(db); | ||
302 | def.into() | ||
303 | } | ||
304 | }) | ||
305 | .collect() | ||
306 | } | ||