diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-06-24 16:07:37 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-06-24 16:07:37 +0100 |
commit | e9bdb05e9676e85bdd8fa5008e3ada3812b36fd9 (patch) | |
tree | a21d348fbfa2d06f1fba77622c5417383938e6fe /crates/ra_hir_def/src/nameres | |
parent | 1a3b507a007d0373a83bde203d780b860ea55ce1 (diff) | |
parent | 2928600374a8356c2c2bffee080c47cb0f463fb9 (diff) |
Merge #4990
4990: Introduce an ItemTree layer to avoid reparsing files r=matklad a=jonas-schievink
This reduces the latency of "go to definition" in a simple benchmark on rust-analyzer by around 30%.
cc https://github.com/rust-analyzer/rust-analyzer/issues/1650
Closes https://github.com/rust-analyzer/rust-analyzer/issues/3485
Co-authored-by: Aleksey Kladov <[email protected]>
Co-authored-by: Jonas Schievink <[email protected]>
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/ra_hir_def/src/nameres')
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 386 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/raw.rs | 482 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests/incremental.rs | 38 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests/mod_resolution.rs | 12 |
4 files changed, 260 insertions, 658 deletions
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index cbce04315..94da700ad 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 | ||
6 | use hir_expand::{ | 6 | use 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,13 +20,16 @@ use test_utils::mark; | |||
19 | use crate::{ | 20 | use crate::{ |
20 | attr::Attrs, | 21 | attr::Attrs, |
21 | db::DefDatabase, | 22 | db::DefDatabase, |
23 | item_tree::{ | ||
24 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind, | ||
25 | }, | ||
22 | nameres::{ | 26 | nameres::{ |
23 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, | 27 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, |
24 | raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, | 28 | BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, |
25 | }, | 29 | }, |
26 | path::{ImportAlias, ModPath, PathKind}, | 30 | path::{ImportAlias, ModPath, PathKind}, |
27 | per_ns::PerNs, | 31 | per_ns::PerNs, |
28 | visibility::Visibility, | 32 | visibility::{RawVisibility, Visibility}, |
29 | AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, | 33 | AdtId, AsMacroCall, AstId, AstIdWithPath, ConstLoc, ContainerId, EnumLoc, EnumVariantId, |
30 | FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, | 34 | FunctionLoc, ImplLoc, Intern, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, |
31 | TraitLoc, TypeAliasLoc, UnionLoc, | 35 | TraitLoc, TypeAliasLoc, UnionLoc, |
@@ -102,10 +106,50 @@ impl PartialResolvedImport { | |||
102 | } | 106 | } |
103 | 107 | ||
104 | #[derive(Clone, Debug, Eq, PartialEq)] | 108 | #[derive(Clone, Debug, Eq, PartialEq)] |
109 | struct Import { | ||
110 | pub path: ModPath, | ||
111 | pub alias: Option<ImportAlias>, | ||
112 | pub visibility: RawVisibility, | ||
113 | pub is_glob: bool, | ||
114 | pub is_prelude: bool, | ||
115 | pub is_extern_crate: bool, | ||
116 | pub is_macro_use: bool, | ||
117 | } | ||
118 | |||
119 | impl Import { | ||
120 | fn from_use(tree: &ItemTree, id: FileItemTreeId<item_tree::Import>) -> Self { | ||
121 | let it = &tree[id]; | ||
122 | let visibility = &tree[it.visibility]; | ||
123 | Self { | ||
124 | path: it.path.clone(), | ||
125 | alias: it.alias.clone(), | ||
126 | visibility: visibility.clone(), | ||
127 | is_glob: it.is_glob, | ||
128 | is_prelude: it.is_prelude, | ||
129 | is_extern_crate: false, | ||
130 | is_macro_use: false, | ||
131 | } | ||
132 | } | ||
133 | |||
134 | fn from_extern_crate(tree: &ItemTree, id: FileItemTreeId<item_tree::ExternCrate>) -> Self { | ||
135 | let it = &tree[id]; | ||
136 | let visibility = &tree[it.visibility]; | ||
137 | Self { | ||
138 | path: it.path.clone(), | ||
139 | alias: it.alias.clone(), | ||
140 | visibility: visibility.clone(), | ||
141 | is_glob: false, | ||
142 | is_prelude: false, | ||
143 | is_extern_crate: true, | ||
144 | is_macro_use: it.is_macro_use, | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | |||
149 | #[derive(Clone, Debug, Eq, PartialEq)] | ||
105 | struct ImportDirective { | 150 | struct ImportDirective { |
106 | module_id: LocalModuleId, | 151 | module_id: LocalModuleId, |
107 | import_id: raw::Import, | 152 | import: Import, |
108 | import: raw::ImportData, | ||
109 | status: PartialResolvedImport, | 153 | status: PartialResolvedImport, |
110 | } | 154 | } |
111 | 155 | ||
@@ -123,6 +167,13 @@ struct DeriveDirective { | |||
123 | ast_id: AstIdWithPath<ast::ModuleItem>, | 167 | ast_id: AstIdWithPath<ast::ModuleItem>, |
124 | } | 168 | } |
125 | 169 | ||
170 | struct DefData<'a> { | ||
171 | id: ModuleDefId, | ||
172 | name: &'a Name, | ||
173 | visibility: &'a RawVisibility, | ||
174 | has_constructor: bool, | ||
175 | } | ||
176 | |||
126 | /// Walks the tree of module recursively | 177 | /// Walks the tree of module recursively |
127 | struct DefCollector<'a> { | 178 | struct DefCollector<'a> { |
128 | db: &'a dyn DefDatabase, | 179 | db: &'a dyn DefDatabase, |
@@ -140,7 +191,7 @@ struct DefCollector<'a> { | |||
140 | impl DefCollector<'_> { | 191 | impl DefCollector<'_> { |
141 | fn collect(&mut self) { | 192 | fn collect(&mut self) { |
142 | let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; | 193 | let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; |
143 | let raw_items = self.db.raw_items(file_id.into()); | 194 | let item_tree = self.db.item_tree(file_id.into()); |
144 | let module_id = self.def_map.root; | 195 | let module_id = self.def_map.root; |
145 | self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; | 196 | self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; |
146 | ModCollector { | 197 | ModCollector { |
@@ -148,10 +199,10 @@ impl DefCollector<'_> { | |||
148 | macro_depth: 0, | 199 | macro_depth: 0, |
149 | module_id, | 200 | module_id, |
150 | file_id: file_id.into(), | 201 | file_id: file_id.into(), |
151 | raw_items: &raw_items, | 202 | item_tree: &item_tree, |
152 | mod_dir: ModDir::root(), | 203 | mod_dir: ModDir::root(), |
153 | } | 204 | } |
154 | .collect(raw_items.items()); | 205 | .collect(item_tree.top_level_items()); |
155 | 206 | ||
156 | // main name resolution fixed-point loop. | 207 | // main name resolution fixed-point loop. |
157 | let mut i = 0; | 208 | let mut i = 0; |
@@ -286,7 +337,7 @@ impl DefCollector<'_> { | |||
286 | fn import_macros_from_extern_crate( | 337 | fn import_macros_from_extern_crate( |
287 | &mut self, | 338 | &mut self, |
288 | current_module_id: LocalModuleId, | 339 | current_module_id: LocalModuleId, |
289 | import: &raw::ImportData, | 340 | import: &item_tree::ExternCrate, |
290 | ) { | 341 | ) { |
291 | log::debug!( | 342 | log::debug!( |
292 | "importing macros from extern crate: {:?} ({:?})", | 343 | "importing macros from extern crate: {:?} ({:?})", |
@@ -352,11 +403,7 @@ impl DefCollector<'_> { | |||
352 | } | 403 | } |
353 | } | 404 | } |
354 | 405 | ||
355 | fn resolve_import( | 406 | fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport { |
356 | &self, | ||
357 | module_id: LocalModuleId, | ||
358 | import: &raw::ImportData, | ||
359 | ) -> PartialResolvedImport { | ||
360 | log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); | 407 | log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); |
361 | if import.is_extern_crate { | 408 | if import.is_extern_crate { |
362 | let res = self.def_map.resolve_name_in_extern_prelude( | 409 | let res = self.def_map.resolve_name_in_extern_prelude( |
@@ -649,17 +696,17 @@ impl DefCollector<'_> { | |||
649 | depth: usize, | 696 | depth: usize, |
650 | ) { | 697 | ) { |
651 | let file_id: HirFileId = macro_call_id.as_file(); | 698 | let file_id: HirFileId = macro_call_id.as_file(); |
652 | let raw_items = self.db.raw_items(file_id); | 699 | let item_tree = self.db.item_tree(file_id); |
653 | let mod_dir = self.mod_dirs[&module_id].clone(); | 700 | let mod_dir = self.mod_dirs[&module_id].clone(); |
654 | ModCollector { | 701 | ModCollector { |
655 | def_collector: &mut *self, | 702 | def_collector: &mut *self, |
656 | macro_depth: depth, | 703 | macro_depth: depth, |
657 | file_id, | 704 | file_id, |
658 | module_id, | 705 | module_id, |
659 | raw_items: &raw_items, | 706 | item_tree: &item_tree, |
660 | mod_dir, | 707 | mod_dir, |
661 | } | 708 | } |
662 | .collect(raw_items.items()); | 709 | .collect(item_tree.top_level_items()); |
663 | } | 710 | } |
664 | 711 | ||
665 | fn finish(self) -> CrateDefMap { | 712 | fn finish(self) -> CrateDefMap { |
@@ -673,12 +720,12 @@ struct ModCollector<'a, 'b> { | |||
673 | macro_depth: usize, | 720 | macro_depth: usize, |
674 | module_id: LocalModuleId, | 721 | module_id: LocalModuleId, |
675 | file_id: HirFileId, | 722 | file_id: HirFileId, |
676 | raw_items: &'a raw::RawItems, | 723 | item_tree: &'a ItemTree, |
677 | mod_dir: ModDir, | 724 | mod_dir: ModDir, |
678 | } | 725 | } |
679 | 726 | ||
680 | impl ModCollector<'_, '_> { | 727 | impl ModCollector<'_, '_> { |
681 | fn collect(&mut self, items: &[raw::RawItem]) { | 728 | fn collect(&mut self, items: &[ModItem]) { |
682 | // Note: don't assert that inserted value is fresh: it's simply not true | 729 | // Note: don't assert that inserted value is fresh: it's simply not true |
683 | // for macros. | 730 | // for macros. |
684 | self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); | 731 | self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); |
@@ -695,64 +742,204 @@ impl ModCollector<'_, '_> { | |||
695 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting | 742 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting |
696 | // any other items. | 743 | // any other items. |
697 | for item in items { | 744 | for item in items { |
698 | if self.is_cfg_enabled(&item.attrs) { | 745 | if self.is_cfg_enabled(self.item_tree.attrs(*item)) { |
699 | if let raw::RawItemKind::Import(import_id) = item.kind { | 746 | if let ModItem::ExternCrate(id) = item { |
700 | let import = self.raw_items[import_id].clone(); | 747 | let import = self.item_tree[*id].clone(); |
701 | if import.is_extern_crate && import.is_macro_use { | 748 | if import.is_macro_use { |
702 | self.def_collector.import_macros_from_extern_crate(self.module_id, &import); | 749 | self.def_collector.import_macros_from_extern_crate(self.module_id, &import); |
703 | } | 750 | } |
704 | } | 751 | } |
705 | } | 752 | } |
706 | } | 753 | } |
707 | 754 | ||
708 | for item in items { | 755 | for &item in items { |
709 | if self.is_cfg_enabled(&item.attrs) { | 756 | let attrs = self.item_tree.attrs(item); |
710 | match item.kind { | 757 | if self.is_cfg_enabled(attrs) { |
711 | raw::RawItemKind::Module(m) => { | 758 | let module = |
712 | self.collect_module(&self.raw_items[m], &item.attrs) | 759 | ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id }; |
713 | } | 760 | let container = ContainerId::ModuleId(module); |
714 | raw::RawItemKind::Import(import_id) => { | 761 | |
762 | let mut def = None; | ||
763 | match item { | ||
764 | ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs), | ||
765 | ModItem::Import(import_id) => { | ||
715 | self.def_collector.unresolved_imports.push(ImportDirective { | 766 | self.def_collector.unresolved_imports.push(ImportDirective { |
716 | module_id: self.module_id, | 767 | module_id: self.module_id, |
717 | import_id, | 768 | import: Import::from_use(&self.item_tree, import_id), |
718 | import: self.raw_items[import_id].clone(), | ||
719 | status: PartialResolvedImport::Unresolved, | 769 | status: PartialResolvedImport::Unresolved, |
720 | }) | 770 | }) |
721 | } | 771 | } |
722 | raw::RawItemKind::Def(def) => { | 772 | ModItem::ExternCrate(import_id) => { |
723 | self.define_def(&self.raw_items[def], &item.attrs) | 773 | self.def_collector.unresolved_imports.push(ImportDirective { |
774 | module_id: self.module_id, | ||
775 | import: Import::from_extern_crate(&self.item_tree, import_id), | ||
776 | status: PartialResolvedImport::Unresolved, | ||
777 | }) | ||
724 | } | 778 | } |
725 | raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]), | 779 | ModItem::MacroCall(mac) => self.collect_macro(&self.item_tree[mac]), |
726 | raw::RawItemKind::Impl(imp) => { | 780 | ModItem::Impl(imp) => { |
727 | let module = ModuleId { | 781 | let module = ModuleId { |
728 | krate: self.def_collector.def_map.krate, | 782 | krate: self.def_collector.def_map.krate, |
729 | local_id: self.module_id, | 783 | local_id: self.module_id, |
730 | }; | 784 | }; |
731 | let container = ContainerId::ModuleId(module); | 785 | let container = ContainerId::ModuleId(module); |
732 | let ast_id = self.raw_items[imp].ast_id; | 786 | let impl_id = ImplLoc { container, id: ItemTreeId::new(self.file_id, imp) } |
733 | let impl_id = | 787 | .intern(self.def_collector.db); |
734 | ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) } | ||
735 | .intern(self.def_collector.db); | ||
736 | self.def_collector.def_map.modules[self.module_id] | 788 | self.def_collector.def_map.modules[self.module_id] |
737 | .scope | 789 | .scope |
738 | .define_impl(impl_id) | 790 | .define_impl(impl_id) |
739 | } | 791 | } |
792 | ModItem::Function(id) => { | ||
793 | let func = &self.item_tree[id]; | ||
794 | def = Some(DefData { | ||
795 | id: FunctionLoc { | ||
796 | container: container.into(), | ||
797 | id: ItemTreeId::new(self.file_id, id), | ||
798 | } | ||
799 | .intern(self.def_collector.db) | ||
800 | .into(), | ||
801 | name: &func.name, | ||
802 | visibility: &self.item_tree[func.visibility], | ||
803 | has_constructor: false, | ||
804 | }); | ||
805 | } | ||
806 | ModItem::Struct(id) => { | ||
807 | let it = &self.item_tree[id]; | ||
808 | |||
809 | // FIXME: check attrs to see if this is an attribute macro invocation; | ||
810 | // in which case we don't add the invocation, just a single attribute | ||
811 | // macro invocation | ||
812 | self.collect_derives(attrs, it.ast_id.upcast()); | ||
813 | |||
814 | def = Some(DefData { | ||
815 | id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } | ||
816 | .intern(self.def_collector.db) | ||
817 | .into(), | ||
818 | name: &it.name, | ||
819 | visibility: &self.item_tree[it.visibility], | ||
820 | has_constructor: it.kind != StructDefKind::Record, | ||
821 | }); | ||
822 | } | ||
823 | ModItem::Union(id) => { | ||
824 | let it = &self.item_tree[id]; | ||
825 | |||
826 | // FIXME: check attrs to see if this is an attribute macro invocation; | ||
827 | // in which case we don't add the invocation, just a single attribute | ||
828 | // macro invocation | ||
829 | self.collect_derives(attrs, it.ast_id.upcast()); | ||
830 | |||
831 | def = Some(DefData { | ||
832 | id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } | ||
833 | .intern(self.def_collector.db) | ||
834 | .into(), | ||
835 | name: &it.name, | ||
836 | visibility: &self.item_tree[it.visibility], | ||
837 | has_constructor: false, | ||
838 | }); | ||
839 | } | ||
840 | ModItem::Enum(id) => { | ||
841 | let it = &self.item_tree[id]; | ||
842 | |||
843 | // FIXME: check attrs to see if this is an attribute macro invocation; | ||
844 | // in which case we don't add the invocation, just a single attribute | ||
845 | // macro invocation | ||
846 | self.collect_derives(attrs, it.ast_id.upcast()); | ||
847 | |||
848 | def = Some(DefData { | ||
849 | id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } | ||
850 | .intern(self.def_collector.db) | ||
851 | .into(), | ||
852 | name: &it.name, | ||
853 | visibility: &self.item_tree[it.visibility], | ||
854 | has_constructor: false, | ||
855 | }); | ||
856 | } | ||
857 | ModItem::Const(id) => { | ||
858 | let it = &self.item_tree[id]; | ||
859 | |||
860 | if let Some(name) = &it.name { | ||
861 | def = Some(DefData { | ||
862 | id: ConstLoc { | ||
863 | container: container.into(), | ||
864 | id: ItemTreeId::new(self.file_id, id), | ||
865 | } | ||
866 | .intern(self.def_collector.db) | ||
867 | .into(), | ||
868 | name, | ||
869 | visibility: &self.item_tree[it.visibility], | ||
870 | has_constructor: false, | ||
871 | }); | ||
872 | } | ||
873 | } | ||
874 | ModItem::Static(id) => { | ||
875 | let it = &self.item_tree[id]; | ||
876 | |||
877 | def = Some(DefData { | ||
878 | id: StaticLoc { container, id: ItemTreeId::new(self.file_id, id) } | ||
879 | .intern(self.def_collector.db) | ||
880 | .into(), | ||
881 | name: &it.name, | ||
882 | visibility: &self.item_tree[it.visibility], | ||
883 | has_constructor: false, | ||
884 | }); | ||
885 | } | ||
886 | ModItem::Trait(id) => { | ||
887 | let it = &self.item_tree[id]; | ||
888 | |||
889 | def = Some(DefData { | ||
890 | id: TraitLoc { container, id: ItemTreeId::new(self.file_id, id) } | ||
891 | .intern(self.def_collector.db) | ||
892 | .into(), | ||
893 | name: &it.name, | ||
894 | visibility: &self.item_tree[it.visibility], | ||
895 | has_constructor: false, | ||
896 | }); | ||
897 | } | ||
898 | ModItem::TypeAlias(id) => { | ||
899 | let it = &self.item_tree[id]; | ||
900 | |||
901 | def = Some(DefData { | ||
902 | id: TypeAliasLoc { | ||
903 | container: container.into(), | ||
904 | id: ItemTreeId::new(self.file_id, id), | ||
905 | } | ||
906 | .intern(self.def_collector.db) | ||
907 | .into(), | ||
908 | name: &it.name, | ||
909 | visibility: &self.item_tree[it.visibility], | ||
910 | has_constructor: false, | ||
911 | }); | ||
912 | } | ||
913 | } | ||
914 | |||
915 | if let Some(DefData { id, name, visibility, has_constructor }) = def { | ||
916 | self.def_collector.def_map.modules[self.module_id].scope.define_def(id); | ||
917 | let vis = self | ||
918 | .def_collector | ||
919 | .def_map | ||
920 | .resolve_visibility(self.def_collector.db, self.module_id, visibility) | ||
921 | .unwrap_or(Visibility::Public); | ||
922 | self.def_collector.update( | ||
923 | self.module_id, | ||
924 | &[(name.clone(), PerNs::from_def(id, vis, has_constructor))], | ||
925 | vis, | ||
926 | ) | ||
740 | } | 927 | } |
741 | } | 928 | } |
742 | } | 929 | } |
743 | } | 930 | } |
744 | 931 | ||
745 | fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) { | 932 | fn collect_module(&mut self, module: &Mod, attrs: &Attrs) { |
746 | let path_attr = attrs.by_key("path").string_value(); | 933 | let path_attr = attrs.by_key("path").string_value(); |
747 | let is_macro_use = attrs.by_key("macro_use").exists(); | 934 | let is_macro_use = attrs.by_key("macro_use").exists(); |
748 | match module { | 935 | match &module.kind { |
749 | // inline module, just recurse | 936 | // inline module, just recurse |
750 | raw::ModuleData::Definition { name, visibility, items, ast_id } => { | 937 | ModKind::Inline { items } => { |
751 | let module_id = self.push_child_module( | 938 | let module_id = self.push_child_module( |
752 | name.clone(), | 939 | module.name.clone(), |
753 | AstId::new(self.file_id, *ast_id), | 940 | AstId::new(self.file_id, module.ast_id), |
754 | None, | 941 | None, |
755 | &visibility, | 942 | &self.item_tree[module.visibility], |
756 | ); | 943 | ); |
757 | 944 | ||
758 | ModCollector { | 945 | ModCollector { |
@@ -760,8 +947,8 @@ impl ModCollector<'_, '_> { | |||
760 | macro_depth: self.macro_depth, | 947 | macro_depth: self.macro_depth, |
761 | module_id, | 948 | module_id, |
762 | file_id: self.file_id, | 949 | file_id: self.file_id, |
763 | raw_items: self.raw_items, | 950 | item_tree: self.item_tree, |
764 | mod_dir: self.mod_dir.descend_into_definition(name, path_attr), | 951 | mod_dir: self.mod_dir.descend_into_definition(&module.name, path_attr), |
765 | } | 952 | } |
766 | .collect(&*items); | 953 | .collect(&*items); |
767 | if is_macro_use { | 954 | if is_macro_use { |
@@ -769,31 +956,31 @@ impl ModCollector<'_, '_> { | |||
769 | } | 956 | } |
770 | } | 957 | } |
771 | // out of line module, resolve, parse and recurse | 958 | // out of line module, resolve, parse and recurse |
772 | raw::ModuleData::Declaration { name, visibility, ast_id } => { | 959 | ModKind::Outline {} => { |
773 | let ast_id = AstId::new(self.file_id, *ast_id); | 960 | let ast_id = AstId::new(self.file_id, module.ast_id); |
774 | match self.mod_dir.resolve_declaration( | 961 | match self.mod_dir.resolve_declaration( |
775 | self.def_collector.db, | 962 | self.def_collector.db, |
776 | self.file_id, | 963 | self.file_id, |
777 | name, | 964 | &module.name, |
778 | path_attr, | 965 | path_attr, |
779 | ) { | 966 | ) { |
780 | Ok((file_id, is_mod_rs, mod_dir)) => { | 967 | Ok((file_id, is_mod_rs, mod_dir)) => { |
781 | let module_id = self.push_child_module( | 968 | let module_id = self.push_child_module( |
782 | name.clone(), | 969 | module.name.clone(), |
783 | ast_id, | 970 | ast_id, |
784 | Some((file_id, is_mod_rs)), | 971 | Some((file_id, is_mod_rs)), |
785 | &visibility, | 972 | &self.item_tree[module.visibility], |
786 | ); | 973 | ); |
787 | let raw_items = self.def_collector.db.raw_items(file_id.into()); | 974 | let item_tree = self.def_collector.db.item_tree(file_id.into()); |
788 | ModCollector { | 975 | ModCollector { |
789 | def_collector: &mut *self.def_collector, | 976 | def_collector: &mut *self.def_collector, |
790 | macro_depth: self.macro_depth, | 977 | macro_depth: self.macro_depth, |
791 | module_id, | 978 | module_id, |
792 | file_id: file_id.into(), | 979 | file_id: file_id.into(), |
793 | raw_items: &raw_items, | 980 | item_tree: &item_tree, |
794 | mod_dir, | 981 | mod_dir, |
795 | } | 982 | } |
796 | .collect(raw_items.items()); | 983 | .collect(item_tree.top_level_items()); |
797 | if is_macro_use { | 984 | if is_macro_use { |
798 | self.import_all_legacy_macros(module_id); | 985 | self.import_all_legacy_macros(module_id); |
799 | } | 986 | } |
@@ -842,77 +1029,7 @@ impl ModCollector<'_, '_> { | |||
842 | res | 1029 | res |
843 | } | 1030 | } |
844 | 1031 | ||
845 | fn define_def(&mut self, def: &raw::DefData, attrs: &Attrs) { | 1032 | fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::ModuleItem>) { |
846 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id }; | ||
847 | // FIXME: check attrs to see if this is an attribute macro invocation; | ||
848 | // in which case we don't add the invocation, just a single attribute | ||
849 | // macro invocation | ||
850 | self.collect_derives(attrs, def); | ||
851 | |||
852 | let name = def.name.clone(); | ||
853 | let container = ContainerId::ModuleId(module); | ||
854 | let vis = &def.visibility; | ||
855 | let mut has_constructor = false; | ||
856 | |||
857 | let def: ModuleDefId = match def.kind { | ||
858 | raw::DefKind::Function(ast_id) => FunctionLoc { | ||
859 | container: container.into(), | ||
860 | ast_id: AstId::new(self.file_id, ast_id), | ||
861 | } | ||
862 | .intern(self.def_collector.db) | ||
863 | .into(), | ||
864 | raw::DefKind::Struct(ast_id, mode) => { | ||
865 | has_constructor = mode != raw::StructDefKind::Record; | ||
866 | StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } | ||
867 | .intern(self.def_collector.db) | ||
868 | .into() | ||
869 | } | ||
870 | raw::DefKind::Union(ast_id) => { | ||
871 | UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) } | ||
872 | .intern(self.def_collector.db) | ||
873 | .into() | ||
874 | } | ||
875 | raw::DefKind::Enum(ast_id) => { | ||
876 | EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) } | ||
877 | .intern(self.def_collector.db) | ||
878 | .into() | ||
879 | } | ||
880 | raw::DefKind::Const(ast_id) => { | ||
881 | ConstLoc { container: container.into(), ast_id: AstId::new(self.file_id, ast_id) } | ||
882 | .intern(self.def_collector.db) | ||
883 | .into() | ||
884 | } | ||
885 | raw::DefKind::Static(ast_id) => { | ||
886 | StaticLoc { container, ast_id: AstId::new(self.file_id, ast_id) } | ||
887 | .intern(self.def_collector.db) | ||
888 | .into() | ||
889 | } | ||
890 | raw::DefKind::Trait(ast_id) => { | ||
891 | TraitLoc { container, ast_id: AstId::new(self.file_id, ast_id) } | ||
892 | .intern(self.def_collector.db) | ||
893 | .into() | ||
894 | } | ||
895 | raw::DefKind::TypeAlias(ast_id) => TypeAliasLoc { | ||
896 | container: container.into(), | ||
897 | ast_id: AstId::new(self.file_id, ast_id), | ||
898 | } | ||
899 | .intern(self.def_collector.db) | ||
900 | .into(), | ||
901 | }; | ||
902 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | ||
903 | let vis = self | ||
904 | .def_collector | ||
905 | .def_map | ||
906 | .resolve_visibility(self.def_collector.db, self.module_id, vis) | ||
907 | .unwrap_or(Visibility::Public); | ||
908 | self.def_collector.update( | ||
909 | self.module_id, | ||
910 | &[(name, PerNs::from_def(def, vis, has_constructor))], | ||
911 | vis, | ||
912 | ) | ||
913 | } | ||
914 | |||
915 | fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { | ||
916 | for derive_subtree in attrs.by_key("derive").tt_values() { | 1033 | for derive_subtree in attrs.by_key("derive").tt_values() { |
917 | // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree | 1034 | // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree |
918 | for tt in &derive_subtree.token_trees { | 1035 | for tt in &derive_subtree.token_trees { |
@@ -923,7 +1040,7 @@ impl ModCollector<'_, '_> { | |||
923 | }; | 1040 | }; |
924 | let path = ModPath::from_tt_ident(ident); | 1041 | let path = ModPath::from_tt_ident(ident); |
925 | 1042 | ||
926 | let ast_id = AstIdWithPath::new(self.file_id, def.kind.ast_id(), path); | 1043 | let ast_id = AstIdWithPath::new(self.file_id, ast_id, path); |
927 | self.def_collector | 1044 | self.def_collector |
928 | .unexpanded_attribute_macros | 1045 | .unexpanded_attribute_macros |
929 | .push(DeriveDirective { module_id: self.module_id, ast_id }); | 1046 | .push(DeriveDirective { module_id: self.module_id, ast_id }); |
@@ -931,11 +1048,11 @@ impl ModCollector<'_, '_> { | |||
931 | } | 1048 | } |
932 | } | 1049 | } |
933 | 1050 | ||
934 | fn collect_macro(&mut self, mac: &raw::MacroData) { | 1051 | fn collect_macro(&mut self, mac: &MacroCall) { |
935 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); | 1052 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); |
936 | 1053 | ||
937 | // Case 0: builtin macros | 1054 | // Case 0: builtin macros |
938 | if mac.builtin { | 1055 | if mac.is_builtin { |
939 | if let Some(name) = &mac.name { | 1056 | if let Some(name) = &mac.name { |
940 | let krate = self.def_collector.def_map.krate; | 1057 | let krate = self.def_collector.def_map.krate; |
941 | if let Some(macro_id) = find_builtin_macro(name, krate, ast_id.ast_id) { | 1058 | if let Some(macro_id) = find_builtin_macro(name, krate, ast_id.ast_id) { |
@@ -943,7 +1060,7 @@ impl ModCollector<'_, '_> { | |||
943 | self.module_id, | 1060 | self.module_id, |
944 | name.clone(), | 1061 | name.clone(), |
945 | macro_id, | 1062 | macro_id, |
946 | mac.export, | 1063 | mac.is_export, |
947 | ); | 1064 | ); |
948 | return; | 1065 | return; |
949 | } | 1066 | } |
@@ -957,9 +1074,14 @@ impl ModCollector<'_, '_> { | |||
957 | ast_id: Some(ast_id.ast_id), | 1074 | ast_id: Some(ast_id.ast_id), |
958 | krate: Some(self.def_collector.def_map.krate), | 1075 | krate: Some(self.def_collector.def_map.krate), |
959 | kind: MacroDefKind::Declarative, | 1076 | kind: MacroDefKind::Declarative, |
960 | local_inner: mac.local_inner, | 1077 | local_inner: mac.is_local_inner, |
961 | }; | 1078 | }; |
962 | self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); | 1079 | self.def_collector.define_macro( |
1080 | self.module_id, | ||
1081 | name.clone(), | ||
1082 | macro_id, | ||
1083 | mac.is_export, | ||
1084 | ); | ||
963 | } | 1085 | } |
964 | return; | 1086 | return; |
965 | } | 1087 | } |
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs deleted file mode 100644 index f44baa579..000000000 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ /dev/null | |||
@@ -1,482 +0,0 @@ | |||
1 | //! Lowers syntax tree of a rust file into a raw representation of containing | ||
2 | //! items, *without* attaching them to a module structure. | ||
3 | //! | ||
4 | //! That is, raw items don't have semantics, just as syntax, but, unlike syntax, | ||
5 | //! they don't change with trivial source code edits, making them a great tool | ||
6 | //! for building salsa recomputation firewalls. | ||
7 | |||
8 | use std::{ops::Index, sync::Arc}; | ||
9 | |||
10 | use hir_expand::{ | ||
11 | ast_id_map::AstIdMap, | ||
12 | hygiene::Hygiene, | ||
13 | name::{AsName, Name}, | ||
14 | }; | ||
15 | use ra_arena::{Arena, Idx}; | ||
16 | use ra_prof::profile; | ||
17 | use ra_syntax::{ | ||
18 | ast::{self, AttrsOwner, NameOwner, VisibilityOwner}, | ||
19 | AstNode, | ||
20 | }; | ||
21 | use test_utils::mark; | ||
22 | |||
23 | use crate::{ | ||
24 | attr::Attrs, | ||
25 | db::DefDatabase, | ||
26 | path::{ImportAlias, ModPath}, | ||
27 | visibility::RawVisibility, | ||
28 | FileAstId, HirFileId, InFile, | ||
29 | }; | ||
30 | |||
31 | /// `RawItems` is a set of top-level items in a file (except for impls). | ||
32 | /// | ||
33 | /// It is the input to name resolution algorithm. `RawItems` are not invalidated | ||
34 | /// on most edits. | ||
35 | #[derive(Debug, Default, PartialEq, Eq)] | ||
36 | pub struct RawItems { | ||
37 | modules: Arena<ModuleData>, | ||
38 | imports: Arena<ImportData>, | ||
39 | defs: Arena<DefData>, | ||
40 | macros: Arena<MacroData>, | ||
41 | impls: Arena<ImplData>, | ||
42 | /// items for top-level module | ||
43 | items: Vec<RawItem>, | ||
44 | } | ||
45 | |||
46 | impl RawItems { | ||
47 | pub(crate) fn raw_items_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<RawItems> { | ||
48 | let _p = profile("raw_items_query"); | ||
49 | let mut collector = RawItemsCollector { | ||
50 | raw_items: RawItems::default(), | ||
51 | source_ast_id_map: db.ast_id_map(file_id), | ||
52 | file_id, | ||
53 | hygiene: Hygiene::new(db.upcast(), file_id), | ||
54 | }; | ||
55 | if let Some(node) = db.parse_or_expand(file_id) { | ||
56 | if let Some(source_file) = ast::SourceFile::cast(node.clone()) { | ||
57 | collector.process_module(None, source_file); | ||
58 | } else if let Some(item_list) = ast::MacroItems::cast(node) { | ||
59 | collector.process_module(None, item_list); | ||
60 | } | ||
61 | } | ||
62 | let raw_items = collector.raw_items; | ||
63 | Arc::new(raw_items) | ||
64 | } | ||
65 | |||
66 | pub(super) fn items(&self) -> &[RawItem] { | ||
67 | &self.items | ||
68 | } | ||
69 | } | ||
70 | |||
71 | impl Index<Idx<ModuleData>> for RawItems { | ||
72 | type Output = ModuleData; | ||
73 | fn index(&self, idx: Idx<ModuleData>) -> &ModuleData { | ||
74 | &self.modules[idx] | ||
75 | } | ||
76 | } | ||
77 | |||
78 | impl Index<Import> for RawItems { | ||
79 | type Output = ImportData; | ||
80 | fn index(&self, idx: Import) -> &ImportData { | ||
81 | &self.imports[idx] | ||
82 | } | ||
83 | } | ||
84 | |||
85 | impl Index<Idx<DefData>> for RawItems { | ||
86 | type Output = DefData; | ||
87 | fn index(&self, idx: Idx<DefData>) -> &DefData { | ||
88 | &self.defs[idx] | ||
89 | } | ||
90 | } | ||
91 | |||
92 | impl Index<Idx<MacroData>> for RawItems { | ||
93 | type Output = MacroData; | ||
94 | fn index(&self, idx: Idx<MacroData>) -> &MacroData { | ||
95 | &self.macros[idx] | ||
96 | } | ||
97 | } | ||
98 | |||
99 | impl Index<Idx<ImplData>> for RawItems { | ||
100 | type Output = ImplData; | ||
101 | fn index(&self, idx: Idx<ImplData>) -> &ImplData { | ||
102 | &self.impls[idx] | ||
103 | } | ||
104 | } | ||
105 | |||
106 | #[derive(Debug, PartialEq, Eq, Clone)] | ||
107 | pub(super) struct RawItem { | ||
108 | pub(super) attrs: Attrs, | ||
109 | pub(super) kind: RawItemKind, | ||
110 | } | ||
111 | |||
112 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | ||
113 | pub(super) enum RawItemKind { | ||
114 | Module(Idx<ModuleData>), | ||
115 | Import(Import), | ||
116 | Def(Idx<DefData>), | ||
117 | Macro(Idx<MacroData>), | ||
118 | Impl(Idx<ImplData>), | ||
119 | } | ||
120 | |||
121 | #[derive(Debug, PartialEq, Eq)] | ||
122 | pub(super) enum ModuleData { | ||
123 | Declaration { | ||
124 | name: Name, | ||
125 | visibility: RawVisibility, | ||
126 | ast_id: FileAstId<ast::Module>, | ||
127 | }, | ||
128 | Definition { | ||
129 | name: Name, | ||
130 | visibility: RawVisibility, | ||
131 | ast_id: FileAstId<ast::Module>, | ||
132 | items: Vec<RawItem>, | ||
133 | }, | ||
134 | } | ||
135 | |||
136 | pub(crate) type Import = Idx<ImportData>; | ||
137 | |||
138 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
139 | pub struct ImportData { | ||
140 | pub(super) path: ModPath, | ||
141 | pub(super) alias: Option<ImportAlias>, | ||
142 | pub(super) is_glob: bool, | ||
143 | pub(super) is_prelude: bool, | ||
144 | pub(super) is_extern_crate: bool, | ||
145 | pub(super) is_macro_use: bool, | ||
146 | pub(super) visibility: RawVisibility, | ||
147 | } | ||
148 | |||
149 | // type Def = Idx<DefData>; | ||
150 | |||
151 | #[derive(Debug, PartialEq, Eq)] | ||
152 | pub(super) struct DefData { | ||
153 | pub(super) name: Name, | ||
154 | pub(super) kind: DefKind, | ||
155 | pub(super) visibility: RawVisibility, | ||
156 | } | ||
157 | |||
158 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | ||
159 | pub(super) enum StructDefKind { | ||
160 | Record, | ||
161 | Tuple, | ||
162 | Unit, | ||
163 | } | ||
164 | |||
165 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | ||
166 | pub(super) enum DefKind { | ||
167 | Function(FileAstId<ast::FnDef>), | ||
168 | Struct(FileAstId<ast::StructDef>, StructDefKind), | ||
169 | Union(FileAstId<ast::UnionDef>), | ||
170 | Enum(FileAstId<ast::EnumDef>), | ||
171 | Const(FileAstId<ast::ConstDef>), | ||
172 | Static(FileAstId<ast::StaticDef>), | ||
173 | Trait(FileAstId<ast::TraitDef>), | ||
174 | TypeAlias(FileAstId<ast::TypeAliasDef>), | ||
175 | } | ||
176 | |||
177 | impl DefKind { | ||
178 | pub fn ast_id(self) -> FileAstId<ast::ModuleItem> { | ||
179 | match self { | ||
180 | DefKind::Function(it) => it.upcast(), | ||
181 | DefKind::Struct(it, _) => it.upcast(), | ||
182 | DefKind::Union(it) => it.upcast(), | ||
183 | DefKind::Enum(it) => it.upcast(), | ||
184 | DefKind::Const(it) => it.upcast(), | ||
185 | DefKind::Static(it) => it.upcast(), | ||
186 | DefKind::Trait(it) => it.upcast(), | ||
187 | DefKind::TypeAlias(it) => it.upcast(), | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | |||
192 | #[derive(Debug, PartialEq, Eq)] | ||
193 | pub(super) struct MacroData { | ||
194 | pub(super) ast_id: FileAstId<ast::MacroCall>, | ||
195 | pub(super) path: ModPath, | ||
196 | pub(super) name: Option<Name>, | ||
197 | pub(super) export: bool, | ||
198 | pub(super) local_inner: bool, | ||
199 | pub(super) builtin: bool, | ||
200 | } | ||
201 | |||
202 | #[derive(Debug, PartialEq, Eq)] | ||
203 | pub(super) struct ImplData { | ||
204 | pub(super) ast_id: FileAstId<ast::ImplDef>, | ||
205 | } | ||
206 | |||
207 | struct RawItemsCollector { | ||
208 | raw_items: RawItems, | ||
209 | source_ast_id_map: Arc<AstIdMap>, | ||
210 | file_id: HirFileId, | ||
211 | hygiene: Hygiene, | ||
212 | } | ||
213 | |||
214 | impl RawItemsCollector { | ||
215 | fn process_module( | ||
216 | &mut self, | ||
217 | current_module: Option<Idx<ModuleData>>, | ||
218 | body: impl ast::ModuleItemOwner, | ||
219 | ) { | ||
220 | for item in body.items() { | ||
221 | self.add_item(current_module, item) | ||
222 | } | ||
223 | } | ||
224 | |||
225 | fn add_item(&mut self, current_module: Option<Idx<ModuleData>>, item: ast::ModuleItem) { | ||
226 | let attrs = self.parse_attrs(&item); | ||
227 | let visibility = RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene); | ||
228 | let (kind, name) = match item { | ||
229 | ast::ModuleItem::Module(module) => { | ||
230 | self.add_module(current_module, module); | ||
231 | return; | ||
232 | } | ||
233 | ast::ModuleItem::UseItem(use_item) => { | ||
234 | self.add_use_item(current_module, use_item); | ||
235 | return; | ||
236 | } | ||
237 | ast::ModuleItem::ExternCrateItem(extern_crate) => { | ||
238 | self.add_extern_crate_item(current_module, extern_crate); | ||
239 | return; | ||
240 | } | ||
241 | ast::ModuleItem::ImplDef(it) => { | ||
242 | self.add_impl(current_module, it); | ||
243 | return; | ||
244 | } | ||
245 | ast::ModuleItem::StructDef(it) => { | ||
246 | let kind = match it.kind() { | ||
247 | ast::StructKind::Record(_) => StructDefKind::Record, | ||
248 | ast::StructKind::Tuple(_) => StructDefKind::Tuple, | ||
249 | ast::StructKind::Unit => StructDefKind::Unit, | ||
250 | }; | ||
251 | let id = self.source_ast_id_map.ast_id(&it); | ||
252 | let name = it.name(); | ||
253 | (DefKind::Struct(id, kind), name) | ||
254 | } | ||
255 | ast::ModuleItem::UnionDef(it) => { | ||
256 | let id = self.source_ast_id_map.ast_id(&it); | ||
257 | let name = it.name(); | ||
258 | (DefKind::Union(id), name) | ||
259 | } | ||
260 | ast::ModuleItem::EnumDef(it) => { | ||
261 | (DefKind::Enum(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
262 | } | ||
263 | ast::ModuleItem::FnDef(it) => { | ||
264 | (DefKind::Function(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
265 | } | ||
266 | ast::ModuleItem::TraitDef(it) => { | ||
267 | (DefKind::Trait(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
268 | } | ||
269 | ast::ModuleItem::TypeAliasDef(it) => { | ||
270 | (DefKind::TypeAlias(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
271 | } | ||
272 | ast::ModuleItem::ConstDef(it) => { | ||
273 | (DefKind::Const(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
274 | } | ||
275 | ast::ModuleItem::StaticDef(it) => { | ||
276 | (DefKind::Static(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
277 | } | ||
278 | ast::ModuleItem::MacroCall(it) => { | ||
279 | self.add_macro(current_module, it); | ||
280 | return; | ||
281 | } | ||
282 | ast::ModuleItem::ExternBlock(it) => { | ||
283 | self.add_extern_block(current_module, it); | ||
284 | return; | ||
285 | } | ||
286 | }; | ||
287 | if let Some(name) = name { | ||
288 | let name = name.as_name(); | ||
289 | let def = self.raw_items.defs.alloc(DefData { name, kind, visibility }); | ||
290 | self.push_item(current_module, attrs, RawItemKind::Def(def)); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | fn add_extern_block( | ||
295 | &mut self, | ||
296 | current_module: Option<Idx<ModuleData>>, | ||
297 | block: ast::ExternBlock, | ||
298 | ) { | ||
299 | if let Some(items) = block.extern_item_list() { | ||
300 | for item in items.extern_items() { | ||
301 | let attrs = self.parse_attrs(&item); | ||
302 | let visibility = | ||
303 | RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene); | ||
304 | let (kind, name) = match item { | ||
305 | ast::ExternItem::FnDef(it) => { | ||
306 | (DefKind::Function(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
307 | } | ||
308 | ast::ExternItem::StaticDef(it) => { | ||
309 | (DefKind::Static(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
310 | } | ||
311 | }; | ||
312 | |||
313 | if let Some(name) = name { | ||
314 | let name = name.as_name(); | ||
315 | let def = self.raw_items.defs.alloc(DefData { name, kind, visibility }); | ||
316 | self.push_item(current_module, attrs, RawItemKind::Def(def)); | ||
317 | } | ||
318 | } | ||
319 | } | ||
320 | } | ||
321 | |||
322 | fn add_module(&mut self, current_module: Option<Idx<ModuleData>>, module: ast::Module) { | ||
323 | let name = match module.name() { | ||
324 | Some(it) => it.as_name(), | ||
325 | None => return, | ||
326 | }; | ||
327 | let attrs = self.parse_attrs(&module); | ||
328 | let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene); | ||
329 | |||
330 | let ast_id = self.source_ast_id_map.ast_id(&module); | ||
331 | if module.semicolon_token().is_some() { | ||
332 | let item = | ||
333 | self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id }); | ||
334 | self.push_item(current_module, attrs, RawItemKind::Module(item)); | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | if let Some(item_list) = module.item_list() { | ||
339 | let item = self.raw_items.modules.alloc(ModuleData::Definition { | ||
340 | name, | ||
341 | visibility, | ||
342 | ast_id, | ||
343 | items: Vec::new(), | ||
344 | }); | ||
345 | self.process_module(Some(item), item_list); | ||
346 | self.push_item(current_module, attrs, RawItemKind::Module(item)); | ||
347 | return; | ||
348 | } | ||
349 | mark::hit!(name_res_works_for_broken_modules); | ||
350 | } | ||
351 | |||
352 | fn add_use_item(&mut self, current_module: Option<Idx<ModuleData>>, use_item: ast::UseItem) { | ||
353 | // FIXME: cfg_attr | ||
354 | let is_prelude = use_item.has_atom_attr("prelude_import"); | ||
355 | let attrs = self.parse_attrs(&use_item); | ||
356 | let visibility = RawVisibility::from_ast_with_hygiene(use_item.visibility(), &self.hygiene); | ||
357 | |||
358 | let mut buf = Vec::new(); | ||
359 | ModPath::expand_use_item( | ||
360 | InFile { value: use_item, file_id: self.file_id }, | ||
361 | &self.hygiene, | ||
362 | |path, _use_tree, is_glob, alias| { | ||
363 | let import_data = ImportData { | ||
364 | path, | ||
365 | alias, | ||
366 | is_glob, | ||
367 | is_prelude, | ||
368 | is_extern_crate: false, | ||
369 | is_macro_use: false, | ||
370 | visibility: visibility.clone(), | ||
371 | }; | ||
372 | buf.push(import_data); | ||
373 | }, | ||
374 | ); | ||
375 | for import_data in buf { | ||
376 | self.push_import(current_module, attrs.clone(), import_data); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | fn add_extern_crate_item( | ||
381 | &mut self, | ||
382 | current_module: Option<Idx<ModuleData>>, | ||
383 | extern_crate: ast::ExternCrateItem, | ||
384 | ) { | ||
385 | if let Some(name_ref) = extern_crate.name_ref() { | ||
386 | let path = ModPath::from_name_ref(&name_ref); | ||
387 | let visibility = | ||
388 | RawVisibility::from_ast_with_hygiene(extern_crate.visibility(), &self.hygiene); | ||
389 | let alias = extern_crate.alias().map(|a| { | ||
390 | a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) | ||
391 | }); | ||
392 | let attrs = self.parse_attrs(&extern_crate); | ||
393 | // FIXME: cfg_attr | ||
394 | let is_macro_use = extern_crate.has_atom_attr("macro_use"); | ||
395 | let import_data = ImportData { | ||
396 | path, | ||
397 | alias, | ||
398 | is_glob: false, | ||
399 | is_prelude: false, | ||
400 | is_extern_crate: true, | ||
401 | is_macro_use, | ||
402 | visibility, | ||
403 | }; | ||
404 | self.push_import(current_module, attrs, import_data); | ||
405 | } | ||
406 | } | ||
407 | |||
408 | fn add_macro(&mut self, current_module: Option<Idx<ModuleData>>, m: ast::MacroCall) { | ||
409 | let attrs = self.parse_attrs(&m); | ||
410 | let path = match m.path().and_then(|path| ModPath::from_src(path, &self.hygiene)) { | ||
411 | Some(it) => it, | ||
412 | _ => return, | ||
413 | }; | ||
414 | |||
415 | let name = m.name().map(|it| it.as_name()); | ||
416 | let ast_id = self.source_ast_id_map.ast_id(&m); | ||
417 | |||
418 | // FIXME: cfg_attr | ||
419 | let export_attr = attrs.by_key("macro_export"); | ||
420 | |||
421 | let export = export_attr.exists(); | ||
422 | let local_inner = if export { | ||
423 | export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it { | ||
424 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { | ||
425 | ident.text.contains("local_inner_macros") | ||
426 | } | ||
427 | _ => false, | ||
428 | }) | ||
429 | } else { | ||
430 | false | ||
431 | }; | ||
432 | |||
433 | let builtin = attrs.by_key("rustc_builtin_macro").exists(); | ||
434 | |||
435 | let m = self.raw_items.macros.alloc(MacroData { | ||
436 | ast_id, | ||
437 | path, | ||
438 | name, | ||
439 | export, | ||
440 | local_inner, | ||
441 | builtin, | ||
442 | }); | ||
443 | self.push_item(current_module, attrs, RawItemKind::Macro(m)); | ||
444 | } | ||
445 | |||
446 | fn add_impl(&mut self, current_module: Option<Idx<ModuleData>>, imp: ast::ImplDef) { | ||
447 | let attrs = self.parse_attrs(&imp); | ||
448 | let ast_id = self.source_ast_id_map.ast_id(&imp); | ||
449 | let imp = self.raw_items.impls.alloc(ImplData { ast_id }); | ||
450 | self.push_item(current_module, attrs, RawItemKind::Impl(imp)) | ||
451 | } | ||
452 | |||
453 | fn push_import( | ||
454 | &mut self, | ||
455 | current_module: Option<Idx<ModuleData>>, | ||
456 | attrs: Attrs, | ||
457 | data: ImportData, | ||
458 | ) { | ||
459 | let import = self.raw_items.imports.alloc(data); | ||
460 | self.push_item(current_module, attrs, RawItemKind::Import(import)) | ||
461 | } | ||
462 | |||
463 | fn push_item( | ||
464 | &mut self, | ||
465 | current_module: Option<Idx<ModuleData>>, | ||
466 | attrs: Attrs, | ||
467 | kind: RawItemKind, | ||
468 | ) { | ||
469 | match current_module { | ||
470 | Some(module) => match &mut self.raw_items.modules[module] { | ||
471 | ModuleData::Definition { items, .. } => items, | ||
472 | ModuleData::Declaration { .. } => unreachable!(), | ||
473 | }, | ||
474 | None => &mut self.raw_items.items, | ||
475 | } | ||
476 | .push(RawItem { attrs, kind }) | ||
477 | } | ||
478 | |||
479 | fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { | ||
480 | Attrs::new(item, &self.hygiene) | ||
481 | } | ||
482 | } | ||
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs index 87165ac33..0c288a108 100644 --- a/crates/ra_hir_def/src/nameres/tests/incremental.rs +++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs | |||
@@ -58,44 +58,6 @@ fn typing_inside_a_function_should_not_invalidate_def_map() { | |||
58 | } | 58 | } |
59 | 59 | ||
60 | #[test] | 60 | #[test] |
61 | fn adding_inner_items_should_not_invalidate_def_map() { | ||
62 | check_def_map_is_not_recomputed( | ||
63 | r" | ||
64 | //- /lib.rs | ||
65 | struct S { a: i32} | ||
66 | enum E { A } | ||
67 | trait T { | ||
68 | fn a() {} | ||
69 | } | ||
70 | mod foo;<|> | ||
71 | impl S { | ||
72 | fn a() {} | ||
73 | } | ||
74 | use crate::foo::bar::Baz; | ||
75 | //- /foo/mod.rs | ||
76 | pub mod bar; | ||
77 | |||
78 | //- /foo/bar.rs | ||
79 | pub struct Baz; | ||
80 | ", | ||
81 | r" | ||
82 | struct S { a: i32, b: () } | ||
83 | enum E { A, B } | ||
84 | trait T { | ||
85 | fn a() {} | ||
86 | fn b() {} | ||
87 | } | ||
88 | mod foo;<|> | ||
89 | impl S { | ||
90 | fn a() {} | ||
91 | fn b() {} | ||
92 | } | ||
93 | use crate::foo::bar::Baz; | ||
94 | ", | ||
95 | ); | ||
96 | } | ||
97 | |||
98 | #[test] | ||
99 | fn typing_inside_a_macro_should_not_invalidate_def_map() { | 61 | fn typing_inside_a_macro_should_not_invalidate_def_map() { |
100 | let (mut db, pos) = TestDB::with_position( | 62 | let (mut db, pos) = TestDB::with_position( |
101 | r" | 63 | r" |
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs index b43b294ca..e9a5e4cba 100644 --- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs +++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs | |||
@@ -20,8 +20,11 @@ fn name_res_works_for_broken_modules() { | |||
20 | ", | 20 | ", |
21 | ); | 21 | ); |
22 | assert_snapshot!(map, @r###" | 22 | assert_snapshot!(map, @r###" |
23 | ⋮crate | 23 | crate |
24 | ⋮Baz: _ | 24 | Baz: _ |
25 | foo: t | ||
26 | |||
27 | crate::foo | ||
25 | "###); | 28 | "###); |
26 | } | 29 | } |
27 | 30 | ||
@@ -719,10 +722,7 @@ fn unresolved_module_diagnostics() { | |||
719 | ), | 722 | ), |
720 | ), | 723 | ), |
721 | ), | 724 | ), |
722 | value: FileAstId { | 725 | value: FileAstId::<ra_syntax::ast::generated::nodes::Module>(1), |
723 | raw: Idx::<SyntaxNodePtr>(1), | ||
724 | _ty: PhantomData, | ||
725 | }, | ||
726 | }, | 726 | }, |
727 | candidate: "bar.rs", | 727 | candidate: "bar.rs", |
728 | }, | 728 | }, |