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.rs382
1 files changed, 137 insertions, 245 deletions
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 53599e74a..282ade2a3 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -2,27 +2,19 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_expand::{ 5use hir_expand::{name::Name, InFile};
6 hygiene::Hygiene,
7 name::{name, AsName, Name},
8 AstId, InFile,
9};
10use ra_prof::profile; 6use ra_prof::profile;
11use ra_syntax::ast::{ 7use ra_syntax::ast;
12 self, AssocItem, AstNode, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner,
13 VisibilityOwner,
14};
15 8
16use crate::{ 9use crate::{
17 attr::Attrs, 10 attr::Attrs,
18 body::LowerCtx, 11 body::Expander,
19 db::DefDatabase, 12 db::DefDatabase,
20 path::{path, AssociatedTypeBinding, GenericArgs, Path}, 13 item_tree::{AssocItem, ItemTreeId, ModItem},
21 src::HasSource, 14 type_ref::{TypeBound, TypeRef},
22 type_ref::{Mutability, TypeBound, TypeRef},
23 visibility::RawVisibility, 15 visibility::RawVisibility,
24 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, 16 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
25 ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc, 17 Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
26}; 18};
27 19
28#[derive(Debug, Clone, PartialEq, Eq)] 20#[derive(Debug, Clone, PartialEq, Eq)]
@@ -41,82 +33,27 @@ pub struct FunctionData {
41impl FunctionData { 33impl FunctionData {
42 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> { 34 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
43 let loc = func.lookup(db); 35 let loc = func.lookup(db);
44 let src = loc.source(db); 36 let item_tree = db.item_tree(loc.id.file_id);
45 let ctx = LowerCtx::new(db, src.file_id); 37 let func = &item_tree[loc.id.value];
46 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); 38
47 let mut params = Vec::new(); 39 Arc::new(FunctionData {
48 let mut has_self_param = false; 40 name: func.name.clone(),
49 if let Some(param_list) = src.value.param_list() { 41 params: func.params.to_vec(),
50 if let Some(self_param) = param_list.self_param() { 42 ret_type: func.ret_type.clone(),
51 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 43 attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(),
52 TypeRef::from_ast(&ctx, type_ref) 44 has_self_param: func.has_self_param,
53 } else { 45 is_unsafe: func.is_unsafe,
54 let self_type = TypeRef::Path(name![Self].into()); 46 visibility: item_tree[func.visibility].clone(),
55 match self_param.kind() { 47 })
56 ast::SelfParamKind::Owned => self_type,
57 ast::SelfParamKind::Ref => {
58 TypeRef::Reference(Box::new(self_type), Mutability::Shared)
59 }
60 ast::SelfParamKind::MutRef => {
61 TypeRef::Reference(Box::new(self_type), Mutability::Mut)
62 }
63 }
64 };
65 params.push(self_type);
66 has_self_param = true;
67 }
68 for param in param_list.params() {
69 let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
70 params.push(type_ref);
71 }
72 }
73 let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id));
74
75 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
76 TypeRef::from_ast(&ctx, type_ref)
77 } else {
78 TypeRef::unit()
79 };
80
81 let ret_type = if src.value.async_token().is_some() {
82 let future_impl = desugar_future_path(ret_type);
83 let ty_bound = TypeBound::Path(future_impl);
84 TypeRef::ImplTrait(vec![ty_bound])
85 } else {
86 ret_type
87 };
88
89 let is_unsafe = src.value.unsafe_token().is_some();
90
91 let vis_default = RawVisibility::default_for_container(loc.container);
92 let visibility =
93 RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility()));
94
95 let sig =
96 FunctionData { name, params, ret_type, has_self_param, is_unsafe, visibility, attrs };
97 Arc::new(sig)
98 } 48 }
99} 49}
100 50
101fn desugar_future_path(orig: TypeRef) -> Path {
102 let path = path![core::future::Future];
103 let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect();
104 let mut last = GenericArgs::empty();
105 last.bindings.push(AssociatedTypeBinding {
106 name: name![Output],
107 type_ref: Some(orig),
108 bounds: Vec::new(),
109 });
110 generic_args.push(Some(Arc::new(last)));
111
112 Path::from_known_path(path, generic_args)
113}
114
115#[derive(Debug, Clone, PartialEq, Eq)] 51#[derive(Debug, Clone, PartialEq, Eq)]
116pub struct TypeAliasData { 52pub struct TypeAliasData {
117 pub name: Name, 53 pub name: Name,
118 pub type_ref: Option<TypeRef>, 54 pub type_ref: Option<TypeRef>,
119 pub visibility: RawVisibility, 55 pub visibility: RawVisibility,
56 /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
120 pub bounds: Vec<TypeBound>, 57 pub bounds: Vec<TypeBound>,
121} 58}
122 59
@@ -126,22 +63,15 @@ impl TypeAliasData {
126 typ: TypeAliasId, 63 typ: TypeAliasId,
127 ) -> Arc<TypeAliasData> { 64 ) -> Arc<TypeAliasData> {
128 let loc = typ.lookup(db); 65 let loc = typ.lookup(db);
129 let node = loc.source(db); 66 let item_tree = db.item_tree(loc.id.file_id);
130 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); 67 let typ = &item_tree[loc.id.value];
131 let lower_ctx = LowerCtx::new(db, node.file_id); 68
132 let type_ref = node.value.type_ref().map(|it| TypeRef::from_ast(&lower_ctx, it)); 69 Arc::new(TypeAliasData {
133 let vis_default = RawVisibility::default_for_container(loc.container); 70 name: typ.name.clone(),
134 let visibility = RawVisibility::from_ast_with_default( 71 type_ref: typ.type_ref.clone(),
135 db, 72 visibility: item_tree[typ.visibility].clone(),
136 vis_default, 73 bounds: typ.bounds.to_vec(),
137 node.as_ref().map(|n| n.visibility()), 74 })
138 );
139 let bounds = if let Some(bound_list) = node.value.type_bound_list() {
140 bound_list.bounds().map(|it| TypeBound::from_ast(&lower_ctx, it)).collect()
141 } else {
142 Vec::new()
143 };
144 Arc::new(TypeAliasData { name, type_ref, visibility, bounds })
145 } 75 }
146} 76}
147 77
@@ -155,30 +85,24 @@ pub struct TraitData {
155impl TraitData { 85impl TraitData {
156 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { 86 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
157 let tr_loc = tr.lookup(db); 87 let tr_loc = tr.lookup(db);
158 let src = tr_loc.source(db); 88 let item_tree = db.item_tree(tr_loc.id.file_id);
159 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 89 let tr_def = &item_tree[tr_loc.id.value];
160 let auto = src.value.auto_token().is_some(); 90 let name = tr_def.name.clone();
91 let auto = tr_def.auto;
161 let module_id = tr_loc.container.module(db); 92 let module_id = tr_loc.container.module(db);
162
163 let container = AssocContainerId::TraitId(tr); 93 let container = AssocContainerId::TraitId(tr);
164 let mut items = Vec::new(); 94 let mut expander = Expander::new(db, tr_loc.id.file_id, module_id);
165 95
166 if let Some(item_list) = src.value.item_list() { 96 let items = collect_items(
167 let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id); 97 db,
168 items.extend(collect_items( 98 module_id,
169 db, 99 &mut expander,
170 &mut expander, 100 tr_def.items.iter().copied(),
171 item_list.assoc_items(), 101 tr_loc.id.file_id,
172 src.file_id, 102 container,
173 container, 103 100,
174 )); 104 );
175 items.extend(collect_items_in_macros( 105
176 db,
177 &mut expander,
178 &src.with_value(item_list),
179 container,
180 ));
181 }
182 Arc::new(TraitData { name, items, auto }) 106 Arc::new(TraitData { name, items, auto })
183 } 107 }
184 108
@@ -209,33 +133,28 @@ impl ImplData {
209 pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> { 133 pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> {
210 let _p = profile("impl_data_query"); 134 let _p = profile("impl_data_query");
211 let impl_loc = id.lookup(db); 135 let impl_loc = id.lookup(db);
212 let src = impl_loc.source(db);
213 let lower_ctx = LowerCtx::new(db, src.file_id);
214 136
215 let target_trait = src.value.target_trait().map(|it| TypeRef::from_ast(&lower_ctx, it)); 137 let item_tree = db.item_tree(impl_loc.id.file_id);
216 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type()); 138 let impl_def = &item_tree[impl_loc.id.value];
217 let is_negative = src.value.excl_token().is_some(); 139 let target_trait = impl_def.target_trait.clone();
140 let target_type = impl_def.target_type.clone();
141 let is_negative = impl_def.is_negative;
218 let module_id = impl_loc.container.module(db); 142 let module_id = impl_loc.container.module(db);
219 let container = AssocContainerId::ImplId(id); 143 let container = AssocContainerId::ImplId(id);
144 let mut expander = Expander::new(db, impl_loc.id.file_id, module_id);
220 145
221 let mut items: Vec<AssocItemId> = Vec::new(); 146 let items = collect_items(
222 147 db,
223 if let Some(item_list) = src.value.item_list() { 148 module_id,
224 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); 149 &mut expander,
225 items.extend( 150 impl_def.items.iter().copied(),
226 collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container) 151 impl_loc.id.file_id,
227 .into_iter() 152 container,
228 .map(|(_, item)| item), 153 100,
229 ); 154 );
230 items.extend( 155 let items = items.into_iter().map(|(_, item)| item).collect();
231 collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container)
232 .into_iter()
233 .map(|(_, item)| item),
234 );
235 }
236 156
237 let res = ImplData { target_trait, target_type, items, is_negative }; 157 Arc::new(ImplData { target_trait, target_type, items, is_negative })
238 Arc::new(res)
239 } 158 }
240} 159}
241 160
@@ -250,22 +169,14 @@ pub struct ConstData {
250impl ConstData { 169impl ConstData {
251 pub(crate) fn const_data_query(db: &dyn DefDatabase, konst: ConstId) -> Arc<ConstData> { 170 pub(crate) fn const_data_query(db: &dyn DefDatabase, konst: ConstId) -> Arc<ConstData> {
252 let loc = konst.lookup(db); 171 let loc = konst.lookup(db);
253 let node = loc.source(db); 172 let item_tree = db.item_tree(loc.id.file_id);
254 let vis_default = RawVisibility::default_for_container(loc.container); 173 let konst = &item_tree[loc.id.value];
255 Arc::new(ConstData::new(db, vis_default, node))
256 }
257 174
258 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>( 175 Arc::new(ConstData {
259 db: &dyn DefDatabase, 176 name: konst.name.clone(),
260 vis_default: RawVisibility, 177 type_ref: konst.type_ref.clone(),
261 node: InFile<N>, 178 visibility: item_tree[konst.visibility].clone(),
262 ) -> ConstData { 179 })
263 let ctx = LowerCtx::new(db, node.file_id);
264 let name = node.value.name().map(|n| n.as_name());
265 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
266 let visibility =
267 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility()));
268 ConstData { name, type_ref, visibility }
269 } 180 }
270} 181}
271 182
@@ -279,44 +190,25 @@ pub struct StaticData {
279 190
280impl StaticData { 191impl StaticData {
281 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> { 192 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> {
282 let node = konst.lookup(db).source(db); 193 let node = konst.lookup(db);
283 let ctx = LowerCtx::new(db, node.file_id); 194 let item_tree = db.item_tree(node.id.file_id);
284 195 let statik = &item_tree[node.id.value];
285 let name = node.value.name().map(|n| n.as_name()); 196
286 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type()); 197 Arc::new(StaticData {
287 let mutable = node.value.mut_token().is_some(); 198 name: Some(statik.name.clone()),
288 let visibility = RawVisibility::from_ast_with_default( 199 type_ref: statik.type_ref.clone(),
289 db, 200 visibility: item_tree[statik.visibility].clone(),
290 RawVisibility::private(), 201 mutable: statik.mutable,
291 node.map(|n| n.visibility()), 202 })
292 );
293
294 Arc::new(StaticData { name, type_ref, visibility, mutable })
295 }
296}
297
298fn collect_items_in_macros(
299 db: &dyn DefDatabase,
300 expander: &mut Expander,
301 impl_def: &InFile<ast::ItemList>,
302 container: AssocContainerId,
303) -> Vec<(Name, AssocItemId)> {
304 let mut res = Vec::new();
305
306 // We set a limit to protect against infinite recursion
307 let limit = 100;
308
309 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) {
310 res.extend(collect_items_in_macro(db, expander, m, container, limit))
311 } 203 }
312
313 res
314} 204}
315 205
316fn collect_items_in_macro( 206fn collect_items(
317 db: &dyn DefDatabase, 207 db: &dyn DefDatabase,
208 module: ModuleId,
318 expander: &mut Expander, 209 expander: &mut Expander,
319 m: ast::MacroCall, 210 assoc_items: impl Iterator<Item = AssocItem>,
211 file_id: crate::HirFileId,
320 container: AssocContainerId, 212 container: AssocContainerId,
321 limit: usize, 213 limit: usize,
322) -> Vec<(Name, AssocItemId)> { 214) -> Vec<(Name, AssocItemId)> {
@@ -324,62 +216,62 @@ fn collect_items_in_macro(
324 return Vec::new(); 216 return Vec::new();
325 } 217 }
326 218
327 if let Some((mark, items)) = expander.enter_expand(db, None, m) { 219 let item_tree = db.item_tree(file_id);
328 let items: InFile<ast::MacroItems> = expander.to_source(items); 220 let cfg_options = db.crate_graph()[module.krate].cfg_options.clone();
329 let mut res = collect_items( 221
330 db, 222 let mut items = Vec::new();
331 expander, 223 for item in assoc_items {
332 items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())), 224 match item {
333 items.file_id, 225 AssocItem::Function(id) => {
334 container, 226 let item = &item_tree[id];
335 ); 227 let attrs = item_tree.attrs(ModItem::from(id).into());
336 228 if !attrs.is_cfg_enabled(&cfg_options) {
337 // Recursive collect macros 229 continue;
338 // Note that ast::ModuleItem do not include ast::MacroCall
339 // We cannot use ModuleItemOwner::items here
340 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) {
341 res.extend(collect_items_in_macro(db, expander, it, container, limit - 1))
342 }
343 expander.exit(db, mark);
344 res
345 } else {
346 Vec::new()
347 }
348}
349
350fn collect_items(
351 db: &dyn DefDatabase,
352 expander: &mut Expander,
353 assoc_items: impl Iterator<Item = AssocItem>,
354 file_id: crate::HirFileId,
355 container: AssocContainerId,
356) -> Vec<(Name, AssocItemId)> {
357 let items = db.ast_id_map(file_id);
358
359 assoc_items
360 .filter_map(|item_node| match item_node {
361 ast::AssocItem::FnDef(it) => {
362 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
363 if !expander.is_cfg_enabled(&it) {
364 return None;
365 } 230 }
366 let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } 231 let def = FunctionLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db);
367 .intern(db); 232 items.push((item.name.clone(), def.into()));
368 Some((name, def.into()))
369 } 233 }
370 ast::AssocItem::ConstDef(it) => { 234 // FIXME: cfg?
371 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 235 AssocItem::Const(id) => {
372 let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } 236 let item = &item_tree[id];
373 .intern(db); 237 let name = match item.name.clone() {
374 Some((name, def.into())) 238 Some(name) => name,
239 None => continue,
240 };
241 let def = ConstLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db);
242 items.push((name, def.into()));
375 } 243 }
376 ast::AssocItem::TypeAliasDef(it) => { 244 AssocItem::TypeAlias(id) => {
377 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 245 let item = &item_tree[id];
378 let def = 246 let def = TypeAliasLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db);
379 TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } 247 items.push((item.name.clone(), def.into()));
380 .intern(db);
381 Some((name, def.into()))
382 } 248 }
383 }) 249 AssocItem::MacroCall(call) => {
384 .collect() 250 let call = &item_tree[call];
251 let ast_id_map = db.ast_id_map(file_id);
252 let root = db.parse_or_expand(file_id).unwrap();
253 let call = ast_id_map.get(call.ast_id).to_node(&root);
254
255 if let Some((mark, mac)) = expander.enter_expand(db, None, call) {
256 let src: InFile<ast::MacroItems> = expander.to_source(mac);
257 let item_tree = db.item_tree(src.file_id);
258 let iter =
259 item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item);
260 items.extend(collect_items(
261 db,
262 module,
263 expander,
264 iter,
265 src.file_id,
266 container,
267 limit - 1,
268 ));
269
270 expander.exit(db, mark);
271 }
272 }
273 }
274 }
275
276 items
385} 277}