diff options
author | Jonas Schievink <[email protected]> | 2020-06-22 14:07:06 +0100 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2020-06-24 15:53:16 +0100 |
commit | 4b03b39d5b4b00daffb120a4d2d9ea4a55a9a7ac (patch) | |
tree | 85431e53ce86bbcf16ba9b38fcc5f2ad27378722 /crates/ra_hir_def/src/item_tree/lower.rs | |
parent | b94caeb88b4aab7219d4b2f5c8c6c668199247fb (diff) |
draw the rest of the owl
Diffstat (limited to 'crates/ra_hir_def/src/item_tree/lower.rs')
-rw-r--r-- | crates/ra_hir_def/src/item_tree/lower.rs | 271 |
1 files changed, 155 insertions, 116 deletions
diff --git a/crates/ra_hir_def/src/item_tree/lower.rs b/crates/ra_hir_def/src/item_tree/lower.rs index 737a69c30..f2b8a9418 100644 --- a/crates/ra_hir_def/src/item_tree/lower.rs +++ b/crates/ra_hir_def/src/item_tree/lower.rs | |||
@@ -7,9 +7,12 @@ use crate::{ | |||
7 | }; | 7 | }; |
8 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}; | 8 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}; |
9 | use ra_arena::map::ArenaMap; | 9 | use ra_arena::map::ArenaMap; |
10 | use ra_syntax::ast::{self, ModuleItemOwner}; | 10 | use ra_syntax::{ |
11 | ast::{self, ModuleItemOwner}, | ||
12 | SyntaxNode, | ||
13 | }; | ||
11 | use smallvec::SmallVec; | 14 | use smallvec::SmallVec; |
12 | use std::sync::Arc; | 15 | use std::{mem, sync::Arc}; |
13 | 16 | ||
14 | fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> { | 17 | fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> { |
15 | FileItemTreeId { index, _p: PhantomData } | 18 | FileItemTreeId { index, _p: PhantomData } |
@@ -27,78 +30,81 @@ where | |||
27 | } | 30 | } |
28 | 31 | ||
29 | pub(super) struct Ctx { | 32 | pub(super) struct Ctx { |
30 | pub tree: ItemTree, | 33 | tree: ItemTree, |
31 | pub hygiene: Hygiene, | 34 | hygiene: Hygiene, |
32 | pub file: HirFileId, | 35 | file: HirFileId, |
33 | pub source_ast_id_map: Arc<AstIdMap>, | 36 | source_ast_id_map: Arc<AstIdMap>, |
34 | pub body_ctx: crate::body::LowerCtx, | 37 | body_ctx: crate::body::LowerCtx, |
38 | inner_items: Vec<ModItem>, | ||
35 | } | 39 | } |
36 | 40 | ||
37 | impl Ctx { | 41 | impl Ctx { |
42 | pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self { | ||
43 | Self { | ||
44 | tree: ItemTree::empty(file), | ||
45 | hygiene, | ||
46 | file, | ||
47 | source_ast_id_map: db.ast_id_map(file), | ||
48 | body_ctx: crate::body::LowerCtx::new(db, file), | ||
49 | inner_items: Vec::new(), | ||
50 | } | ||
51 | } | ||
52 | |||
38 | pub(super) fn lower(mut self, item_owner: &dyn ModuleItemOwner) -> ItemTree { | 53 | pub(super) fn lower(mut self, item_owner: &dyn ModuleItemOwner) -> ItemTree { |
39 | self.tree.top_level = item_owner | 54 | self.tree.top_level = item_owner |
40 | .items() | 55 | .items() |
41 | .flat_map(|item| self.lower_mod_item(&item)) | 56 | .flat_map(|item| self.lower_mod_item(&item, false)) |
42 | .flat_map(|items| items.0) | 57 | .flat_map(|items| items.0) |
43 | .collect(); | 58 | .collect(); |
44 | self.tree | 59 | self.tree |
45 | } | 60 | } |
46 | 61 | ||
47 | fn lower_mod_item(&mut self, item: &ast::ModuleItem) -> Option<ModItems> { | 62 | fn lower_mod_item(&mut self, item: &ast::ModuleItem, inner: bool) -> Option<ModItems> { |
63 | assert!(inner || self.inner_items.is_empty()); | ||
64 | |||
65 | // Collect inner items for 1-to-1-lowered items. | ||
66 | match item { | ||
67 | ast::ModuleItem::StructDef(_) | ||
68 | | ast::ModuleItem::UnionDef(_) | ||
69 | | ast::ModuleItem::EnumDef(_) | ||
70 | | ast::ModuleItem::FnDef(_) | ||
71 | | ast::ModuleItem::TypeAliasDef(_) | ||
72 | | ast::ModuleItem::ConstDef(_) | ||
73 | | ast::ModuleItem::StaticDef(_) | ||
74 | | ast::ModuleItem::MacroCall(_) => self.collect_inner_items(item.syntax()), | ||
75 | |||
76 | // These are handled in their respective `lower_X` method (since we can't just blindly | ||
77 | // walk them). | ||
78 | ast::ModuleItem::TraitDef(_) | ||
79 | | ast::ModuleItem::ImplDef(_) | ||
80 | | ast::ModuleItem::ExternBlock(_) => {} | ||
81 | |||
82 | // These don't have inner items. | ||
83 | ast::ModuleItem::Module(_) | ||
84 | | ast::ModuleItem::ExternCrateItem(_) | ||
85 | | ast::ModuleItem::UseItem(_) => {} | ||
86 | }; | ||
87 | |||
48 | let attrs = Attrs::new(item, &self.hygiene); | 88 | let attrs = Attrs::new(item, &self.hygiene); |
49 | let items = match item { | 89 | let items = match item { |
50 | ast::ModuleItem::StructDef(ast) => { | 90 | ast::ModuleItem::StructDef(ast) => self.lower_struct(ast).map(Into::into), |
51 | self.lower_struct(ast).map(|data| id(self.tree.structs.alloc(data)).into()) | 91 | ast::ModuleItem::UnionDef(ast) => self.lower_union(ast).map(Into::into), |
52 | } | 92 | ast::ModuleItem::EnumDef(ast) => self.lower_enum(ast).map(Into::into), |
53 | ast::ModuleItem::UnionDef(ast) => { | 93 | ast::ModuleItem::FnDef(ast) => self.lower_function(ast).map(Into::into), |
54 | self.lower_union(ast).map(|data| id(self.tree.unions.alloc(data)).into()) | 94 | ast::ModuleItem::TypeAliasDef(ast) => self.lower_type_alias(ast).map(Into::into), |
55 | } | 95 | ast::ModuleItem::StaticDef(ast) => self.lower_static(ast).map(Into::into), |
56 | ast::ModuleItem::EnumDef(ast) => { | 96 | ast::ModuleItem::ConstDef(ast) => Some(self.lower_const(ast).into()), |
57 | self.lower_enum(ast).map(|data| id(self.tree.enums.alloc(data)).into()) | 97 | ast::ModuleItem::Module(ast) => self.lower_module(ast).map(Into::into), |
58 | } | 98 | ast::ModuleItem::TraitDef(ast) => self.lower_trait(ast).map(Into::into), |
59 | ast::ModuleItem::FnDef(ast) => { | 99 | ast::ModuleItem::ImplDef(ast) => self.lower_impl(ast).map(Into::into), |
60 | self.lower_function(ast).map(|data| id(self.tree.functions.alloc(data)).into()) | ||
61 | } | ||
62 | ast::ModuleItem::TypeAliasDef(ast) => { | ||
63 | self.lower_type_alias(ast).map(|data| id(self.tree.type_aliases.alloc(data)).into()) | ||
64 | } | ||
65 | ast::ModuleItem::StaticDef(ast) => { | ||
66 | self.lower_static(ast).map(|data| id(self.tree.statics.alloc(data)).into()) | ||
67 | } | ||
68 | ast::ModuleItem::ConstDef(ast) => { | ||
69 | let data = self.lower_const(ast); | ||
70 | Some(id(self.tree.consts.alloc(data)).into()) | ||
71 | } | ||
72 | ast::ModuleItem::Module(ast) => { | ||
73 | self.lower_module(ast).map(|data| id(self.tree.mods.alloc(data)).into()) | ||
74 | } | ||
75 | ast::ModuleItem::TraitDef(ast) => { | ||
76 | self.lower_trait(ast).map(|data| id(self.tree.traits.alloc(data)).into()) | ||
77 | } | ||
78 | ast::ModuleItem::ImplDef(ast) => { | ||
79 | self.lower_impl(ast).map(|data| id(self.tree.impls.alloc(data)).into()) | ||
80 | } | ||
81 | ast::ModuleItem::UseItem(ast) => Some(ModItems( | 100 | ast::ModuleItem::UseItem(ast) => Some(ModItems( |
82 | self.lower_use(ast) | 101 | self.lower_use(ast).into_iter().map(Into::into).collect::<SmallVec<_>>(), |
83 | .into_iter() | ||
84 | .map(|data| id(self.tree.imports.alloc(data)).into()) | ||
85 | .collect::<SmallVec<_>>(), | ||
86 | )), | 102 | )), |
87 | ast::ModuleItem::ExternCrateItem(ast) => { | 103 | ast::ModuleItem::ExternCrateItem(ast) => self.lower_extern_crate(ast).map(Into::into), |
88 | self.lower_extern_crate(ast).map(|data| id(self.tree.imports.alloc(data)).into()) | 104 | ast::ModuleItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), |
105 | ast::ModuleItem::ExternBlock(ast) => { | ||
106 | Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) | ||
89 | } | 107 | } |
90 | ast::ModuleItem::MacroCall(ast) => { | ||
91 | self.lower_macro_call(ast).map(|data| id(self.tree.macro_calls.alloc(data)).into()) | ||
92 | } | ||
93 | ast::ModuleItem::ExternBlock(ast) => Some(ModItems( | ||
94 | self.lower_extern_block(ast) | ||
95 | .into_iter() | ||
96 | .map(|item| match item { | ||
97 | Either::Left(func) => id(self.tree.functions.alloc(func)).into(), | ||
98 | Either::Right(statik) => id(self.tree.statics.alloc(statik)).into(), | ||
99 | }) | ||
100 | .collect::<SmallVec<_>>(), | ||
101 | )), | ||
102 | }; | 108 | }; |
103 | 109 | ||
104 | if !attrs.is_empty() { | 110 | if !attrs.is_empty() { |
@@ -110,22 +116,28 @@ impl Ctx { | |||
110 | items | 116 | items |
111 | } | 117 | } |
112 | 118 | ||
113 | fn lower_assoc_item(&mut self, item: &ast::AssocItem) -> Option<AssocItem> { | 119 | fn collect_inner_items(&mut self, container: &SyntaxNode) { |
120 | let mut inner_items = mem::replace(&mut self.tree.inner_items, FxHashMap::default()); | ||
121 | inner_items.extend( | ||
122 | container.descendants().skip(1).filter_map(ast::ModuleItem::cast).filter_map(|item| { | ||
123 | let ast_id = self.source_ast_id_map.ast_id(&item); | ||
124 | Some((ast_id, self.lower_mod_item(&item, true)?.0)) | ||
125 | }), | ||
126 | ); | ||
127 | self.tree.inner_items = inner_items; | ||
128 | } | ||
129 | |||
130 | fn lower_assoc_item(&mut self, item: &ast::ModuleItem) -> Option<AssocItem> { | ||
114 | match item { | 131 | match item { |
115 | ast::AssocItem::FnDef(ast) => { | 132 | ast::ModuleItem::FnDef(ast) => self.lower_function(ast).map(Into::into), |
116 | self.lower_function(ast).map(|data| id(self.tree.functions.alloc(data)).into()) | 133 | ast::ModuleItem::TypeAliasDef(ast) => self.lower_type_alias(ast).map(Into::into), |
117 | } | 134 | ast::ModuleItem::ConstDef(ast) => Some(self.lower_const(ast).into()), |
118 | ast::AssocItem::TypeAliasDef(ast) => { | 135 | ast::ModuleItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), |
119 | self.lower_type_alias(ast).map(|data| id(self.tree.type_aliases.alloc(data)).into()) | 136 | _ => None, |
120 | } | ||
121 | ast::AssocItem::ConstDef(ast) => { | ||
122 | let data = self.lower_const(ast); | ||
123 | Some(id(self.tree.consts.alloc(data)).into()) | ||
124 | } | ||
125 | } | 137 | } |
126 | } | 138 | } |
127 | 139 | ||
128 | fn lower_struct(&mut self, strukt: &ast::StructDef) -> Option<Struct> { | 140 | fn lower_struct(&mut self, strukt: &ast::StructDef) -> Option<FileItemTreeId<Struct>> { |
129 | let attrs = self.lower_attrs(strukt); | 141 | let attrs = self.lower_attrs(strukt); |
130 | let visibility = self.lower_visibility(strukt); | 142 | let visibility = self.lower_visibility(strukt); |
131 | let name = strukt.name()?.as_name(); | 143 | let name = strukt.name()?.as_name(); |
@@ -138,7 +150,7 @@ impl Ctx { | |||
138 | ast::StructKind::Unit => StructDefKind::Unit, | 150 | ast::StructKind::Unit => StructDefKind::Unit, |
139 | }; | 151 | }; |
140 | let res = Struct { name, attrs, visibility, generic_params, fields, ast_id, kind }; | 152 | let res = Struct { name, attrs, visibility, generic_params, fields, ast_id, kind }; |
141 | Some(res) | 153 | Some(id(self.tree.structs.alloc(res))) |
142 | } | 154 | } |
143 | 155 | ||
144 | fn lower_fields(&mut self, strukt_kind: &ast::StructKind) -> Fields { | 156 | fn lower_fields(&mut self, strukt_kind: &ast::StructKind) -> Fields { |
@@ -193,7 +205,7 @@ impl Ctx { | |||
193 | Some(res) | 205 | Some(res) |
194 | } | 206 | } |
195 | 207 | ||
196 | fn lower_union(&mut self, union: &ast::UnionDef) -> Option<Union> { | 208 | fn lower_union(&mut self, union: &ast::UnionDef) -> Option<FileItemTreeId<Union>> { |
197 | let attrs = self.lower_attrs(union); | 209 | let attrs = self.lower_attrs(union); |
198 | let visibility = self.lower_visibility(union); | 210 | let visibility = self.lower_visibility(union); |
199 | let name = union.name()?.as_name(); | 211 | let name = union.name()?.as_name(); |
@@ -206,10 +218,10 @@ impl Ctx { | |||
206 | }; | 218 | }; |
207 | let ast_id = self.source_ast_id_map.ast_id(union); | 219 | let ast_id = self.source_ast_id_map.ast_id(union); |
208 | let res = Union { name, attrs, visibility, generic_params, fields, ast_id }; | 220 | let res = Union { name, attrs, visibility, generic_params, fields, ast_id }; |
209 | Some(res) | 221 | Some(id(self.tree.unions.alloc(res))) |
210 | } | 222 | } |
211 | 223 | ||
212 | fn lower_enum(&mut self, enum_: &ast::EnumDef) -> Option<Enum> { | 224 | fn lower_enum(&mut self, enum_: &ast::EnumDef) -> Option<FileItemTreeId<Enum>> { |
213 | let attrs = self.lower_attrs(enum_); | 225 | let attrs = self.lower_attrs(enum_); |
214 | let visibility = self.lower_visibility(enum_); | 226 | let visibility = self.lower_visibility(enum_); |
215 | let name = enum_.name()?.as_name(); | 227 | let name = enum_.name()?.as_name(); |
@@ -220,7 +232,7 @@ impl Ctx { | |||
220 | }; | 232 | }; |
221 | let ast_id = self.source_ast_id_map.ast_id(enum_); | 233 | let ast_id = self.source_ast_id_map.ast_id(enum_); |
222 | let res = Enum { name, attrs, visibility, generic_params, variants, ast_id }; | 234 | let res = Enum { name, attrs, visibility, generic_params, variants, ast_id }; |
223 | Some(res) | 235 | Some(id(self.tree.enums.alloc(res))) |
224 | } | 236 | } |
225 | 237 | ||
226 | fn lower_variants(&mut self, variants: &ast::EnumVariantList) -> Range<Idx<Variant>> { | 238 | fn lower_variants(&mut self, variants: &ast::EnumVariantList) -> Range<Idx<Variant>> { |
@@ -241,7 +253,7 @@ impl Ctx { | |||
241 | Some(res) | 253 | Some(res) |
242 | } | 254 | } |
243 | 255 | ||
244 | fn lower_function(&mut self, func: &ast::FnDef) -> Option<Function> { | 256 | fn lower_function(&mut self, func: &ast::FnDef) -> Option<FileItemTreeId<Function>> { |
245 | let attrs = self.lower_attrs(func); | 257 | let attrs = self.lower_attrs(func); |
246 | let visibility = self.lower_visibility(func); | 258 | let visibility = self.lower_visibility(func); |
247 | let name = func.name()?.as_name(); | 259 | let name = func.name()?.as_name(); |
@@ -297,37 +309,42 @@ impl Ctx { | |||
297 | ast_id, | 309 | ast_id, |
298 | }; | 310 | }; |
299 | res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); | 311 | res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); |
300 | Some(res) | 312 | |
313 | Some(id(self.tree.functions.alloc(res))) | ||
301 | } | 314 | } |
302 | 315 | ||
303 | fn lower_type_alias(&mut self, type_alias: &ast::TypeAliasDef) -> Option<TypeAlias> { | 316 | fn lower_type_alias( |
317 | &mut self, | ||
318 | type_alias: &ast::TypeAliasDef, | ||
319 | ) -> Option<FileItemTreeId<TypeAlias>> { | ||
304 | let name = type_alias.name()?.as_name(); | 320 | let name = type_alias.name()?.as_name(); |
305 | let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it)); | 321 | let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it)); |
306 | let visibility = self.lower_visibility(type_alias); | 322 | let visibility = self.lower_visibility(type_alias); |
307 | let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias); | 323 | let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias); |
308 | let ast_id = self.source_ast_id_map.ast_id(type_alias); | 324 | let ast_id = self.source_ast_id_map.ast_id(type_alias); |
309 | let res = TypeAlias { name, visibility, generic_params, type_ref, ast_id }; | 325 | let res = TypeAlias { name, visibility, generic_params, type_ref, ast_id }; |
310 | Some(res) | 326 | Some(id(self.tree.type_aliases.alloc(res))) |
311 | } | 327 | } |
312 | 328 | ||
313 | fn lower_static(&mut self, static_: &ast::StaticDef) -> Option<Static> { | 329 | fn lower_static(&mut self, static_: &ast::StaticDef) -> Option<FileItemTreeId<Static>> { |
314 | let name = static_.name()?.as_name(); | 330 | let name = static_.name()?.as_name(); |
315 | let type_ref = self.lower_type_ref_opt(static_.ascribed_type()); | 331 | let type_ref = self.lower_type_ref_opt(static_.ascribed_type()); |
316 | let visibility = self.lower_visibility(static_); | 332 | let visibility = self.lower_visibility(static_); |
317 | let ast_id = self.source_ast_id_map.ast_id(static_); | 333 | let ast_id = self.source_ast_id_map.ast_id(static_); |
318 | let res = Static { name, visibility, type_ref, ast_id }; | 334 | let res = Static { name, visibility, type_ref, ast_id }; |
319 | Some(res) | 335 | Some(id(self.tree.statics.alloc(res))) |
320 | } | 336 | } |
321 | 337 | ||
322 | fn lower_const(&mut self, konst: &ast::ConstDef) -> Const { | 338 | fn lower_const(&mut self, konst: &ast::ConstDef) -> FileItemTreeId<Const> { |
323 | let name = konst.name().map(|it| it.as_name()); | 339 | let name = konst.name().map(|it| it.as_name()); |
324 | let type_ref = self.lower_type_ref_opt(konst.ascribed_type()); | 340 | let type_ref = self.lower_type_ref_opt(konst.ascribed_type()); |
325 | let visibility = self.lower_visibility(konst); | 341 | let visibility = self.lower_visibility(konst); |
326 | let ast_id = self.source_ast_id_map.ast_id(konst); | 342 | let ast_id = self.source_ast_id_map.ast_id(konst); |
327 | Const { name, visibility, type_ref, ast_id } | 343 | let res = Const { name, visibility, type_ref, ast_id }; |
344 | id(self.tree.consts.alloc(res)) | ||
328 | } | 345 | } |
329 | 346 | ||
330 | fn lower_module(&mut self, module: &ast::Module) -> Option<Mod> { | 347 | fn lower_module(&mut self, module: &ast::Module) -> Option<FileItemTreeId<Mod>> { |
331 | let name = module.name()?.as_name(); | 348 | let name = module.name()?.as_name(); |
332 | let visibility = self.lower_visibility(module); | 349 | let visibility = self.lower_visibility(module); |
333 | let kind = if module.semicolon_token().is_some() { | 350 | let kind = if module.semicolon_token().is_some() { |
@@ -338,7 +355,7 @@ impl Ctx { | |||
338 | .item_list() | 355 | .item_list() |
339 | .map(|list| { | 356 | .map(|list| { |
340 | list.items() | 357 | list.items() |
341 | .flat_map(|item| self.lower_mod_item(&item)) | 358 | .flat_map(|item| self.lower_mod_item(&item, false)) |
342 | .flat_map(|items| items.0) | 359 | .flat_map(|items| items.0) |
343 | .collect() | 360 | .collect() |
344 | }) | 361 | }) |
@@ -349,90 +366,101 @@ impl Ctx { | |||
349 | } | 366 | } |
350 | }; | 367 | }; |
351 | let ast_id = self.source_ast_id_map.ast_id(module); | 368 | let ast_id = self.source_ast_id_map.ast_id(module); |
352 | Some(Mod { name, visibility, kind, ast_id }) | 369 | let res = Mod { name, visibility, kind, ast_id }; |
370 | Some(id(self.tree.mods.alloc(res))) | ||
353 | } | 371 | } |
354 | 372 | ||
355 | fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<Trait> { | 373 | fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<FileItemTreeId<Trait>> { |
356 | let name = trait_def.name()?.as_name(); | 374 | let name = trait_def.name()?.as_name(); |
357 | let visibility = self.lower_visibility(trait_def); | 375 | let visibility = self.lower_visibility(trait_def); |
358 | let generic_params = self.lower_generic_params(GenericsOwner::Trait(trait_def), trait_def); | 376 | let generic_params = self.lower_generic_params(GenericsOwner::Trait(trait_def), trait_def); |
359 | let auto = trait_def.auto_token().is_some(); | 377 | let auto = trait_def.auto_token().is_some(); |
360 | let items = trait_def.item_list().map(|list| { | 378 | let items = trait_def.item_list().map(|list| { |
361 | // FIXME: Does not handle macros | 379 | list.items() |
362 | list.assoc_items().flat_map(|item| self.lower_assoc_item(&item)).collect() | 380 | .flat_map(|item| { |
381 | self.collect_inner_items(item.syntax()); | ||
382 | self.lower_assoc_item(&item) | ||
383 | }) | ||
384 | .collect() | ||
363 | }); | 385 | }); |
364 | let ast_id = self.source_ast_id_map.ast_id(trait_def); | 386 | let ast_id = self.source_ast_id_map.ast_id(trait_def); |
365 | Some(Trait { | 387 | let res = Trait { |
366 | name, | 388 | name, |
367 | visibility, | 389 | visibility, |
368 | generic_params, | 390 | generic_params, |
369 | auto, | 391 | auto, |
370 | items: items.unwrap_or_default(), | 392 | items: items.unwrap_or_default(), |
371 | ast_id, | 393 | ast_id, |
372 | }) | 394 | }; |
395 | Some(id(self.tree.traits.alloc(res))) | ||
373 | } | 396 | } |
374 | 397 | ||
375 | fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<Impl> { | 398 | fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<FileItemTreeId<Impl>> { |
376 | let generic_params = self.lower_generic_params(GenericsOwner::Impl, impl_def); | 399 | let generic_params = self.lower_generic_params(GenericsOwner::Impl, impl_def); |
377 | let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr)); | 400 | let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr)); |
378 | let target_type = self.lower_type_ref(&impl_def.target_type()?); | 401 | let target_type = self.lower_type_ref(&impl_def.target_type()?); |
379 | let is_negative = impl_def.excl_token().is_some(); | 402 | let is_negative = impl_def.excl_token().is_some(); |
403 | |||
404 | // We cannot use `assoc_items()` here as that does not include macro calls. | ||
380 | let items = impl_def | 405 | let items = impl_def |
381 | .item_list()? | 406 | .item_list()? |
382 | .assoc_items() | 407 | .items() |
383 | .filter_map(|item| self.lower_assoc_item(&item)) | 408 | .filter_map(|item| { |
409 | self.collect_inner_items(item.syntax()); | ||
410 | let assoc = self.lower_assoc_item(&item)?; | ||
411 | Some(assoc) | ||
412 | }) | ||
384 | .collect(); | 413 | .collect(); |
385 | let ast_id = self.source_ast_id_map.ast_id(impl_def); | 414 | let ast_id = self.source_ast_id_map.ast_id(impl_def); |
386 | Some(Impl { generic_params, target_trait, target_type, is_negative, items, ast_id }) | 415 | let res = Impl { generic_params, target_trait, target_type, is_negative, items, ast_id }; |
416 | Some(id(self.tree.impls.alloc(res))) | ||
387 | } | 417 | } |
388 | 418 | ||
389 | fn lower_use(&mut self, use_item: &ast::UseItem) -> Vec<Import> { | 419 | fn lower_use(&mut self, use_item: &ast::UseItem) -> Vec<FileItemTreeId<Import>> { |
390 | // FIXME: cfg_attr | 420 | // FIXME: cfg_attr |
391 | let is_prelude = use_item.has_atom_attr("prelude_import"); | 421 | let is_prelude = use_item.has_atom_attr("prelude_import"); |
392 | let visibility = self.lower_visibility(use_item); | 422 | let visibility = self.lower_visibility(use_item); |
423 | let ast_id = self.source_ast_id_map.ast_id(use_item); | ||
393 | 424 | ||
394 | // Every use item can expand to many `Import`s. | 425 | // Every use item can expand to many `Import`s. |
395 | let mut imports = Vec::new(); | 426 | let mut imports = Vec::new(); |
427 | let tree = &mut self.tree; | ||
396 | ModPath::expand_use_item( | 428 | ModPath::expand_use_item( |
397 | InFile::new(self.file, use_item.clone()), | 429 | InFile::new(self.file, use_item.clone()), |
398 | &self.hygiene, | 430 | &self.hygiene, |
399 | |path, _tree, is_glob, alias| { | 431 | |path, _tree, is_glob, alias| { |
400 | imports.push(Import { | 432 | imports.push(id(tree.imports.alloc(Import { |
401 | path, | 433 | path, |
402 | alias, | 434 | alias, |
403 | visibility: visibility.clone(), | 435 | visibility: visibility.clone(), |
404 | is_glob, | 436 | is_glob, |
405 | is_prelude, | 437 | is_prelude, |
406 | is_extern_crate: false, | 438 | ast_id, |
407 | is_macro_use: false, | 439 | }))); |
408 | }); | ||
409 | }, | 440 | }, |
410 | ); | 441 | ); |
411 | 442 | ||
412 | imports | 443 | imports |
413 | } | 444 | } |
414 | 445 | ||
415 | fn lower_extern_crate(&mut self, extern_crate: &ast::ExternCrateItem) -> Option<Import> { | 446 | fn lower_extern_crate( |
447 | &mut self, | ||
448 | extern_crate: &ast::ExternCrateItem, | ||
449 | ) -> Option<FileItemTreeId<ExternCrate>> { | ||
416 | let path = ModPath::from_name_ref(&extern_crate.name_ref()?); | 450 | let path = ModPath::from_name_ref(&extern_crate.name_ref()?); |
417 | let alias = extern_crate.alias().map(|a| { | 451 | let alias = extern_crate.alias().map(|a| { |
418 | a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) | 452 | a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) |
419 | }); | 453 | }); |
420 | let visibility = self.lower_visibility(extern_crate); | 454 | let visibility = self.lower_visibility(extern_crate); |
455 | let ast_id = self.source_ast_id_map.ast_id(extern_crate); | ||
421 | // FIXME: cfg_attr | 456 | // FIXME: cfg_attr |
422 | let is_macro_use = extern_crate.has_atom_attr("macro_use"); | 457 | let is_macro_use = extern_crate.has_atom_attr("macro_use"); |
423 | 458 | ||
424 | Some(Import { | 459 | let res = ExternCrate { path, alias, visibility, is_macro_use, ast_id }; |
425 | path, | 460 | Some(id(self.tree.extern_crates.alloc(res))) |
426 | alias, | ||
427 | visibility, | ||
428 | is_glob: false, | ||
429 | is_prelude: false, | ||
430 | is_extern_crate: true, | ||
431 | is_macro_use, | ||
432 | }) | ||
433 | } | 461 | } |
434 | 462 | ||
435 | fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<MacroCall> { | 463 | fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { |
436 | let name = m.name().map(|it| it.as_name()); | 464 | let name = m.name().map(|it| it.as_name()); |
437 | let attrs = Attrs::new(m, &self.hygiene); | 465 | let attrs = Attrs::new(m, &self.hygiene); |
438 | let path = ModPath::from_src(m.path()?, &self.hygiene)?; | 466 | let path = ModPath::from_src(m.path()?, &self.hygiene)?; |
@@ -455,15 +483,26 @@ impl Ctx { | |||
455 | }; | 483 | }; |
456 | 484 | ||
457 | let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); | 485 | let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); |
458 | Some(MacroCall { name, path, is_export, is_builtin, is_local_inner, ast_id }) | 486 | let res = MacroCall { name, path, is_export, is_builtin, is_local_inner, ast_id }; |
487 | Some(id(self.tree.macro_calls.alloc(res))) | ||
459 | } | 488 | } |
460 | 489 | ||
461 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<Either<Function, Static>> { | 490 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { |
462 | block.extern_item_list().map_or(Vec::new(), |list| { | 491 | block.extern_item_list().map_or(Vec::new(), |list| { |
463 | list.extern_items() | 492 | list.extern_items() |
464 | .filter_map(|item| match item { | 493 | .filter_map(|item| { |
465 | ast::ExternItem::FnDef(ast) => self.lower_function(&ast).map(Either::Left), | 494 | self.collect_inner_items(item.syntax()); |
466 | ast::ExternItem::StaticDef(ast) => self.lower_static(&ast).map(Either::Right), | 495 | let id = match item { |
496 | ast::ExternItem::FnDef(ast) => { | ||
497 | let func = self.lower_function(&ast)?; | ||
498 | func.into() | ||
499 | } | ||
500 | ast::ExternItem::StaticDef(ast) => { | ||
501 | let statik = self.lower_static(&ast)?; | ||
502 | statik.into() | ||
503 | } | ||
504 | }; | ||
505 | Some(id) | ||
467 | }) | 506 | }) |
468 | .collect() | 507 | .collect() |
469 | }) | 508 | }) |