aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-06-15 18:16:14 +0100
committerJonas Schievink <[email protected]>2020-06-24 15:53:14 +0100
commit9d244129296a1805f890640016719afcee66a320 (patch)
treef2c36f261aa27a236b14bd0862cb87cd2e1d2f37 /crates/ra_hir_def
parentf9417bcf49f531e0382afd405b9163f791f91c85 (diff)
Move collector
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs301
1 files changed, 193 insertions, 108 deletions
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 034f27410..b899a5fb3 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -4,6 +4,7 @@
4//! resolves imports and expands macros. 4//! resolves imports and expands macros.
5 5
6use hir_expand::{ 6use hir_expand::{
7 ast_id_map::FileAstId,
7 builtin_derive::find_builtin_derive, 8 builtin_derive::find_builtin_derive,
8 builtin_macro::find_builtin_macro, 9 builtin_macro::find_builtin_macro,
9 name::{name, AsName, Name}, 10 name::{name, AsName, Name},
@@ -19,14 +20,14 @@ use test_utils::mark;
19use crate::{ 20use crate::{
20 attr::Attrs, 21 attr::Attrs,
21 db::DefDatabase, 22 db::DefDatabase,
22 item_tree::{Import, ItemTree, Mod, ModItem}, 23 item_tree::{Import, ItemTree, MacroCall, Mod, ModItem, ModKind, StructDefKind},
23 nameres::{ 24 nameres::{
24 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 25 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
25 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, 26 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
26 }, 27 },
27 path::{ImportAlias, ModPath, PathKind}, 28 path::{ImportAlias, ModPath, PathKind},
28 per_ns::PerNs, 29 per_ns::PerNs,
29 visibility::Visibility, 30 visibility::{RawVisibility, Visibility},
30 AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, 31 AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId,
31 FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, 32 FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc,
32 TraitLoc, TypeAliasLoc, UnionLoc, 33 TraitLoc, TypeAliasLoc, UnionLoc,
@@ -125,6 +126,13 @@ struct DeriveDirective {
125 ast_id: AstIdWithPath<ast::ModuleItem>, 126 ast_id: AstIdWithPath<ast::ModuleItem>,
126} 127}
127 128
129struct DefData<'a> {
130 id: ModuleDefId,
131 name: &'a Name,
132 visibility: &'a RawVisibility,
133 has_constructor: bool,
134}
135
128/// Walks the tree of module recursively 136/// Walks the tree of module recursively
129struct DefCollector<'a> { 137struct DefCollector<'a> {
130 db: &'a dyn DefDatabase, 138 db: &'a dyn DefDatabase,
@@ -693,9 +701,9 @@ impl ModCollector<'_, '_> {
693 // `#[macro_use] extern crate` is hoisted to imports macros before collecting 701 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
694 // any other items. 702 // any other items.
695 for item in items { 703 for item in items {
696 if self.is_cfg_enabled(&item.attrs) { 704 if self.is_cfg_enabled(self.item_tree.attrs(*item)) {
697 if let raw::RawItemKind::Import(import_id) = item.kind { 705 if let ModItem::Import(import_id) = item {
698 let import = self.item_tree[import_id].clone(); 706 let import = self.item_tree[*import_id].clone();
699 if import.is_extern_crate && import.is_macro_use { 707 if import.is_extern_crate && import.is_macro_use {
700 self.def_collector.import_macros_from_extern_crate(self.module_id, &import); 708 self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
701 } 709 }
@@ -703,13 +711,17 @@ impl ModCollector<'_, '_> {
703 } 711 }
704 } 712 }
705 713
706 for item in items { 714 for &item in items {
707 if self.is_cfg_enabled(&item.attrs) { 715 let attrs = self.item_tree.attrs(item);
708 match item.kind { 716 if self.is_cfg_enabled(attrs) {
709 raw::RawItemKind::Module(m) => { 717 let module =
710 self.collect_module(&self.item_tree[m], &item.attrs) 718 ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
711 } 719 let container = ContainerId::ModuleId(module);
712 raw::RawItemKind::Import(import_id) => { 720
721 let mut def = None;
722 match item {
723 ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs),
724 ModItem::Import(import_id) => {
713 self.def_collector.unresolved_imports.push(ImportDirective { 725 self.def_collector.unresolved_imports.push(ImportDirective {
714 module_id: self.module_id, 726 module_id: self.module_id,
715 import_id, 727 import_id,
@@ -717,11 +729,8 @@ impl ModCollector<'_, '_> {
717 status: PartialResolvedImport::Unresolved, 729 status: PartialResolvedImport::Unresolved,
718 }) 730 })
719 } 731 }
720 raw::RawItemKind::Def(def) => { 732 ModItem::MacroCall(mac) => self.collect_macro(&self.item_tree[mac]),
721 self.define_def(&self.item_tree[def], &item.attrs) 733 ModItem::Impl(imp) => {
722 }
723 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.item_tree[mac]),
724 raw::RawItemKind::Impl(imp) => {
725 let module = ModuleId { 734 let module = ModuleId {
726 krate: self.def_collector.def_map.krate, 735 krate: self.def_collector.def_map.krate,
727 local_id: self.module_id, 736 local_id: self.module_id,
@@ -735,6 +744,147 @@ impl ModCollector<'_, '_> {
735 .scope 744 .scope
736 .define_impl(impl_id) 745 .define_impl(impl_id)
737 } 746 }
747 ModItem::Function(it) => {
748 let it = &self.item_tree[it];
749 def = Some(DefData {
750 id: FunctionLoc {
751 container: container.into(),
752 ast_id: AstId::new(self.file_id, it.ast_id),
753 }
754 .intern(self.def_collector.db)
755 .into(),
756 name: &it.name,
757 visibility: &it.visibility,
758 has_constructor: false,
759 });
760 }
761 ModItem::Struct(it) => {
762 let it = &self.item_tree[it];
763
764 // FIXME: check attrs to see if this is an attribute macro invocation;
765 // in which case we don't add the invocation, just a single attribute
766 // macro invocation
767 self.collect_derives(attrs, it.ast_id.upcast());
768
769 def = Some(DefData {
770 id: StructLoc {
771 container,
772 ast_id: AstId::new(self.file_id, it.ast_id),
773 }
774 .intern(self.def_collector.db)
775 .into(),
776 name: &it.name,
777 visibility: &it.visibility,
778 has_constructor: it.kind != StructDefKind::Record,
779 });
780 }
781 ModItem::Union(it) => {
782 let it = &self.item_tree[it];
783
784 // FIXME: check attrs to see if this is an attribute macro invocation;
785 // in which case we don't add the invocation, just a single attribute
786 // macro invocation
787 self.collect_derives(attrs, it.ast_id.upcast());
788
789 def = Some(DefData {
790 id: UnionLoc { container, ast_id: AstId::new(self.file_id, it.ast_id) }
791 .intern(self.def_collector.db)
792 .into(),
793 name: &it.name,
794 visibility: &it.visibility,
795 has_constructor: false,
796 });
797 }
798 ModItem::Enum(it) => {
799 let it = &self.item_tree[it];
800
801 // FIXME: check attrs to see if this is an attribute macro invocation;
802 // in which case we don't add the invocation, just a single attribute
803 // macro invocation
804 self.collect_derives(attrs, it.ast_id.upcast());
805
806 def = Some(DefData {
807 id: EnumLoc { container, ast_id: AstId::new(self.file_id, it.ast_id) }
808 .intern(self.def_collector.db)
809 .into(),
810 name: &it.name,
811 visibility: &it.visibility,
812 has_constructor: false,
813 });
814 }
815 ModItem::Const(it) => {
816 let it = &self.item_tree[it];
817
818 if let Some(name) = &it.name {
819 def = Some(DefData {
820 id: ConstLoc {
821 container: container.into(),
822 ast_id: AstId::new(self.file_id, it.ast_id),
823 }
824 .intern(self.def_collector.db)
825 .into(),
826 name,
827 visibility: &it.visibility,
828 has_constructor: false,
829 });
830 }
831 }
832 ModItem::Static(it) => {
833 let it = &self.item_tree[it];
834
835 def = Some(DefData {
836 id: StaticLoc {
837 container,
838 ast_id: AstId::new(self.file_id, it.ast_id),
839 }
840 .intern(self.def_collector.db)
841 .into(),
842 name: &it.name,
843 visibility: &it.visibility,
844 has_constructor: false,
845 });
846 }
847 ModItem::Trait(it) => {
848 let it = &self.item_tree[it];
849
850 def = Some(DefData {
851 id: TraitLoc { container, ast_id: AstId::new(self.file_id, it.ast_id) }
852 .intern(self.def_collector.db)
853 .into(),
854 name: &it.name,
855 visibility: &it.visibility,
856 has_constructor: false,
857 });
858 }
859 ModItem::TypeAlias(it) => {
860 let it = &self.item_tree[it];
861
862 def = Some(DefData {
863 id: TypeAliasLoc {
864 container: container.into(),
865 ast_id: AstId::new(self.file_id, it.ast_id),
866 }
867 .intern(self.def_collector.db)
868 .into(),
869 name: &it.name,
870 visibility: &it.visibility,
871 has_constructor: false,
872 });
873 }
874 }
875
876 if let Some(DefData { id, name, visibility, has_constructor }) = def {
877 self.def_collector.def_map.modules[self.module_id].scope.define_def(id);
878 let vis = self
879 .def_collector
880 .def_map
881 .resolve_visibility(self.def_collector.db, self.module_id, visibility)
882 .unwrap_or(Visibility::Public);
883 self.def_collector.update(
884 self.module_id,
885 &[(name.clone(), PerNs::from_def(id, vis, has_constructor))],
886 vis,
887 )
738 } 888 }
739 } 889 }
740 } 890 }
@@ -743,14 +893,14 @@ impl ModCollector<'_, '_> {
743 fn collect_module(&mut self, module: &Mod, attrs: &Attrs) { 893 fn collect_module(&mut self, module: &Mod, attrs: &Attrs) {
744 let path_attr = attrs.by_key("path").string_value(); 894 let path_attr = attrs.by_key("path").string_value();
745 let is_macro_use = attrs.by_key("macro_use").exists(); 895 let is_macro_use = attrs.by_key("macro_use").exists();
746 match module { 896 match &module.kind {
747 // inline module, just recurse 897 // inline module, just recurse
748 raw::ModuleData::Definition { name, visibility, items, ast_id } => { 898 ModKind::Inline { items } => {
749 let module_id = self.push_child_module( 899 let module_id = self.push_child_module(
750 name.clone(), 900 module.name.clone(),
751 AstId::new(self.file_id, *ast_id), 901 AstId::new(self.file_id, module.ast_id),
752 None, 902 None,
753 &visibility, 903 &module.visibility,
754 ); 904 );
755 905
756 ModCollector { 906 ModCollector {
@@ -759,7 +909,7 @@ impl ModCollector<'_, '_> {
759 module_id, 909 module_id,
760 file_id: self.file_id, 910 file_id: self.file_id,
761 item_tree: self.item_tree, 911 item_tree: self.item_tree,
762 mod_dir: self.mod_dir.descend_into_definition(name, path_attr), 912 mod_dir: self.mod_dir.descend_into_definition(&module.name, path_attr),
763 } 913 }
764 .collect(&*items); 914 .collect(&*items);
765 if is_macro_use { 915 if is_macro_use {
@@ -767,31 +917,31 @@ impl ModCollector<'_, '_> {
767 } 917 }
768 } 918 }
769 // out of line module, resolve, parse and recurse 919 // out of line module, resolve, parse and recurse
770 raw::ModuleData::Declaration { name, visibility, ast_id } => { 920 ModKind::Outline {} => {
771 let ast_id = AstId::new(self.file_id, *ast_id); 921 let ast_id = AstId::new(self.file_id, module.ast_id);
772 match self.mod_dir.resolve_declaration( 922 match self.mod_dir.resolve_declaration(
773 self.def_collector.db, 923 self.def_collector.db,
774 self.file_id, 924 self.file_id,
775 name, 925 &module.name,
776 path_attr, 926 path_attr,
777 ) { 927 ) {
778 Ok((file_id, is_mod_rs, mod_dir)) => { 928 Ok((file_id, is_mod_rs, mod_dir)) => {
779 let module_id = self.push_child_module( 929 let module_id = self.push_child_module(
780 name.clone(), 930 module.name.clone(),
781 ast_id, 931 ast_id,
782 Some((file_id, is_mod_rs)), 932 Some((file_id, is_mod_rs)),
783 &visibility, 933 &module.visibility,
784 ); 934 );
785 let raw_items = self.def_collector.db.raw_items(file_id.into()); 935 let item_tree = self.def_collector.db.item_tree(file_id.into());
786 ModCollector { 936 ModCollector {
787 def_collector: &mut *self.def_collector, 937 def_collector: &mut *self.def_collector,
788 macro_depth: self.macro_depth, 938 macro_depth: self.macro_depth,
789 module_id, 939 module_id,
790 file_id: file_id.into(), 940 file_id: file_id.into(),
791 item_tree: &raw_items, 941 item_tree: &item_tree,
792 mod_dir, 942 mod_dir,
793 } 943 }
794 .collect(raw_items.items()); 944 .collect(item_tree.top_level_items());
795 if is_macro_use { 945 if is_macro_use {
796 self.import_all_legacy_macros(module_id); 946 self.import_all_legacy_macros(module_id);
797 } 947 }
@@ -840,77 +990,7 @@ impl ModCollector<'_, '_> {
840 res 990 res
841 } 991 }
842 992
843 fn define_def(&mut self, def: &raw::DefData, attrs: &Attrs) { 993 fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::ModuleItem>) {
844 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
845 // FIXME: check attrs to see if this is an attribute macro invocation;
846 // in which case we don't add the invocation, just a single attribute
847 // macro invocation
848 self.collect_derives(attrs, def);
849
850 let name = def.name.clone();
851 let container = ContainerId::ModuleId(module);
852 let vis = &def.visibility;
853 let mut has_constructor = false;
854
855 let def: ModuleDefId = match def.kind {
856 raw::DefKind::Function(ast_id) => FunctionLoc {
857 container: container.into(),
858 ast_id: AstId::new(self.file_id, ast_id),
859 }
860 .intern(self.def_collector.db)
861 .into(),
862 raw::DefKind::Struct(ast_id, mode) => {
863 has_constructor = mode != raw::StructDefKind::Record;
864 StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
865 .intern(self.def_collector.db)
866 .into()
867 }
868 raw::DefKind::Union(ast_id) => {
869 UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
870 .intern(self.def_collector.db)
871 .into()
872 }
873 raw::DefKind::Enum(ast_id) => {
874 EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
875 .intern(self.def_collector.db)
876 .into()
877 }
878 raw::DefKind::Const(ast_id) => {
879 ConstLoc { container: container.into(), ast_id: AstId::new(self.file_id, ast_id) }
880 .intern(self.def_collector.db)
881 .into()
882 }
883 raw::DefKind::Static(ast_id) => {
884 StaticLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
885 .intern(self.def_collector.db)
886 .into()
887 }
888 raw::DefKind::Trait(ast_id) => {
889 TraitLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
890 .intern(self.def_collector.db)
891 .into()
892 }
893 raw::DefKind::TypeAlias(ast_id) => TypeAliasLoc {
894 container: container.into(),
895 ast_id: AstId::new(self.file_id, ast_id),
896 }
897 .intern(self.def_collector.db)
898 .into(),
899 };
900 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
901 let vis = self
902 .def_collector
903 .def_map
904 .resolve_visibility(self.def_collector.db, self.module_id, vis)
905 .unwrap_or(Visibility::Public);
906 self.def_collector.update(
907 self.module_id,
908 &[(name, PerNs::from_def(def, vis, has_constructor))],
909 vis,
910 )
911 }
912
913 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
914 for derive_subtree in attrs.by_key("derive").tt_values() { 994 for derive_subtree in attrs.by_key("derive").tt_values() {
915 // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree 995 // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree
916 for tt in &derive_subtree.token_trees { 996 for tt in &derive_subtree.token_trees {
@@ -921,7 +1001,7 @@ impl ModCollector<'_, '_> {
921 }; 1001 };
922 let path = ModPath::from_tt_ident(ident); 1002 let path = ModPath::from_tt_ident(ident);
923 1003
924 let ast_id = AstIdWithPath::new(self.file_id, def.kind.ast_id(), path); 1004 let ast_id = AstIdWithPath::new(self.file_id, ast_id, path);
925 self.def_collector 1005 self.def_collector
926 .unexpanded_attribute_macros 1006 .unexpanded_attribute_macros
927 .push(DeriveDirective { module_id: self.module_id, ast_id }); 1007 .push(DeriveDirective { module_id: self.module_id, ast_id });
@@ -929,11 +1009,11 @@ impl ModCollector<'_, '_> {
929 } 1009 }
930 } 1010 }
931 1011
932 fn collect_macro(&mut self, mac: &raw::MacroData) { 1012 fn collect_macro(&mut self, mac: &MacroCall) {
933 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); 1013 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone());
934 1014
935 // Case 0: builtin macros 1015 // Case 0: builtin macros
936 if mac.builtin { 1016 if mac.is_builtin {
937 if let Some(name) = &mac.name { 1017 if let Some(name) = &mac.name {
938 let krate = self.def_collector.def_map.krate; 1018 let krate = self.def_collector.def_map.krate;
939 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id.ast_id) { 1019 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id.ast_id) {
@@ -941,7 +1021,7 @@ impl ModCollector<'_, '_> {
941 self.module_id, 1021 self.module_id,
942 name.clone(), 1022 name.clone(),
943 macro_id, 1023 macro_id,
944 mac.export, 1024 mac.is_export,
945 ); 1025 );
946 return; 1026 return;
947 } 1027 }
@@ -955,9 +1035,14 @@ impl ModCollector<'_, '_> {
955 ast_id: Some(ast_id.ast_id), 1035 ast_id: Some(ast_id.ast_id),
956 krate: Some(self.def_collector.def_map.krate), 1036 krate: Some(self.def_collector.def_map.krate),
957 kind: MacroDefKind::Declarative, 1037 kind: MacroDefKind::Declarative,
958 local_inner: mac.local_inner, 1038 local_inner: mac.is_local_inner,
959 }; 1039 };
960 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); 1040 self.def_collector.define_macro(
1041 self.module_id,
1042 name.clone(),
1043 macro_id,
1044 mac.is_export,
1045 );
961 } 1046 }
962 return; 1047 return;
963 } 1048 }