diff options
Diffstat (limited to 'crates/ra_hir_def/src/data.rs')
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 221 |
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 | }; |
10 | use ra_prof::profile; | 10 | use ra_prof::profile; |
11 | use ra_syntax::ast::{ | 11 | use 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 | ||
16 | use crate::{ | 16 | use 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 | ||
148 | impl TraitData { | 155 | impl 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 | ||
290 | fn collect_impl_items_in_macros( | 272 | #[derive(Debug, Clone, PartialEq, Eq)] |
273 | pub struct StaticData { | ||
274 | pub name: Option<Name>, | ||
275 | pub type_ref: TypeRef, | ||
276 | pub visibility: RawVisibility, | ||
277 | pub mutable: bool, | ||
278 | } | ||
279 | |||
280 | impl 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 | |||
298 | fn 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 | ||
308 | fn collect_impl_items_in_macro( | 316 | fn 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 | ||
341 | fn collect_impl_items( | 350 | fn 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() |