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.rs184
1 files changed, 81 insertions, 103 deletions
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index ccb682f9a..e7eb2bb11 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -9,12 +9,13 @@ use hir_expand::{
9}; 9};
10use ra_prof::profile; 10use ra_prof::profile;
11use ra_syntax::ast::{ 11use ra_syntax::ast::{
12 self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, 12 self, AssocItem, AstNode, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner,
13 VisibilityOwner, 13 VisibilityOwner,
14}; 14};
15 15
16use crate::{ 16use crate::{
17 attr::Attrs, 17 attr::Attrs,
18 body::LowerCtx,
18 db::DefDatabase, 19 db::DefDatabase,
19 path::{path, AssociatedTypeBinding, GenericArgs, Path}, 20 path::{path, AssociatedTypeBinding, GenericArgs, Path},
20 src::HasSource, 21 src::HasSource,
@@ -40,13 +41,14 @@ impl FunctionData {
40 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> { 41 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
41 let loc = func.lookup(db); 42 let loc = func.lookup(db);
42 let src = loc.source(db); 43 let src = loc.source(db);
44 let ctx = LowerCtx::new(db, src.file_id);
43 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); 45 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
44 let mut params = Vec::new(); 46 let mut params = Vec::new();
45 let mut has_self_param = false; 47 let mut has_self_param = false;
46 if let Some(param_list) = src.value.param_list() { 48 if let Some(param_list) = src.value.param_list() {
47 if let Some(self_param) = param_list.self_param() { 49 if let Some(self_param) = param_list.self_param() {
48 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 50 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
49 TypeRef::from_ast(type_ref) 51 TypeRef::from_ast(&ctx, type_ref)
50 } else { 52 } else {
51 let self_type = TypeRef::Path(name![Self].into()); 53 let self_type = TypeRef::Path(name![Self].into());
52 match self_param.kind() { 54 match self_param.kind() {
@@ -63,14 +65,14 @@ impl FunctionData {
63 has_self_param = true; 65 has_self_param = true;
64 } 66 }
65 for param in param_list.params() { 67 for param in param_list.params() {
66 let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); 68 let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
67 params.push(type_ref); 69 params.push(type_ref);
68 } 70 }
69 } 71 }
70 let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id)); 72 let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id));
71 73
72 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { 74 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
73 TypeRef::from_ast(type_ref) 75 TypeRef::from_ast(&ctx, type_ref)
74 } else { 76 } else {
75 TypeRef::unit() 77 TypeRef::unit()
76 }; 78 };
@@ -122,7 +124,8 @@ impl TypeAliasData {
122 let loc = typ.lookup(db); 124 let loc = typ.lookup(db);
123 let node = loc.source(db); 125 let node = loc.source(db);
124 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); 126 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name());
125 let type_ref = node.value.type_ref().map(TypeRef::from_ast); 127 let lower_ctx = LowerCtx::new(db, node.file_id);
128 let type_ref = node.value.type_ref().map(|it| TypeRef::from_ast(&lower_ctx, it));
126 let vis_default = RawVisibility::default_for_container(loc.container); 129 let vis_default = RawVisibility::default_for_container(loc.container);
127 let visibility = RawVisibility::from_ast_with_default( 130 let visibility = RawVisibility::from_ast_with_default(
128 db, 131 db,
@@ -130,7 +133,7 @@ impl TypeAliasData {
130 node.as_ref().map(|n| n.visibility()), 133 node.as_ref().map(|n| n.visibility()),
131 ); 134 );
132 let bounds = if let Some(bound_list) = node.value.type_bound_list() { 135 let bounds = if let Some(bound_list) = node.value.type_bound_list() {
133 bound_list.bounds().map(TypeBound::from_ast).collect() 136 bound_list.bounds().map(|it| TypeBound::from_ast(&lower_ctx, it)).collect()
134 } else { 137 } else {
135 Vec::new() 138 Vec::new()
136 }; 139 };
@@ -147,51 +150,31 @@ pub struct TraitData {
147 150
148impl TraitData { 151impl TraitData {
149 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { 152 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
150 let src = tr.lookup(db).source(db); 153 let tr_loc = tr.lookup(db);
154 let src = tr_loc.source(db);
151 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 155 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
152 let auto = src.value.auto_token().is_some(); 156 let auto = src.value.auto_token().is_some();
153 let ast_id_map = db.ast_id_map(src.file_id); 157 let module_id = tr_loc.container.module(db);
154 158
155 let container = AssocContainerId::TraitId(tr); 159 let container = AssocContainerId::TraitId(tr);
156 let items = if let Some(item_list) = src.value.item_list() { 160 let mut items = Vec::new();
157 item_list 161
158 .impl_items() 162 if let Some(item_list) = src.value.item_list() {
159 .map(|item_node| match item_node { 163 let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id);
160 ast::ImplItem::FnDef(it) => { 164 items.extend(collect_items(
161 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 165 db,
162 let def = FunctionLoc { 166 &mut expander,
163 container, 167 item_list.assoc_items(),
164 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), 168 src.file_id,
165 } 169 container,
166 .intern(db) 170 ));
167 .into(); 171 items.extend(collect_items_in_macros(
168 (name, def) 172 db,
169 } 173 &mut expander,
170 ast::ImplItem::ConstDef(it) => { 174 &src.with_value(item_list),
171 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 175 container,
172 let def = ConstLoc { 176 ));
173 container, 177 }
174 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
175 }
176 .intern(db)
177 .into();
178 (name, def)
179 }
180 ast::ImplItem::TypeAliasDef(it) => {
181 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
182 let def = TypeAliasLoc {
183 container,
184 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
185 }
186 .intern(db)
187 .into();
188 (name, def)
189 }
190 })
191 .collect()
192 } else {
193 Vec::new()
194 };
195 Arc::new(TraitData { name, items, auto }) 178 Arc::new(TraitData { name, items, auto })
196 } 179 }
197 180
@@ -223,29 +206,28 @@ impl ImplData {
223 let _p = profile("impl_data_query"); 206 let _p = profile("impl_data_query");
224 let impl_loc = id.lookup(db); 207 let impl_loc = id.lookup(db);
225 let src = impl_loc.source(db); 208 let src = impl_loc.source(db);
209 let lower_ctx = LowerCtx::new(db, src.file_id);
226 210
227 let target_trait = src.value.target_trait().map(TypeRef::from_ast); 211 let target_trait = src.value.target_trait().map(|it| TypeRef::from_ast(&lower_ctx, it));
228 let target_type = TypeRef::from_ast_opt(src.value.target_type()); 212 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
229 let is_negative = src.value.excl_token().is_some(); 213 let is_negative = src.value.excl_token().is_some();
230 let module_id = impl_loc.container.module(db); 214 let module_id = impl_loc.container.module(db);
215 let container = AssocContainerId::ImplId(id);
231 216
232 let mut items = Vec::new(); 217 let mut items: Vec<AssocItemId> = Vec::new();
233 218
234 if let Some(item_list) = src.value.item_list() { 219 if let Some(item_list) = src.value.item_list() {
235 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); 220 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
236 items.extend(collect_impl_items( 221 items.extend(
237 db, 222 collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container)
238 &mut expander, 223 .into_iter()
239 item_list.impl_items(), 224 .map(|(_, item)| item),
240 src.file_id, 225 );
241 id, 226 items.extend(
242 )); 227 collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container)
243 items.extend(collect_impl_items_in_macros( 228 .into_iter()
244 db, 229 .map(|(_, item)| item),
245 &mut expander, 230 );
246 &src.with_value(item_list),
247 id,
248 ));
249 } 231 }
250 232
251 let res = ImplData { target_trait, target_type, items, is_negative }; 233 let res = ImplData { target_trait, target_type, items, is_negative };
@@ -279,57 +261,59 @@ impl ConstData {
279 vis_default: RawVisibility, 261 vis_default: RawVisibility,
280 node: InFile<N>, 262 node: InFile<N>,
281 ) -> ConstData { 263 ) -> ConstData {
264 let ctx = LowerCtx::new(db, node.file_id);
282 let name = node.value.name().map(|n| n.as_name()); 265 let name = node.value.name().map(|n| n.as_name());
283 let type_ref = TypeRef::from_ast_opt(node.value.ascribed_type()); 266 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
284 let visibility = 267 let visibility =
285 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); 268 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility()));
286 ConstData { name, type_ref, visibility } 269 ConstData { name, type_ref, visibility }
287 } 270 }
288} 271}
289 272
290fn collect_impl_items_in_macros( 273fn collect_items_in_macros(
291 db: &dyn DefDatabase, 274 db: &dyn DefDatabase,
292 expander: &mut Expander, 275 expander: &mut Expander,
293 impl_def: &InFile<ast::ItemList>, 276 impl_def: &InFile<ast::ItemList>,
294 id: ImplId, 277 container: AssocContainerId,
295) -> Vec<AssocItemId> { 278) -> Vec<(Name, AssocItemId)> {
296 let mut res = Vec::new(); 279 let mut res = Vec::new();
297 280
298 // We set a limit to protect against infinite recursion 281 // We set a limit to protect against infinite recursion
299 let limit = 100; 282 let limit = 100;
300 283
301 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { 284 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) {
302 res.extend(collect_impl_items_in_macro(db, expander, m, id, limit)) 285 res.extend(collect_items_in_macro(db, expander, m, container, limit))
303 } 286 }
304 287
305 res 288 res
306} 289}
307 290
308fn collect_impl_items_in_macro( 291fn collect_items_in_macro(
309 db: &dyn DefDatabase, 292 db: &dyn DefDatabase,
310 expander: &mut Expander, 293 expander: &mut Expander,
311 m: ast::MacroCall, 294 m: ast::MacroCall,
312 id: ImplId, 295 container: AssocContainerId,
313 limit: usize, 296 limit: usize,
314) -> Vec<AssocItemId> { 297) -> Vec<(Name, AssocItemId)> {
315 if limit == 0 { 298 if limit == 0 {
316 return Vec::new(); 299 return Vec::new();
317 } 300 }
318 301
319 if let Some((mark, items)) = expander.enter_expand(db, None, m) { 302 if let Some((mark, items)) = expander.enter_expand(db, None, m) {
320 let items: InFile<ast::MacroItems> = expander.to_source(items); 303 let items: InFile<ast::MacroItems> = expander.to_source(items);
321 let mut res = collect_impl_items( 304 let mut res = collect_items(
322 db, 305 db,
323 expander, 306 expander,
324 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), 307 items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())),
325 items.file_id, 308 items.file_id,
326 id, 309 container,
327 ); 310 );
311
328 // Recursive collect macros 312 // Recursive collect macros
329 // Note that ast::ModuleItem do not include ast::MacroCall 313 // Note that ast::ModuleItem do not include ast::MacroCall
330 // We cannot use ModuleItemOwner::items here 314 // We cannot use ModuleItemOwner::items here
331 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { 315 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) {
332 res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1)) 316 res.extend(collect_items_in_macro(db, expander, it, container, limit - 1))
333 } 317 }
334 expander.exit(db, mark); 318 expander.exit(db, mark);
335 res 319 res
@@ -338,44 +322,38 @@ fn collect_impl_items_in_macro(
338 } 322 }
339} 323}
340 324
341fn collect_impl_items( 325fn collect_items(
342 db: &dyn DefDatabase, 326 db: &dyn DefDatabase,
343 expander: &mut Expander, 327 expander: &mut Expander,
344 impl_items: impl Iterator<Item = ImplItem>, 328 assoc_items: impl Iterator<Item = AssocItem>,
345 file_id: crate::HirFileId, 329 file_id: crate::HirFileId,
346 id: ImplId, 330 container: AssocContainerId,
347) -> Vec<AssocItemId> { 331) -> Vec<(Name, AssocItemId)> {
348 let items = db.ast_id_map(file_id); 332 let items = db.ast_id_map(file_id);
349 333
350 impl_items 334 assoc_items
351 .filter_map(|item_node| match item_node { 335 .filter_map(|item_node| match item_node {
352 ast::ImplItem::FnDef(it) => { 336 ast::AssocItem::FnDef(it) => {
353 let attrs = expander.parse_attrs(&it); 337 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
354 if !expander.is_cfg_enabled(&attrs) { 338 if !expander.is_cfg_enabled(&it) {
355 return None; 339 return None;
356 } 340 }
357 let def = FunctionLoc { 341 let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
358 container: AssocContainerId::ImplId(id), 342 .intern(db);
359 ast_id: AstId::new(file_id, items.ast_id(&it)), 343 Some((name, def.into()))
360 }
361 .intern(db);
362 Some(def.into())
363 } 344 }
364 ast::ImplItem::ConstDef(it) => { 345 ast::AssocItem::ConstDef(it) => {
365 let def = ConstLoc { 346 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
366 container: AssocContainerId::ImplId(id), 347 let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
367 ast_id: AstId::new(file_id, items.ast_id(&it)), 348 .intern(db);
368 } 349 Some((name, def.into()))
369 .intern(db);
370 Some(def.into())
371 } 350 }
372 ast::ImplItem::TypeAliasDef(it) => { 351 ast::AssocItem::TypeAliasDef(it) => {
373 let def = TypeAliasLoc { 352 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
374 container: AssocContainerId::ImplId(id), 353 let def =
375 ast_id: AstId::new(file_id, items.ast_id(&it)), 354 TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
376 } 355 .intern(db);
377 .intern(db); 356 Some((name, def.into()))
378 Some(def.into())
379 } 357 }
380 }) 358 })
381 .collect() 359 .collect()