aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/item_tree.rs135
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};
20use ast::{AstNode, AttrsOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner}; 20use ast::{AstNode, AttrsOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner};
21use either::Either; 21use either::Either;
22use rustc_hash::FxHashMap;
22use smallvec::SmallVec; 23use smallvec::SmallVec;
23use std::{ 24use 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)]
30pub struct ItemTree { 31pub 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
49impl ItemTree { 54impl 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 &macro_storage as &dyn ModuleItemOwner 70 &macro_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
90macro_rules! impl_index { 109macro_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)]
178pub 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)]
217pub struct Mod { 254pub 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)]
223pub enum ModKind { 262pub 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)]
230pub struct MacroCall { 271pub 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)]
260pub enum ModItem { 303pub 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> {