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.rs221
1 files changed, 112 insertions, 109 deletions
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index ccb682f9a..807195d25 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,
@@ -33,6 +34,7 @@ pub struct FunctionData {
33 /// True if the first param is `self`. This is relevant to decide whether this 34 /// True if the first param is `self`. This is relevant to decide whether this
34 /// can be called as a method. 35 /// can be called as a method.
35 pub has_self_param: bool, 36 pub has_self_param: bool,
37 pub is_unsafe: bool,
36 pub visibility: RawVisibility, 38 pub visibility: RawVisibility,
37} 39}
38 40
@@ -40,13 +42,14 @@ impl FunctionData {
40 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> { 42 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
41 let loc = func.lookup(db); 43 let loc = func.lookup(db);
42 let src = loc.source(db); 44 let src = loc.source(db);
45 let ctx = LowerCtx::new(db, src.file_id);
43 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); 46 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
44 let mut params = Vec::new(); 47 let mut params = Vec::new();
45 let mut has_self_param = false; 48 let mut has_self_param = false;
46 if let Some(param_list) = src.value.param_list() { 49 if let Some(param_list) = src.value.param_list() {
47 if let Some(self_param) = param_list.self_param() { 50 if let Some(self_param) = param_list.self_param() {
48 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 51 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
49 TypeRef::from_ast(type_ref) 52 TypeRef::from_ast(&ctx, type_ref)
50 } else { 53 } else {
51 let self_type = TypeRef::Path(name![Self].into()); 54 let self_type = TypeRef::Path(name![Self].into());
52 match self_param.kind() { 55 match self_param.kind() {
@@ -63,14 +66,14 @@ impl FunctionData {
63 has_self_param = true; 66 has_self_param = true;
64 } 67 }
65 for param in param_list.params() { 68 for param in param_list.params() {
66 let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); 69 let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
67 params.push(type_ref); 70 params.push(type_ref);
68 } 71 }
69 } 72 }
70 let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id)); 73 let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id));
71 74
72 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { 75 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
73 TypeRef::from_ast(type_ref) 76 TypeRef::from_ast(&ctx, type_ref)
74 } else { 77 } else {
75 TypeRef::unit() 78 TypeRef::unit()
76 }; 79 };
@@ -83,11 +86,14 @@ impl FunctionData {
83 ret_type 86 ret_type
84 }; 87 };
85 88
89 let is_unsafe = src.value.unsafe_token().is_some();
90
86 let vis_default = RawVisibility::default_for_container(loc.container); 91 let vis_default = RawVisibility::default_for_container(loc.container);
87 let visibility = 92 let visibility =
88 RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility())); 93 RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility()));
89 94
90 let sig = FunctionData { name, params, ret_type, has_self_param, visibility, attrs }; 95 let sig =
96 FunctionData { name, params, ret_type, has_self_param, is_unsafe, visibility, attrs };
91 Arc::new(sig) 97 Arc::new(sig)
92 } 98 }
93} 99}
@@ -122,7 +128,8 @@ impl TypeAliasData {
122 let loc = typ.lookup(db); 128 let loc = typ.lookup(db);
123 let node = loc.source(db); 129 let node = loc.source(db);
124 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); 130 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); 131 let lower_ctx = LowerCtx::new(db, node.file_id);
132 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); 133 let vis_default = RawVisibility::default_for_container(loc.container);
127 let visibility = RawVisibility::from_ast_with_default( 134 let visibility = RawVisibility::from_ast_with_default(
128 db, 135 db,
@@ -130,7 +137,7 @@ impl TypeAliasData {
130 node.as_ref().map(|n| n.visibility()), 137 node.as_ref().map(|n| n.visibility()),
131 ); 138 );
132 let bounds = if let Some(bound_list) = node.value.type_bound_list() { 139 let bounds = if let Some(bound_list) = node.value.type_bound_list() {
133 bound_list.bounds().map(TypeBound::from_ast).collect() 140 bound_list.bounds().map(|it| TypeBound::from_ast(&lower_ctx, it)).collect()
134 } else { 141 } else {
135 Vec::new() 142 Vec::new()
136 }; 143 };
@@ -147,51 +154,31 @@ pub struct TraitData {
147 154
148impl TraitData { 155impl TraitData {
149 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { 156 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
150 let src = tr.lookup(db).source(db); 157 let tr_loc = tr.lookup(db);
158 let src = tr_loc.source(db);
151 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 159 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
152 let auto = src.value.auto_token().is_some(); 160 let auto = src.value.auto_token().is_some();
153 let ast_id_map = db.ast_id_map(src.file_id); 161 let module_id = tr_loc.container.module(db);
154 162
155 let container = AssocContainerId::TraitId(tr); 163 let container = AssocContainerId::TraitId(tr);
156 let items = if let Some(item_list) = src.value.item_list() { 164 let mut items = Vec::new();
157 item_list 165
158 .impl_items() 166 if let Some(item_list) = src.value.item_list() {
159 .map(|item_node| match item_node { 167 let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id);
160 ast::ImplItem::FnDef(it) => { 168 items.extend(collect_items(
161 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 169 db,
162 let def = FunctionLoc { 170 &mut expander,
163 container, 171 item_list.assoc_items(),
164 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), 172 src.file_id,
165 } 173 container,
166 .intern(db) 174 ));
167 .into(); 175 items.extend(collect_items_in_macros(
168 (name, def) 176 db,
169 } 177 &mut expander,
170 ast::ImplItem::ConstDef(it) => { 178 &src.with_value(item_list),
171 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 179 container,
172 let def = ConstLoc { 180 ));
173 container, 181 }
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 }) 182 Arc::new(TraitData { name, items, auto })
196 } 183 }
197 184
@@ -223,29 +210,28 @@ impl ImplData {
223 let _p = profile("impl_data_query"); 210 let _p = profile("impl_data_query");
224 let impl_loc = id.lookup(db); 211 let impl_loc = id.lookup(db);
225 let src = impl_loc.source(db); 212 let src = impl_loc.source(db);
213 let lower_ctx = LowerCtx::new(db, src.file_id);
226 214
227 let target_trait = src.value.target_trait().map(TypeRef::from_ast); 215 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()); 216 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
229 let is_negative = src.value.excl_token().is_some(); 217 let is_negative = src.value.excl_token().is_some();
230 let module_id = impl_loc.container.module(db); 218 let module_id = impl_loc.container.module(db);
219 let container = AssocContainerId::ImplId(id);
231 220
232 let mut items = Vec::new(); 221 let mut items: Vec<AssocItemId> = Vec::new();
233 222
234 if let Some(item_list) = src.value.item_list() { 223 if let Some(item_list) = src.value.item_list() {
235 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); 224 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
236 items.extend(collect_impl_items( 225 items.extend(
237 db, 226 collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container)
238 &mut expander, 227 .into_iter()
239 item_list.impl_items(), 228 .map(|(_, item)| item),
240 src.file_id, 229 );
241 id, 230 items.extend(
242 )); 231 collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container)
243 items.extend(collect_impl_items_in_macros( 232 .into_iter()
244 db, 233 .map(|(_, item)| item),
245 &mut expander, 234 );
246 &src.with_value(item_list),
247 id,
248 ));
249 } 235 }
250 236
251 let res = ImplData { target_trait, target_type, items, is_negative }; 237 let res = ImplData { target_trait, target_type, items, is_negative };
@@ -269,67 +255,90 @@ impl ConstData {
269 Arc::new(ConstData::new(db, vis_default, node)) 255 Arc::new(ConstData::new(db, vis_default, node))
270 } 256 }
271 257
272 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<ConstData> {
273 let node = konst.lookup(db).source(db);
274 Arc::new(ConstData::new(db, RawVisibility::private(), node))
275 }
276
277 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>( 258 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>(
278 db: &dyn DefDatabase, 259 db: &dyn DefDatabase,
279 vis_default: RawVisibility, 260 vis_default: RawVisibility,
280 node: InFile<N>, 261 node: InFile<N>,
281 ) -> ConstData { 262 ) -> ConstData {
263 let ctx = LowerCtx::new(db, node.file_id);
282 let name = node.value.name().map(|n| n.as_name()); 264 let name = node.value.name().map(|n| n.as_name());
283 let type_ref = TypeRef::from_ast_opt(node.value.ascribed_type()); 265 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
284 let visibility = 266 let visibility =
285 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); 267 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility()));
286 ConstData { name, type_ref, visibility } 268 ConstData { name, type_ref, visibility }
287 } 269 }
288} 270}
289 271
290fn collect_impl_items_in_macros( 272#[derive(Debug, Clone, PartialEq, Eq)]
273pub struct StaticData {
274 pub name: Option<Name>,
275 pub type_ref: TypeRef,
276 pub visibility: RawVisibility,
277 pub mutable: bool,
278}
279
280impl StaticData {
281 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> {
282 let node = konst.lookup(db).source(db);
283 let ctx = LowerCtx::new(db, node.file_id);
284
285 let name = node.value.name().map(|n| n.as_name());
286 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
287 let mutable = node.value.mut_token().is_some();
288 let visibility = RawVisibility::from_ast_with_default(
289 db,
290 RawVisibility::private(),
291 node.map(|n| n.visibility()),
292 );
293
294 Arc::new(StaticData { name, type_ref, visibility, mutable })
295 }
296}
297
298fn collect_items_in_macros(
291 db: &dyn DefDatabase, 299 db: &dyn DefDatabase,
292 expander: &mut Expander, 300 expander: &mut Expander,
293 impl_def: &InFile<ast::ItemList>, 301 impl_def: &InFile<ast::ItemList>,
294 id: ImplId, 302 container: AssocContainerId,
295) -> Vec<AssocItemId> { 303) -> Vec<(Name, AssocItemId)> {
296 let mut res = Vec::new(); 304 let mut res = Vec::new();
297 305
298 // We set a limit to protect against infinite recursion 306 // We set a limit to protect against infinite recursion
299 let limit = 100; 307 let limit = 100;
300 308
301 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { 309 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)) 310 res.extend(collect_items_in_macro(db, expander, m, container, limit))
303 } 311 }
304 312
305 res 313 res
306} 314}
307 315
308fn collect_impl_items_in_macro( 316fn collect_items_in_macro(
309 db: &dyn DefDatabase, 317 db: &dyn DefDatabase,
310 expander: &mut Expander, 318 expander: &mut Expander,
311 m: ast::MacroCall, 319 m: ast::MacroCall,
312 id: ImplId, 320 container: AssocContainerId,
313 limit: usize, 321 limit: usize,
314) -> Vec<AssocItemId> { 322) -> Vec<(Name, AssocItemId)> {
315 if limit == 0 { 323 if limit == 0 {
316 return Vec::new(); 324 return Vec::new();
317 } 325 }
318 326
319 if let Some((mark, items)) = expander.enter_expand(db, None, m) { 327 if let Some((mark, items)) = expander.enter_expand(db, None, m) {
320 let items: InFile<ast::MacroItems> = expander.to_source(items); 328 let items: InFile<ast::MacroItems> = expander.to_source(items);
321 let mut res = collect_impl_items( 329 let mut res = collect_items(
322 db, 330 db,
323 expander, 331 expander,
324 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), 332 items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())),
325 items.file_id, 333 items.file_id,
326 id, 334 container,
327 ); 335 );
336
328 // Recursive collect macros 337 // Recursive collect macros
329 // Note that ast::ModuleItem do not include ast::MacroCall 338 // Note that ast::ModuleItem do not include ast::MacroCall
330 // We cannot use ModuleItemOwner::items here 339 // We cannot use ModuleItemOwner::items here
331 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { 340 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)) 341 res.extend(collect_items_in_macro(db, expander, it, container, limit - 1))
333 } 342 }
334 expander.exit(db, mark); 343 expander.exit(db, mark);
335 res 344 res
@@ -338,44 +347,38 @@ fn collect_impl_items_in_macro(
338 } 347 }
339} 348}
340 349
341fn collect_impl_items( 350fn collect_items(
342 db: &dyn DefDatabase, 351 db: &dyn DefDatabase,
343 expander: &mut Expander, 352 expander: &mut Expander,
344 impl_items: impl Iterator<Item = ImplItem>, 353 assoc_items: impl Iterator<Item = AssocItem>,
345 file_id: crate::HirFileId, 354 file_id: crate::HirFileId,
346 id: ImplId, 355 container: AssocContainerId,
347) -> Vec<AssocItemId> { 356) -> Vec<(Name, AssocItemId)> {
348 let items = db.ast_id_map(file_id); 357 let items = db.ast_id_map(file_id);
349 358
350 impl_items 359 assoc_items
351 .filter_map(|item_node| match item_node { 360 .filter_map(|item_node| match item_node {
352 ast::ImplItem::FnDef(it) => { 361 ast::AssocItem::FnDef(it) => {
353 let attrs = expander.parse_attrs(&it); 362 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
354 if !expander.is_cfg_enabled(&attrs) { 363 if !expander.is_cfg_enabled(&it) {
355 return None; 364 return None;
356 } 365 }
357 let def = FunctionLoc { 366 let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
358 container: AssocContainerId::ImplId(id), 367 .intern(db);
359 ast_id: AstId::new(file_id, items.ast_id(&it)), 368 Some((name, def.into()))
360 }
361 .intern(db);
362 Some(def.into())
363 } 369 }
364 ast::ImplItem::ConstDef(it) => { 370 ast::AssocItem::ConstDef(it) => {
365 let def = ConstLoc { 371 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
366 container: AssocContainerId::ImplId(id), 372 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)), 373 .intern(db);
368 } 374 Some((name, def.into()))
369 .intern(db);
370 Some(def.into())
371 } 375 }
372 ast::ImplItem::TypeAliasDef(it) => { 376 ast::AssocItem::TypeAliasDef(it) => {
373 let def = TypeAliasLoc { 377 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
374 container: AssocContainerId::ImplId(id), 378 let def =
375 ast_id: AstId::new(file_id, items.ast_id(&it)), 379 TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
376 } 380 .intern(db);
377 .intern(db); 381 Some((name, def.into()))
378 Some(def.into())
379 } 382 }
380 }) 383 })
381 .collect() 384 .collect()