diff options
Diffstat (limited to 'crates/ra_hir_def/src/item_tree.rs')
-rw-r--r-- | crates/ra_hir_def/src/item_tree.rs | 235 |
1 files changed, 206 insertions, 29 deletions
diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index 7e81bc178..3ea6e10c9 100644 --- a/crates/ra_hir_def/src/item_tree.rs +++ b/crates/ra_hir_def/src/item_tree.rs | |||
@@ -4,7 +4,7 @@ use hir_expand::{ | |||
4 | ast_id_map::{AstIdMap, FileAstId}, | 4 | ast_id_map::{AstIdMap, FileAstId}, |
5 | hygiene::Hygiene, | 5 | hygiene::Hygiene, |
6 | name::{name, AsName, Name}, | 6 | name::{name, AsName, Name}, |
7 | HirFileId, | 7 | HirFileId, InFile, |
8 | }; | 8 | }; |
9 | use ra_arena::{Arena, Idx, RawId}; | 9 | use ra_arena::{Arena, Idx, RawId}; |
10 | use ra_syntax::{ast, match_ast}; | 10 | use ra_syntax::{ast, match_ast}; |
@@ -12,17 +12,20 @@ use ra_syntax::{ast, match_ast}; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | attr::Attrs, | 13 | attr::Attrs, |
14 | db::DefDatabase, | 14 | db::DefDatabase, |
15 | generics::GenericParams, | 15 | generics, |
16 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path}, | 16 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path}, |
17 | type_ref::{Mutability, TypeBound, TypeRef}, | 17 | type_ref::{Mutability, TypeBound, TypeRef}, |
18 | visibility::RawVisibility, | 18 | visibility::RawVisibility, |
19 | }; | 19 | }; |
20 | use ast::{AstNode, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner}; | 20 | use ast::{AstNode, AttrsOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner}; |
21 | use either::Either; | ||
22 | use smallvec::SmallVec; | ||
21 | use std::{ | 23 | use std::{ |
22 | ops::{Index, Range}, | 24 | ops::{Index, Range}, |
23 | sync::Arc, | 25 | sync::Arc, |
24 | }; | 26 | }; |
25 | 27 | ||
28 | /// The item tree of a source file. | ||
26 | #[derive(Debug, Default, Eq, PartialEq)] | 29 | #[derive(Debug, Default, Eq, PartialEq)] |
27 | pub struct ItemTree { | 30 | pub struct ItemTree { |
28 | top_level: Vec<ModItem>, | 31 | top_level: Vec<ModItem>, |
@@ -70,6 +73,7 @@ impl ItemTree { | |||
70 | let ctx = Ctx { | 73 | let ctx = Ctx { |
71 | tree: ItemTree::default(), | 74 | tree: ItemTree::default(), |
72 | hygiene: Hygiene::new(db.upcast(), file_id), | 75 | hygiene: Hygiene::new(db.upcast(), file_id), |
76 | file: file_id, | ||
73 | source_ast_id_map: map, | 77 | source_ast_id_map: map, |
74 | body_ctx: crate::body::LowerCtx::new(db, file_id), | 78 | body_ctx: crate::body::LowerCtx::new(db, file_id), |
75 | }; | 79 | }; |
@@ -115,6 +119,7 @@ impl_index!( | |||
115 | exprs: Expr, | 119 | exprs: Expr, |
116 | ); | 120 | ); |
117 | 121 | ||
122 | /// A desugared `extern crate` or `use` import. | ||
118 | #[derive(Debug, Eq, PartialEq)] | 123 | #[derive(Debug, Eq, PartialEq)] |
119 | pub struct Import { | 124 | pub struct Import { |
120 | pub path: ModPath, | 125 | pub path: ModPath, |
@@ -131,11 +136,12 @@ pub struct Function { | |||
131 | pub name: Name, | 136 | pub name: Name, |
132 | pub attrs: Attrs, | 137 | pub attrs: Attrs, |
133 | pub visibility: RawVisibility, | 138 | pub visibility: RawVisibility, |
134 | pub generic_params: GenericParams, | 139 | pub generic_params: generics::GenericParams, |
135 | pub has_self_param: bool, | 140 | pub has_self_param: bool, |
136 | pub params: Vec<TypeRef>, | 141 | pub params: Vec<TypeRef>, |
137 | pub ret_type: TypeRef, | 142 | pub ret_type: TypeRef, |
138 | pub ast: FileAstId<ast::FnDef>, | 143 | pub ast: FileAstId<ast::FnDef>, |
144 | // FIXME inner items | ||
139 | } | 145 | } |
140 | 146 | ||
141 | #[derive(Debug, Eq, PartialEq)] | 147 | #[derive(Debug, Eq, PartialEq)] |
@@ -143,7 +149,7 @@ pub struct Struct { | |||
143 | pub name: Name, | 149 | pub name: Name, |
144 | pub attrs: Attrs, | 150 | pub attrs: Attrs, |
145 | pub visibility: RawVisibility, | 151 | pub visibility: RawVisibility, |
146 | pub generic_params: GenericParams, | 152 | pub generic_params: generics::GenericParams, |
147 | pub fields: Fields, | 153 | pub fields: Fields, |
148 | pub ast: FileAstId<ast::StructDef>, | 154 | pub ast: FileAstId<ast::StructDef>, |
149 | } | 155 | } |
@@ -153,7 +159,7 @@ pub struct Union { | |||
153 | pub name: Name, | 159 | pub name: Name, |
154 | pub attrs: Attrs, | 160 | pub attrs: Attrs, |
155 | pub visibility: RawVisibility, | 161 | pub visibility: RawVisibility, |
156 | pub generic_params: GenericParams, | 162 | pub generic_params: generics::GenericParams, |
157 | pub fields: Fields, | 163 | pub fields: Fields, |
158 | } | 164 | } |
159 | 165 | ||
@@ -162,7 +168,7 @@ pub struct Enum { | |||
162 | pub name: Name, | 168 | pub name: Name, |
163 | pub attrs: Attrs, | 169 | pub attrs: Attrs, |
164 | pub visibility: RawVisibility, | 170 | pub visibility: RawVisibility, |
165 | pub generic_params: GenericParams, | 171 | pub generic_params: generics::GenericParams, |
166 | pub variants: Range<Idx<Variant>>, | 172 | pub variants: Range<Idx<Variant>>, |
167 | } | 173 | } |
168 | 174 | ||
@@ -185,14 +191,14 @@ pub struct Static { | |||
185 | pub struct Trait { | 191 | pub struct Trait { |
186 | pub name: Name, | 192 | pub name: Name, |
187 | pub visibility: RawVisibility, | 193 | pub visibility: RawVisibility, |
188 | pub generic_params: GenericParams, | 194 | pub generic_params: generics::GenericParams, |
189 | pub auto: bool, | 195 | pub auto: bool, |
190 | pub items: Vec<AssocItem>, | 196 | pub items: Vec<AssocItem>, |
191 | } | 197 | } |
192 | 198 | ||
193 | #[derive(Debug, Eq, PartialEq)] | 199 | #[derive(Debug, Eq, PartialEq)] |
194 | pub struct Impl { | 200 | pub struct Impl { |
195 | pub generic_params: GenericParams, | 201 | pub generic_params: generics::GenericParams, |
196 | pub target_trait: Option<TypeRef>, | 202 | pub target_trait: Option<TypeRef>, |
197 | pub target_type: TypeRef, | 203 | pub target_type: TypeRef, |
198 | pub is_negative: bool, | 204 | pub is_negative: bool, |
@@ -203,7 +209,7 @@ pub struct Impl { | |||
203 | pub struct TypeAlias { | 209 | pub struct TypeAlias { |
204 | pub name: Name, | 210 | pub name: Name, |
205 | pub visibility: RawVisibility, | 211 | pub visibility: RawVisibility, |
206 | pub generic_params: GenericParams, | 212 | pub generic_params: generics::GenericParams, |
207 | pub type_ref: Option<TypeRef>, | 213 | pub type_ref: Option<TypeRef>, |
208 | } | 214 | } |
209 | 215 | ||
@@ -218,8 +224,12 @@ pub struct Mod { | |||
218 | pub struct MacroCall { | 224 | pub struct MacroCall { |
219 | pub name: Option<Name>, | 225 | pub name: Option<Name>, |
220 | pub path: ModPath, | 226 | pub path: ModPath, |
221 | pub export: bool, | 227 | /// Has `#[macro_export]`. |
222 | pub builtin: bool, | 228 | pub is_export: bool, |
229 | /// Has `#[macro_export(local_inner_macros)]`. | ||
230 | pub is_local_inner: bool, | ||
231 | /// Has `#[rustc_builtin_macro]`. | ||
232 | pub is_builtin: bool, | ||
223 | pub ast_id: FileAstId<ast::MacroCall>, | 233 | pub ast_id: FileAstId<ast::MacroCall>, |
224 | } | 234 | } |
225 | 235 | ||
@@ -307,20 +317,36 @@ pub struct Field { | |||
307 | pub visibility: RawVisibility, | 317 | pub visibility: RawVisibility, |
308 | } | 318 | } |
309 | 319 | ||
320 | struct ModItems(SmallVec<[ModItem; 1]>); | ||
321 | |||
322 | impl<T> From<T> for ModItems | ||
323 | where | ||
324 | T: Into<ModItem>, | ||
325 | { | ||
326 | fn from(t: T) -> Self { | ||
327 | ModItems(SmallVec::from_buf([t.into(); 1])) | ||
328 | } | ||
329 | } | ||
330 | |||
310 | struct Ctx { | 331 | struct Ctx { |
311 | tree: ItemTree, | 332 | tree: ItemTree, |
312 | hygiene: Hygiene, | 333 | hygiene: Hygiene, |
334 | file: HirFileId, | ||
313 | source_ast_id_map: Arc<AstIdMap>, | 335 | source_ast_id_map: Arc<AstIdMap>, |
314 | body_ctx: crate::body::LowerCtx, | 336 | body_ctx: crate::body::LowerCtx, |
315 | } | 337 | } |
316 | 338 | ||
317 | impl Ctx { | 339 | impl Ctx { |
318 | fn lower(mut self, item_owner: &dyn ModuleItemOwner) -> ItemTree { | 340 | fn lower(mut self, item_owner: &dyn ModuleItemOwner) -> ItemTree { |
319 | self.tree.top_level = item_owner.items().flat_map(|item| self.lower_item(&item)).collect(); | 341 | self.tree.top_level = item_owner |
342 | .items() | ||
343 | .flat_map(|item| self.lower_mod_item(&item)) | ||
344 | .flat_map(|items| items.0) | ||
345 | .collect(); | ||
320 | self.tree | 346 | self.tree |
321 | } | 347 | } |
322 | 348 | ||
323 | fn lower_item(&mut self, item: &ast::ModuleItem) -> Option<ModItem> { | 349 | fn lower_mod_item(&mut self, item: &ast::ModuleItem) -> Option<ModItems> { |
324 | match item { | 350 | match item { |
325 | ast::ModuleItem::StructDef(ast) => { | 351 | ast::ModuleItem::StructDef(ast) => { |
326 | self.lower_struct(ast).map(|data| self.tree.structs.alloc(data).into()) | 352 | self.lower_struct(ast).map(|data| self.tree.structs.alloc(data).into()) |
@@ -347,12 +373,48 @@ impl Ctx { | |||
347 | ast::ModuleItem::Module(ast) => { | 373 | ast::ModuleItem::Module(ast) => { |
348 | self.lower_module(ast).map(|data| self.tree.mods.alloc(data).into()) | 374 | self.lower_module(ast).map(|data| self.tree.mods.alloc(data).into()) |
349 | } | 375 | } |
350 | ast::ModuleItem::TraitDef(_) => todo!(), | 376 | ast::ModuleItem::TraitDef(ast) => { |
351 | ast::ModuleItem::ImplDef(_) => todo!(), | 377 | self.lower_trait(ast).map(|data| self.tree.traits.alloc(data).into()) |
352 | ast::ModuleItem::UseItem(_) => todo!(), | 378 | } |
353 | ast::ModuleItem::ExternCrateItem(_) => todo!(), | 379 | ast::ModuleItem::ImplDef(ast) => { |
354 | ast::ModuleItem::MacroCall(_) => todo!(), | 380 | self.lower_impl(ast).map(|data| self.tree.impls.alloc(data).into()) |
355 | ast::ModuleItem::ExternBlock(_) => todo!(), | 381 | } |
382 | ast::ModuleItem::UseItem(ast) => Some(ModItems( | ||
383 | self.lower_use(ast) | ||
384 | .into_iter() | ||
385 | .map(|data| self.tree.imports.alloc(data).into()) | ||
386 | .collect::<SmallVec<_>>(), | ||
387 | )), | ||
388 | ast::ModuleItem::ExternCrateItem(ast) => { | ||
389 | self.lower_extern_crate(ast).map(|data| self.tree.imports.alloc(data).into()) | ||
390 | } | ||
391 | ast::ModuleItem::MacroCall(ast) => { | ||
392 | self.lower_macro_call(ast).map(|data| self.tree.macro_calls.alloc(data).into()) | ||
393 | } | ||
394 | ast::ModuleItem::ExternBlock(ast) => Some(ModItems( | ||
395 | self.lower_extern_block(ast) | ||
396 | .into_iter() | ||
397 | .map(|item| match item { | ||
398 | Either::Left(func) => self.tree.functions.alloc(func).into(), | ||
399 | Either::Right(statik) => self.tree.statics.alloc(statik).into(), | ||
400 | }) | ||
401 | .collect::<SmallVec<_>>(), | ||
402 | )), | ||
403 | } | ||
404 | } | ||
405 | |||
406 | fn lower_assoc_item(&mut self, item: &ast::AssocItem) -> Option<AssocItem> { | ||
407 | match item { | ||
408 | ast::AssocItem::FnDef(ast) => { | ||
409 | self.lower_function(ast).map(|data| self.tree.functions.alloc(data).into()) | ||
410 | } | ||
411 | ast::AssocItem::TypeAliasDef(ast) => { | ||
412 | self.lower_type_alias(ast).map(|data| self.tree.type_aliases.alloc(data).into()) | ||
413 | } | ||
414 | ast::AssocItem::ConstDef(ast) => { | ||
415 | let data = self.lower_const(ast); | ||
416 | Some(self.tree.consts.alloc(data).into()) | ||
417 | } | ||
356 | } | 418 | } |
357 | } | 419 | } |
358 | 420 | ||
@@ -385,7 +447,7 @@ impl Ctx { | |||
385 | let start = self.next_field_idx(); | 447 | let start = self.next_field_idx(); |
386 | for field in fields.fields() { | 448 | for field in fields.fields() { |
387 | if let Some(data) = self.lower_record_field(&field) { | 449 | if let Some(data) = self.lower_record_field(&field) { |
388 | let idx = self.tree.fields.alloc(data); | 450 | self.tree.fields.alloc(data); |
389 | } | 451 | } |
390 | } | 452 | } |
391 | let end = self.next_field_idx(); | 453 | let end = self.next_field_idx(); |
@@ -404,7 +466,7 @@ impl Ctx { | |||
404 | let start = self.next_field_idx(); | 466 | let start = self.next_field_idx(); |
405 | for (i, field) in fields.fields().enumerate() { | 467 | for (i, field) in fields.fields().enumerate() { |
406 | if let Some(data) = self.lower_tuple_field(i, &field) { | 468 | if let Some(data) = self.lower_tuple_field(i, &field) { |
407 | let idx = self.tree.fields.alloc(data); | 469 | self.tree.fields.alloc(data); |
408 | } | 470 | } |
409 | } | 471 | } |
410 | let end = self.next_field_idx(); | 472 | let end = self.next_field_idx(); |
@@ -451,7 +513,7 @@ impl Ctx { | |||
451 | let start = self.next_variant_idx(); | 513 | let start = self.next_variant_idx(); |
452 | for variant in variants.variants() { | 514 | for variant in variants.variants() { |
453 | if let Some(data) = self.lower_variant(&variant) { | 515 | if let Some(data) = self.lower_variant(&variant) { |
454 | let idx = self.tree.variants.alloc(data); | 516 | self.tree.variants.alloc(data); |
455 | } | 517 | } |
456 | } | 518 | } |
457 | let end = self.next_variant_idx(); | 519 | let end = self.next_variant_idx(); |
@@ -551,14 +613,129 @@ impl Ctx { | |||
551 | fn lower_module(&mut self, module: &ast::Module) -> Option<Mod> { | 613 | fn lower_module(&mut self, module: &ast::Module) -> Option<Mod> { |
552 | let name = module.name()?.as_name(); | 614 | let name = module.name()?.as_name(); |
553 | let visibility = self.lower_visibility(module); | 615 | let visibility = self.lower_visibility(module); |
554 | let items = module | 616 | let items = module.item_list().map(move |list| { |
555 | .item_list() | 617 | list.items() |
556 | .map(move |list| list.items().flat_map(move |item| self.lower_item(&item)).collect()); | 618 | .flat_map(move |item| self.lower_mod_item(&item)) |
619 | .flat_map(|items| items.0) | ||
620 | .collect() | ||
621 | }); | ||
557 | Some(Mod { name, visibility, items: items.unwrap_or_default() }) | 622 | Some(Mod { name, visibility, items: items.unwrap_or_default() }) |
558 | } | 623 | } |
559 | 624 | ||
560 | fn lower_generic_params(&mut self, _item: &impl ast::TypeParamsOwner) -> GenericParams { | 625 | fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<Trait> { |
561 | None.unwrap() | 626 | let name = trait_def.name()?.as_name(); |
627 | let visibility = self.lower_visibility(trait_def); | ||
628 | let generic_params = self.lower_generic_params(trait_def); | ||
629 | let auto = trait_def.auto_token().is_some(); | ||
630 | let items = trait_def.item_list().map(move |list| { | ||
631 | // FIXME: Does not handle macros | ||
632 | list.assoc_items().flat_map(move |item| self.lower_assoc_item(&item)).collect() | ||
633 | }); | ||
634 | Some(Trait { name, visibility, generic_params, auto, items: items.unwrap_or_default() }) | ||
635 | } | ||
636 | |||
637 | fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<Impl> { | ||
638 | let generic_params = self.lower_generic_params(impl_def); | ||
639 | let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr)); | ||
640 | let target_type = self.lower_type_ref(&impl_def.target_type()?); | ||
641 | let is_negative = impl_def.excl_token().is_some(); | ||
642 | let items = impl_def | ||
643 | .item_list()? | ||
644 | .assoc_items() | ||
645 | .filter_map(|item| self.lower_assoc_item(&item)) | ||
646 | .collect(); | ||
647 | Some(Impl { generic_params, target_trait, target_type, is_negative, items }) | ||
648 | } | ||
649 | |||
650 | fn lower_use(&mut self, use_item: &ast::UseItem) -> Vec<Import> { | ||
651 | // FIXME: cfg_attr | ||
652 | let is_prelude = use_item.has_atom_attr("prelude_import"); | ||
653 | let visibility = self.lower_visibility(use_item); | ||
654 | |||
655 | // Every use item can expand to many `Import`s. | ||
656 | let mut imports = Vec::new(); | ||
657 | ModPath::expand_use_item( | ||
658 | InFile::new(self.file, use_item.clone()), | ||
659 | &self.hygiene, | ||
660 | |path, _tree, is_glob, alias| { | ||
661 | imports.push(Import { | ||
662 | path, | ||
663 | alias, | ||
664 | visibility: visibility.clone(), | ||
665 | is_glob, | ||
666 | is_prelude, | ||
667 | is_extern_crate: false, | ||
668 | is_macro_use: false, | ||
669 | }); | ||
670 | }, | ||
671 | ); | ||
672 | |||
673 | imports | ||
674 | } | ||
675 | |||
676 | fn lower_extern_crate(&mut self, extern_crate: &ast::ExternCrateItem) -> Option<Import> { | ||
677 | let path = ModPath::from_name_ref(&extern_crate.name_ref()?); | ||
678 | let alias = extern_crate.alias().map(|a| { | ||
679 | a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) | ||
680 | }); | ||
681 | let visibility = self.lower_visibility(extern_crate); | ||
682 | // FIXME: cfg_attr | ||
683 | let is_macro_use = extern_crate.has_atom_attr("macro_use"); | ||
684 | |||
685 | Some(Import { | ||
686 | path, | ||
687 | alias, | ||
688 | visibility, | ||
689 | is_glob: false, | ||
690 | is_prelude: false, | ||
691 | is_extern_crate: true, | ||
692 | is_macro_use, | ||
693 | }) | ||
694 | } | ||
695 | |||
696 | fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<MacroCall> { | ||
697 | let name = m.name().map(|it| it.as_name()); | ||
698 | let attrs = Attrs::new(m, &self.hygiene); | ||
699 | let path = ModPath::from_src(m.path()?, &self.hygiene)?; | ||
700 | |||
701 | let ast_id = self.source_ast_id_map.ast_id(m); | ||
702 | |||
703 | // FIXME: cfg_attr | ||
704 | let export_attr = attrs.by_key("macro_export"); | ||
705 | |||
706 | let is_export = export_attr.exists(); | ||
707 | let is_local_inner = if is_export { | ||
708 | export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it { | ||
709 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { | ||
710 | ident.text.contains("local_inner_macros") | ||
711 | } | ||
712 | _ => false, | ||
713 | }) | ||
714 | } else { | ||
715 | false | ||
716 | }; | ||
717 | |||
718 | let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); | ||
719 | Some(MacroCall { name, path, is_export, is_builtin, is_local_inner, ast_id }) | ||
720 | } | ||
721 | |||
722 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<Either<Function, Static>> { | ||
723 | block.extern_item_list().map_or(Vec::new(), |list| { | ||
724 | list.extern_items() | ||
725 | .filter_map(|item| match item { | ||
726 | ast::ExternItem::FnDef(ast) => self.lower_function(&ast).map(Either::Left), | ||
727 | ast::ExternItem::StaticDef(ast) => self.lower_static(&ast).map(Either::Right), | ||
728 | }) | ||
729 | .collect() | ||
730 | }) | ||
731 | } | ||
732 | |||
733 | fn lower_generic_params( | ||
734 | &mut self, | ||
735 | _item: &impl ast::TypeParamsOwner, | ||
736 | ) -> generics::GenericParams { | ||
737 | // TODO | ||
738 | generics::GenericParams { types: Arena::new(), where_predicates: Vec::new() } | ||
562 | } | 739 | } |
563 | 740 | ||
564 | fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { | 741 | fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { |
@@ -583,7 +760,7 @@ impl Ctx { | |||
583 | } | 760 | } |
584 | 761 | ||
585 | fn desugar_future_path(orig: TypeRef) -> Path { | 762 | fn desugar_future_path(orig: TypeRef) -> Path { |
586 | let path = path![std::future::Future]; | 763 | let path = path![core::future::Future]; |
587 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); | 764 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); |
588 | let mut last = GenericArgs::empty(); | 765 | let mut last = GenericArgs::empty(); |
589 | let binding = | 766 | let binding = |