aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/data.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/data.rs')
-rw-r--r--crates/ra_hir_def/src/data.rs154
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 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_expand::{ 5use hir_expand::{
6 name::{self, AsName, Name}, 6 name::{name, AsName, Name},
7 AstId, 7 AstId, InFile,
8}; 8};
9use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 9use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner};
10 10
11use crate::{ 11use 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
94impl TraitData { 95impl 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
167impl ImplData { 168impl 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
219fn 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
238fn 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
270fn 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}