diff options
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r-- | crates/ra_hir_def/src/item_tree.rs | 135 |
1 files changed, 108 insertions, 27 deletions
diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index 9dee4f43d..71b415802 100644 --- a/crates/ra_hir_def/src/item_tree.rs +++ b/crates/ra_hir_def/src/item_tree.rs | |||
@@ -19,6 +19,7 @@ use crate::{ | |||
19 | }; | 19 | }; |
20 | use ast::{AstNode, AttrsOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner}; | 20 | use ast::{AstNode, AttrsOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner}; |
21 | use either::Either; | 21 | use either::Either; |
22 | use rustc_hash::FxHashMap; | ||
22 | use smallvec::SmallVec; | 23 | use smallvec::SmallVec; |
23 | use std::{ | 24 | use std::{ |
24 | ops::{Index, Range}, | 25 | ops::{Index, Range}, |
@@ -29,6 +30,10 @@ use std::{ | |||
29 | #[derive(Debug, Default, Eq, PartialEq)] | 30 | #[derive(Debug, Default, Eq, PartialEq)] |
30 | pub struct ItemTree { | 31 | pub struct ItemTree { |
31 | top_level: Vec<ModItem>, | 32 | top_level: Vec<ModItem>, |
33 | top_attrs: Attrs, | ||
34 | attrs: FxHashMap<ModItem, Attrs>, | ||
35 | empty_attrs: Attrs, | ||
36 | |||
32 | imports: Arena<Import>, | 37 | imports: Arena<Import>, |
33 | functions: Arena<Function>, | 38 | functions: Arena<Function>, |
34 | structs: Arena<Struct>, | 39 | structs: Arena<Struct>, |
@@ -48,12 +53,15 @@ pub struct ItemTree { | |||
48 | 53 | ||
49 | impl ItemTree { | 54 | impl ItemTree { |
50 | pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { | 55 | pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { |
56 | let _p = ra_prof::profile("item_tree_query"); | ||
51 | let syntax = if let Some(node) = db.parse_or_expand(file_id) { | 57 | let syntax = if let Some(node) = db.parse_or_expand(file_id) { |
52 | node | 58 | node |
53 | } else { | 59 | } else { |
54 | return Default::default(); | 60 | return Default::default(); |
55 | }; | 61 | }; |
56 | 62 | ||
63 | let hygiene = Hygiene::new(db.upcast(), file_id); | ||
64 | let mut top_attrs = None; | ||
57 | let (macro_storage, file_storage); | 65 | let (macro_storage, file_storage); |
58 | let item_owner = match_ast! { | 66 | let item_owner = match_ast! { |
59 | match syntax { | 67 | match syntax { |
@@ -62,6 +70,7 @@ impl ItemTree { | |||
62 | ¯o_storage as &dyn ModuleItemOwner | 70 | ¯o_storage as &dyn ModuleItemOwner |
63 | }, | 71 | }, |
64 | ast::SourceFile(file) => { | 72 | ast::SourceFile(file) => { |
73 | top_attrs = Some(Attrs::new(&file, &hygiene)); | ||
65 | file_storage = file; | 74 | file_storage = file; |
66 | &file_storage | 75 | &file_storage |
67 | }, | 76 | }, |
@@ -70,13 +79,14 @@ impl ItemTree { | |||
70 | }; | 79 | }; |
71 | 80 | ||
72 | let map = db.ast_id_map(file_id); | 81 | let map = db.ast_id_map(file_id); |
73 | let ctx = Ctx { | 82 | let mut ctx = Ctx { |
74 | tree: ItemTree::default(), | 83 | tree: ItemTree::default(), |
75 | hygiene: Hygiene::new(db.upcast(), file_id), | 84 | hygiene, |
76 | file: file_id, | 85 | file: file_id, |
77 | source_ast_id_map: map, | 86 | source_ast_id_map: map, |
78 | body_ctx: crate::body::LowerCtx::new(db, file_id), | 87 | body_ctx: crate::body::LowerCtx::new(db, file_id), |
79 | }; | 88 | }; |
89 | ctx.tree.top_attrs = top_attrs.unwrap_or_default(); | ||
80 | Arc::new(ctx.lower(item_owner)) | 90 | Arc::new(ctx.lower(item_owner)) |
81 | } | 91 | } |
82 | 92 | ||
@@ -85,6 +95,15 @@ impl ItemTree { | |||
85 | pub fn top_level_items(&self) -> &[ModItem] { | 95 | pub fn top_level_items(&self) -> &[ModItem] { |
86 | &self.top_level | 96 | &self.top_level |
87 | } | 97 | } |
98 | |||
99 | /// Returns the inner attributes of the source file. | ||
100 | pub fn top_level_attrs(&self) -> &Attrs { | ||
101 | &self.top_attrs | ||
102 | } | ||
103 | |||
104 | pub fn attrs(&self, of: ModItem) -> &Attrs { | ||
105 | self.attrs.get(&of).unwrap_or(&self.empty_attrs) | ||
106 | } | ||
88 | } | 107 | } |
89 | 108 | ||
90 | macro_rules! impl_index { | 109 | macro_rules! impl_index { |
@@ -140,7 +159,7 @@ pub struct Function { | |||
140 | pub has_self_param: bool, | 159 | pub has_self_param: bool, |
141 | pub params: Vec<TypeRef>, | 160 | pub params: Vec<TypeRef>, |
142 | pub ret_type: TypeRef, | 161 | pub ret_type: TypeRef, |
143 | pub ast: FileAstId<ast::FnDef>, | 162 | pub ast_id: FileAstId<ast::FnDef>, |
144 | // FIXME inner items | 163 | // FIXME inner items |
145 | } | 164 | } |
146 | 165 | ||
@@ -151,7 +170,18 @@ pub struct Struct { | |||
151 | pub visibility: RawVisibility, | 170 | pub visibility: RawVisibility, |
152 | pub generic_params: generics::GenericParams, | 171 | pub generic_params: generics::GenericParams, |
153 | pub fields: Fields, | 172 | pub fields: Fields, |
154 | pub ast: FileAstId<ast::StructDef>, | 173 | pub ast_id: FileAstId<ast::StructDef>, |
174 | pub kind: StructDefKind, | ||
175 | } | ||
176 | |||
177 | #[derive(Debug, Eq, PartialEq)] | ||
178 | pub enum StructDefKind { | ||
179 | /// `struct S { ... }` - type namespace only. | ||
180 | Record, | ||
181 | /// `struct S(...);` | ||
182 | Tuple, | ||
183 | /// `struct S;` | ||
184 | Unit, | ||
155 | } | 185 | } |
156 | 186 | ||
157 | #[derive(Debug, Eq, PartialEq)] | 187 | #[derive(Debug, Eq, PartialEq)] |
@@ -161,6 +191,7 @@ pub struct Union { | |||
161 | pub visibility: RawVisibility, | 191 | pub visibility: RawVisibility, |
162 | pub generic_params: generics::GenericParams, | 192 | pub generic_params: generics::GenericParams, |
163 | pub fields: Fields, | 193 | pub fields: Fields, |
194 | pub ast_id: FileAstId<ast::UnionDef>, | ||
164 | } | 195 | } |
165 | 196 | ||
166 | #[derive(Debug, Eq, PartialEq)] | 197 | #[derive(Debug, Eq, PartialEq)] |
@@ -170,6 +201,7 @@ pub struct Enum { | |||
170 | pub visibility: RawVisibility, | 201 | pub visibility: RawVisibility, |
171 | pub generic_params: generics::GenericParams, | 202 | pub generic_params: generics::GenericParams, |
172 | pub variants: Range<Idx<Variant>>, | 203 | pub variants: Range<Idx<Variant>>, |
204 | pub ast_id: FileAstId<ast::EnumDef>, | ||
173 | } | 205 | } |
174 | 206 | ||
175 | #[derive(Debug, Eq, PartialEq)] | 207 | #[derive(Debug, Eq, PartialEq)] |
@@ -178,6 +210,7 @@ pub struct Const { | |||
178 | pub name: Option<Name>, | 210 | pub name: Option<Name>, |
179 | pub visibility: RawVisibility, | 211 | pub visibility: RawVisibility, |
180 | pub type_ref: TypeRef, | 212 | pub type_ref: TypeRef, |
213 | pub ast_id: FileAstId<ast::ConstDef>, | ||
181 | } | 214 | } |
182 | 215 | ||
183 | #[derive(Debug, Eq, PartialEq)] | 216 | #[derive(Debug, Eq, PartialEq)] |
@@ -185,6 +218,7 @@ pub struct Static { | |||
185 | pub name: Name, | 218 | pub name: Name, |
186 | pub visibility: RawVisibility, | 219 | pub visibility: RawVisibility, |
187 | pub type_ref: TypeRef, | 220 | pub type_ref: TypeRef, |
221 | pub ast_id: FileAstId<ast::StaticDef>, | ||
188 | } | 222 | } |
189 | 223 | ||
190 | #[derive(Debug, Eq, PartialEq)] | 224 | #[derive(Debug, Eq, PartialEq)] |
@@ -194,6 +228,7 @@ pub struct Trait { | |||
194 | pub generic_params: generics::GenericParams, | 228 | pub generic_params: generics::GenericParams, |
195 | pub auto: bool, | 229 | pub auto: bool, |
196 | pub items: Vec<AssocItem>, | 230 | pub items: Vec<AssocItem>, |
231 | pub ast_id: FileAstId<ast::TraitDef>, | ||
197 | } | 232 | } |
198 | 233 | ||
199 | #[derive(Debug, Eq, PartialEq)] | 234 | #[derive(Debug, Eq, PartialEq)] |
@@ -203,6 +238,7 @@ pub struct Impl { | |||
203 | pub target_type: TypeRef, | 238 | pub target_type: TypeRef, |
204 | pub is_negative: bool, | 239 | pub is_negative: bool, |
205 | pub items: Vec<AssocItem>, | 240 | pub items: Vec<AssocItem>, |
241 | pub ast_id: FileAstId<ast::ImplDef>, | ||
206 | } | 242 | } |
207 | 243 | ||
208 | #[derive(Debug, Clone, PartialEq, Eq)] | 244 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -211,24 +247,31 @@ pub struct TypeAlias { | |||
211 | pub visibility: RawVisibility, | 247 | pub visibility: RawVisibility, |
212 | pub generic_params: generics::GenericParams, | 248 | pub generic_params: generics::GenericParams, |
213 | pub type_ref: Option<TypeRef>, | 249 | pub type_ref: Option<TypeRef>, |
250 | pub ast_id: FileAstId<ast::TypeAliasDef>, | ||
214 | } | 251 | } |
215 | 252 | ||
216 | #[derive(Debug, Eq, PartialEq)] | 253 | #[derive(Debug, Eq, PartialEq)] |
217 | pub struct Mod { | 254 | pub struct Mod { |
218 | pub name: Name, | 255 | pub name: Name, |
219 | pub visibility: RawVisibility, | 256 | pub visibility: RawVisibility, |
220 | pub items: Vec<ModItem>, | 257 | pub kind: ModKind, |
258 | pub ast_id: FileAstId<ast::Module>, | ||
221 | } | 259 | } |
222 | 260 | ||
261 | #[derive(Debug, Eq, PartialEq)] | ||
223 | pub enum ModKind { | 262 | pub enum ModKind { |
263 | /// `mod m { ... }` | ||
224 | Inline { items: Vec<ModItem> }, | 264 | Inline { items: Vec<ModItem> }, |
225 | 265 | ||
266 | /// `mod m;` | ||
226 | Outline {}, | 267 | Outline {}, |
227 | } | 268 | } |
228 | 269 | ||
229 | #[derive(Debug, Eq, PartialEq)] | 270 | #[derive(Debug, Eq, PartialEq)] |
230 | pub struct MacroCall { | 271 | pub struct MacroCall { |
272 | /// For `macro_rules!` declarations, this is the name of the declared macro. | ||
231 | pub name: Option<Name>, | 273 | pub name: Option<Name>, |
274 | /// Path to the called macro. | ||
232 | pub path: ModPath, | 275 | pub path: ModPath, |
233 | /// Has `#[macro_export]`. | 276 | /// Has `#[macro_export]`. |
234 | pub is_export: bool, | 277 | pub is_export: bool, |
@@ -256,7 +299,7 @@ macro_rules! impl_froms { | |||
256 | } | 299 | } |
257 | } | 300 | } |
258 | 301 | ||
259 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | 302 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] |
260 | pub enum ModItem { | 303 | pub enum ModItem { |
261 | Import(Idx<Import>), | 304 | Import(Idx<Import>), |
262 | Function(Idx<Function>), | 305 | Function(Idx<Function>), |
@@ -353,7 +396,8 @@ impl Ctx { | |||
353 | } | 396 | } |
354 | 397 | ||
355 | fn lower_mod_item(&mut self, item: &ast::ModuleItem) -> Option<ModItems> { | 398 | fn lower_mod_item(&mut self, item: &ast::ModuleItem) -> Option<ModItems> { |
356 | match item { | 399 | let attrs = Attrs::new(item, &self.hygiene); |
400 | let items = match item { | ||
357 | ast::ModuleItem::StructDef(ast) => { | 401 | ast::ModuleItem::StructDef(ast) => { |
358 | self.lower_struct(ast).map(|data| self.tree.structs.alloc(data).into()) | 402 | self.lower_struct(ast).map(|data| self.tree.structs.alloc(data).into()) |
359 | } | 403 | } |
@@ -406,7 +450,15 @@ impl Ctx { | |||
406 | }) | 450 | }) |
407 | .collect::<SmallVec<_>>(), | 451 | .collect::<SmallVec<_>>(), |
408 | )), | 452 | )), |
453 | }; | ||
454 | |||
455 | if !attrs.is_empty() { | ||
456 | for item in items.iter().flat_map(|items| &items.0) { | ||
457 | self.tree.attrs.insert(*item, attrs.clone()); | ||
458 | } | ||
409 | } | 459 | } |
460 | |||
461 | items | ||
410 | } | 462 | } |
411 | 463 | ||
412 | fn lower_assoc_item(&mut self, item: &ast::AssocItem) -> Option<AssocItem> { | 464 | fn lower_assoc_item(&mut self, item: &ast::AssocItem) -> Option<AssocItem> { |
@@ -430,8 +482,13 @@ impl Ctx { | |||
430 | let name = strukt.name()?.as_name(); | 482 | let name = strukt.name()?.as_name(); |
431 | let generic_params = self.lower_generic_params(strukt); | 483 | let generic_params = self.lower_generic_params(strukt); |
432 | let fields = self.lower_fields(&strukt.kind()); | 484 | let fields = self.lower_fields(&strukt.kind()); |
433 | let ast = self.source_ast_id_map.ast_id(strukt); | 485 | let ast_id = self.source_ast_id_map.ast_id(strukt); |
434 | let res = Struct { name, attrs, visibility, generic_params, fields, ast }; | 486 | let kind = match strukt.kind() { |
487 | ast::StructKind::Record(_) => StructDefKind::Record, | ||
488 | ast::StructKind::Tuple(_) => StructDefKind::Tuple, | ||
489 | ast::StructKind::Unit => StructDefKind::Unit, | ||
490 | }; | ||
491 | let res = Struct { name, attrs, visibility, generic_params, fields, ast_id, kind }; | ||
435 | Some(res) | 492 | Some(res) |
436 | } | 493 | } |
437 | 494 | ||
@@ -498,7 +555,8 @@ impl Ctx { | |||
498 | } | 555 | } |
499 | None => Fields::Record(self.next_field_idx()..self.next_field_idx()), | 556 | None => Fields::Record(self.next_field_idx()..self.next_field_idx()), |
500 | }; | 557 | }; |
501 | let res = Union { name, attrs, visibility, generic_params, fields }; | 558 | let ast_id = self.source_ast_id_map.ast_id(union); |
559 | let res = Union { name, attrs, visibility, generic_params, fields, ast_id }; | ||
502 | Some(res) | 560 | Some(res) |
503 | } | 561 | } |
504 | 562 | ||
@@ -511,7 +569,8 @@ impl Ctx { | |||
511 | Some(variant_list) => self.lower_variants(variant_list), | 569 | Some(variant_list) => self.lower_variants(variant_list), |
512 | None => self.next_variant_idx()..self.next_variant_idx(), | 570 | None => self.next_variant_idx()..self.next_variant_idx(), |
513 | }; | 571 | }; |
514 | let res = Enum { name, attrs, visibility, generic_params, variants }; | 572 | let ast_id = self.source_ast_id_map.ast_id(enum_); |
573 | let res = Enum { name, attrs, visibility, generic_params, variants, ast_id }; | ||
515 | Some(res) | 574 | Some(res) |
516 | } | 575 | } |
517 | 576 | ||
@@ -578,7 +637,7 @@ impl Ctx { | |||
578 | ret_type | 637 | ret_type |
579 | }; | 638 | }; |
580 | 639 | ||
581 | let ast = self.source_ast_id_map.ast_id(func); | 640 | let ast_id = self.source_ast_id_map.ast_id(func); |
582 | let res = Function { | 641 | let res = Function { |
583 | name, | 642 | name, |
584 | attrs, | 643 | attrs, |
@@ -587,7 +646,7 @@ impl Ctx { | |||
587 | has_self_param, | 646 | has_self_param, |
588 | params, | 647 | params, |
589 | ret_type, | 648 | ret_type, |
590 | ast, | 649 | ast_id, |
591 | }; | 650 | }; |
592 | Some(res) | 651 | Some(res) |
593 | } | 652 | } |
@@ -597,7 +656,8 @@ impl Ctx { | |||
597 | let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it)); | 656 | let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it)); |
598 | let visibility = self.lower_visibility(type_alias); | 657 | let visibility = self.lower_visibility(type_alias); |
599 | let generic_params = self.lower_generic_params(type_alias); | 658 | let generic_params = self.lower_generic_params(type_alias); |
600 | let res = TypeAlias { name, visibility, generic_params, type_ref }; | 659 | let ast_id = self.source_ast_id_map.ast_id(type_alias); |
660 | let res = TypeAlias { name, visibility, generic_params, type_ref, ast_id }; | ||
601 | Some(res) | 661 | Some(res) |
602 | } | 662 | } |
603 | 663 | ||
@@ -605,7 +665,8 @@ impl Ctx { | |||
605 | let name = static_.name()?.as_name(); | 665 | let name = static_.name()?.as_name(); |
606 | let type_ref = self.lower_type_ref_opt(static_.ascribed_type()); | 666 | let type_ref = self.lower_type_ref_opt(static_.ascribed_type()); |
607 | let visibility = self.lower_visibility(static_); | 667 | let visibility = self.lower_visibility(static_); |
608 | let res = Static { name, visibility, type_ref }; | 668 | let ast_id = self.source_ast_id_map.ast_id(static_); |
669 | let res = Static { name, visibility, type_ref, ast_id }; | ||
609 | Some(res) | 670 | Some(res) |
610 | } | 671 | } |
611 | 672 | ||
@@ -613,19 +674,30 @@ impl Ctx { | |||
613 | let name = konst.name().map(|it| it.as_name()); | 674 | let name = konst.name().map(|it| it.as_name()); |
614 | let type_ref = self.lower_type_ref_opt(konst.ascribed_type()); | 675 | let type_ref = self.lower_type_ref_opt(konst.ascribed_type()); |
615 | let visibility = self.lower_visibility(konst); | 676 | let visibility = self.lower_visibility(konst); |
616 | Const { name, visibility, type_ref } | 677 | let ast_id = self.source_ast_id_map.ast_id(konst); |
678 | Const { name, visibility, type_ref, ast_id } | ||
617 | } | 679 | } |
618 | 680 | ||
619 | fn lower_module(&mut self, module: &ast::Module) -> Option<Mod> { | 681 | fn lower_module(&mut self, module: &ast::Module) -> Option<Mod> { |
620 | let name = module.name()?.as_name(); | 682 | let name = module.name()?.as_name(); |
621 | let visibility = self.lower_visibility(module); | 683 | let visibility = self.lower_visibility(module); |
622 | let items = module.item_list().map(move |list| { | 684 | let kind = if module.semicolon_token().is_some() { |
623 | list.items() | 685 | ModKind::Outline {} |
624 | .flat_map(move |item| self.lower_mod_item(&item)) | 686 | } else { |
625 | .flat_map(|items| items.0) | 687 | ModKind::Inline { |
626 | .collect() | 688 | items: module |
627 | }); | 689 | .item_list() |
628 | Some(Mod { name, visibility, items: items.unwrap_or_default() }) | 690 | .map(|list| { |
691 | list.items() | ||
692 | .flat_map(|item| self.lower_mod_item(&item)) | ||
693 | .flat_map(|items| items.0) | ||
694 | .collect() | ||
695 | }) | ||
696 | .unwrap_or_default(), | ||
697 | } | ||
698 | }; | ||
699 | let ast_id = self.source_ast_id_map.ast_id(module); | ||
700 | Some(Mod { name, visibility, kind, ast_id }) | ||
629 | } | 701 | } |
630 | 702 | ||
631 | fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<Trait> { | 703 | fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<Trait> { |
@@ -633,11 +705,19 @@ impl Ctx { | |||
633 | let visibility = self.lower_visibility(trait_def); | 705 | let visibility = self.lower_visibility(trait_def); |
634 | let generic_params = self.lower_generic_params(trait_def); | 706 | let generic_params = self.lower_generic_params(trait_def); |
635 | let auto = trait_def.auto_token().is_some(); | 707 | let auto = trait_def.auto_token().is_some(); |
636 | let items = trait_def.item_list().map(move |list| { | 708 | let items = trait_def.item_list().map(|list| { |
637 | // FIXME: Does not handle macros | 709 | // FIXME: Does not handle macros |
638 | list.assoc_items().flat_map(move |item| self.lower_assoc_item(&item)).collect() | 710 | list.assoc_items().flat_map(|item| self.lower_assoc_item(&item)).collect() |
639 | }); | 711 | }); |
640 | Some(Trait { name, visibility, generic_params, auto, items: items.unwrap_or_default() }) | 712 | let ast_id = self.source_ast_id_map.ast_id(trait_def); |
713 | Some(Trait { | ||
714 | name, | ||
715 | visibility, | ||
716 | generic_params, | ||
717 | auto, | ||
718 | items: items.unwrap_or_default(), | ||
719 | ast_id, | ||
720 | }) | ||
641 | } | 721 | } |
642 | 722 | ||
643 | fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<Impl> { | 723 | fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<Impl> { |
@@ -650,7 +730,8 @@ impl Ctx { | |||
650 | .assoc_items() | 730 | .assoc_items() |
651 | .filter_map(|item| self.lower_assoc_item(&item)) | 731 | .filter_map(|item| self.lower_assoc_item(&item)) |
652 | .collect(); | 732 | .collect(); |
653 | Some(Impl { generic_params, target_trait, target_type, is_negative, items }) | 733 | let ast_id = self.source_ast_id_map.ast_id(impl_def); |
734 | Some(Impl { generic_params, target_trait, target_type, is_negative, items, ast_id }) | ||
654 | } | 735 | } |
655 | 736 | ||
656 | fn lower_use(&mut self, use_item: &ast::UseItem) -> Vec<Import> { | 737 | fn lower_use(&mut self, use_item: &ast::UseItem) -> Vec<Import> { |