diff options
author | Aleksey Kladov <[email protected]> | 2019-03-13 13:38:02 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-03-17 09:49:07 +0000 |
commit | 2195d1db6d70d64383bec82819fab02891d09744 (patch) | |
tree | 40174ca7cbb3625ea62ebc10dbd9b592c83a8081 | |
parent | 182c05a96c25321ac3ff262cea098e0c4d7ed6f8 (diff) |
Replace module_tree with CrateDefMap
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl/krate.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl/module.rs | 97 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir/src/ids.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/module_tree.rs | 340 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map.rs | 118 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map/collector.rs | 166 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map/raw.rs | 51 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map/tests.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/runnables.rs | 2 |
16 files changed, 333 insertions, 511 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 87a7195e6..ef69ef96a 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -9,12 +9,12 @@ use crate::{ | |||
9 | HirDatabase, PersistentHirDatabase, | 9 | HirDatabase, PersistentHirDatabase, |
10 | type_ref::TypeRef, | 10 | type_ref::TypeRef, |
11 | nameres::{ModuleScope, Namespace, lower::ImportId}, | 11 | nameres::{ModuleScope, Namespace, lower::ImportId}, |
12 | nameres::crate_def_map::ModuleId, | ||
12 | expr::{Body, BodySourceMap}, | 13 | expr::{Body, BodySourceMap}, |
13 | ty::InferenceResult, | 14 | ty::InferenceResult, |
14 | adt::{EnumVariantId, StructFieldId, VariantDef}, | 15 | adt::{EnumVariantId, StructFieldId, VariantDef}, |
15 | generics::GenericParams, | 16 | generics::GenericParams, |
16 | docs::{Documentation, Docs, docs_from_ast}, | 17 | docs::{Documentation, Docs, docs_from_ast}, |
17 | module_tree::ModuleId, | ||
18 | ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, | 18 | ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, |
19 | impl_block::ImplBlock, | 19 | impl_block::ImplBlock, |
20 | resolve::Resolver, | 20 | resolve::Resolver, |
diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs index 161ae6e18..cc87c6f14 100644 --- a/crates/ra_hir/src/code_model_impl/krate.rs +++ b/crates/ra_hir/src/code_model_impl/krate.rs | |||
@@ -18,9 +18,7 @@ impl Crate { | |||
18 | .collect() | 18 | .collect() |
19 | } | 19 | } |
20 | pub(crate) fn root_module_impl(&self, db: &impl PersistentHirDatabase) -> Option<Module> { | 20 | pub(crate) fn root_module_impl(&self, db: &impl PersistentHirDatabase) -> Option<Module> { |
21 | let module_tree = db.module_tree(*self); | 21 | let module_id = db.crate_def_map(*self).root(); |
22 | let module_id = module_tree.modules().next()?; | ||
23 | |||
24 | let module = Module { krate: *self, module_id }; | 22 | let module = Module { krate: *self, module_id }; |
25 | Some(module) | 23 | Some(module) |
26 | } | 24 | } |
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 437f96942..5d8f738b5 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -1,33 +1,62 @@ | |||
1 | use ra_syntax::{ast, SyntaxNode, TreeArc}; | 1 | use ra_db::FileId; |
2 | use ra_syntax::{ast, SyntaxNode, TreeArc, AstNode}; | ||
2 | 3 | ||
3 | use crate::{ | 4 | use crate::{ |
4 | Module, ModuleSource, Problem, | 5 | Module, ModuleSource, Problem, Name, |
5 | Name, | 6 | nameres::crate_def_map::ModuleId, |
6 | module_tree::ModuleId, | ||
7 | nameres::lower::ImportId, | 7 | nameres::lower::ImportId, |
8 | HirDatabase, PersistentHirDatabase, | 8 | HirDatabase, PersistentHirDatabase, |
9 | HirFileId | 9 | HirFileId, SourceItemId, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | impl ModuleSource { | ||
13 | pub(crate) fn new( | ||
14 | db: &impl PersistentHirDatabase, | ||
15 | file_id: Option<FileId>, | ||
16 | decl_id: Option<SourceItemId>, | ||
17 | ) -> ModuleSource { | ||
18 | match (file_id, decl_id) { | ||
19 | (Some(file_id), _) => { | ||
20 | let source_file = db.parse(file_id); | ||
21 | ModuleSource::SourceFile(source_file) | ||
22 | } | ||
23 | (None, Some(item_id)) => { | ||
24 | let module = db.file_item(item_id); | ||
25 | let module = ast::Module::cast(&*module).unwrap(); | ||
26 | assert!(module.item_list().is_some(), "expected inline module"); | ||
27 | ModuleSource::Module(module.to_owned()) | ||
28 | } | ||
29 | (None, None) => panic!(), | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | |||
12 | impl Module { | 34 | impl Module { |
13 | fn with_module_id(&self, module_id: ModuleId) -> Module { | 35 | fn with_module_id(&self, module_id: ModuleId) -> Module { |
14 | Module { module_id, krate: self.krate } | 36 | Module { module_id, krate: self.krate } |
15 | } | 37 | } |
16 | 38 | ||
17 | pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option<Name> { | 39 | pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option<Name> { |
18 | let module_tree = db.module_tree(self.krate); | 40 | let def_map = db.crate_def_map(self.krate); |
19 | let link = self.module_id.parent_link(&module_tree)?; | 41 | let parent = def_map[self.module_id].parent?; |
20 | Some(link.name(&module_tree).clone()) | 42 | def_map[parent].children.iter().find_map(|(name, module_id)| { |
43 | if *module_id == self.module_id { | ||
44 | Some(name.clone()) | ||
45 | } else { | ||
46 | None | ||
47 | } | ||
48 | }) | ||
21 | } | 49 | } |
22 | 50 | ||
23 | pub(crate) fn definition_source_impl( | 51 | pub(crate) fn definition_source_impl( |
24 | &self, | 52 | &self, |
25 | db: &impl PersistentHirDatabase, | 53 | db: &impl PersistentHirDatabase, |
26 | ) -> (HirFileId, ModuleSource) { | 54 | ) -> (HirFileId, ModuleSource) { |
27 | let module_tree = db.module_tree(self.krate); | 55 | let def_map = db.crate_def_map(self.krate); |
28 | let file_id = self.module_id.file_id(&module_tree); | 56 | let decl_id = def_map[self.module_id].declaration; |
29 | let decl_id = self.module_id.decl_id(&module_tree); | 57 | let file_id = def_map[self.module_id].definition; |
30 | let module_source = ModuleSource::new(db, file_id, decl_id); | 58 | let module_source = ModuleSource::new(db, file_id, decl_id); |
59 | let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id); | ||
31 | (file_id, module_source) | 60 | (file_id, module_source) |
32 | } | 61 | } |
33 | 62 | ||
@@ -35,11 +64,11 @@ impl Module { | |||
35 | &self, | 64 | &self, |
36 | db: &impl HirDatabase, | 65 | db: &impl HirDatabase, |
37 | ) -> Option<(HirFileId, TreeArc<ast::Module>)> { | 66 | ) -> Option<(HirFileId, TreeArc<ast::Module>)> { |
38 | let module_tree = db.module_tree(self.krate); | 67 | let def_map = db.crate_def_map(self.krate); |
39 | let link = self.module_id.parent_link(&module_tree)?; | 68 | let decl = def_map[self.module_id].declaration?; |
40 | let file_id = link.owner(&module_tree).file_id(&module_tree); | 69 | let syntax_node = db.file_item(decl); |
41 | let src = link.source(&module_tree, db); | 70 | let ast = ast::Module::cast(&syntax_node).unwrap().to_owned(); |
42 | Some((file_id, src)) | 71 | Some((decl.file_id, ast)) |
43 | } | 72 | } |
44 | 73 | ||
45 | pub(crate) fn import_source_impl( | 74 | pub(crate) fn import_source_impl( |
@@ -53,16 +82,15 @@ impl Module { | |||
53 | } | 82 | } |
54 | 83 | ||
55 | pub(crate) fn crate_root_impl(&self, db: &impl PersistentHirDatabase) -> Module { | 84 | pub(crate) fn crate_root_impl(&self, db: &impl PersistentHirDatabase) -> Module { |
56 | let module_tree = db.module_tree(self.krate); | 85 | let def_map = db.crate_def_map(self.krate); |
57 | let module_id = self.module_id.crate_root(&module_tree); | 86 | self.with_module_id(def_map.root()) |
58 | self.with_module_id(module_id) | ||
59 | } | 87 | } |
60 | 88 | ||
61 | /// Finds a child module with the specified name. | 89 | /// Finds a child module with the specified name. |
62 | pub(crate) fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> { | 90 | pub(crate) fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> { |
63 | let module_tree = db.module_tree(self.krate); | 91 | let def_map = db.crate_def_map(self.krate); |
64 | let child_id = self.module_id.child(&module_tree, name)?; | 92 | let child_id = def_map[self.module_id].children.get(name)?; |
65 | Some(self.with_module_id(child_id)) | 93 | Some(self.with_module_id(*child_id)) |
66 | } | 94 | } |
67 | 95 | ||
68 | /// Iterates over all child modules. | 96 | /// Iterates over all child modules. |
@@ -70,18 +98,18 @@ impl Module { | |||
70 | &self, | 98 | &self, |
71 | db: &impl PersistentHirDatabase, | 99 | db: &impl PersistentHirDatabase, |
72 | ) -> impl Iterator<Item = Module> { | 100 | ) -> impl Iterator<Item = Module> { |
73 | let module_tree = db.module_tree(self.krate); | 101 | let def_map = db.crate_def_map(self.krate); |
74 | let children = self | 102 | let children = def_map[self.module_id] |
75 | .module_id | 103 | .children |
76 | .children(&module_tree) | 104 | .iter() |
77 | .map(|(_, module_id)| self.with_module_id(module_id)) | 105 | .map(|(_, module_id)| self.with_module_id(*module_id)) |
78 | .collect::<Vec<_>>(); | 106 | .collect::<Vec<_>>(); |
79 | children.into_iter() | 107 | children.into_iter() |
80 | } | 108 | } |
81 | 109 | ||
82 | pub(crate) fn parent_impl(&self, db: &impl PersistentHirDatabase) -> Option<Module> { | 110 | pub(crate) fn parent_impl(&self, db: &impl PersistentHirDatabase) -> Option<Module> { |
83 | let module_tree = db.module_tree(self.krate); | 111 | let def_map = db.crate_def_map(self.krate); |
84 | let parent_id = self.module_id.parent(&module_tree)?; | 112 | let parent_id = def_map[self.module_id].parent?; |
85 | Some(self.with_module_id(parent_id)) | 113 | Some(self.with_module_id(parent_id)) |
86 | } | 114 | } |
87 | 115 | ||
@@ -89,7 +117,14 @@ impl Module { | |||
89 | &self, | 117 | &self, |
90 | db: &impl HirDatabase, | 118 | db: &impl HirDatabase, |
91 | ) -> Vec<(TreeArc<SyntaxNode>, Problem)> { | 119 | ) -> Vec<(TreeArc<SyntaxNode>, Problem)> { |
92 | let module_tree = db.module_tree(self.krate); | 120 | let def_map = db.crate_def_map(self.krate); |
93 | self.module_id.problems(&module_tree, db) | 121 | let (my_file_id, _) = self.definition_source(db); |
122 | // FIXME: not entirely corret filterint by module | ||
123 | def_map | ||
124 | .problems() | ||
125 | .iter() | ||
126 | .filter(|(source_item_id, _problem)| my_file_id == source_item_id.file_id) | ||
127 | .map(|(source_item_id, problem)| (db.file_item(*source_item_id), problem.clone())) | ||
128 | .collect() | ||
94 | } | 129 | } |
95 | } | 130 | } |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 5ad9547f1..423922a57 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; | 3 | use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; |
4 | use ra_db::{SourceDatabase, salsa}; | 4 | use ra_db::{SourceDatabase, salsa, FileId}; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | MacroCallId, HirFileId, | 7 | MacroCallId, HirFileId, |
@@ -10,14 +10,11 @@ use crate::{ | |||
10 | Struct, Enum, StructField, | 10 | Struct, Enum, StructField, |
11 | Const, ConstSignature, Static, | 11 | Const, ConstSignature, Static, |
12 | macros::MacroExpansion, | 12 | macros::MacroExpansion, |
13 | module_tree::ModuleTree, | 13 | nameres::{Namespace, ItemMap, lower::{LoweredModule, ImportSourceMap}, crate_def_map::{RawItems, CrateDefMap}}, |
14 | nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, | ||
15 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig}, | 14 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig}, |
16 | adt::{StructData, EnumData}, | 15 | adt::{StructData, EnumData}, |
17 | impl_block::{ModuleImplBlocks, ImplSourceMap}, | 16 | impl_block::{ModuleImplBlocks, ImplSourceMap}, |
18 | generics::{GenericParams, GenericDef}, | 17 | generics::{GenericParams, GenericDef}, |
19 | ids::SourceFileItemId, | ||
20 | nameres::Namespace, | ||
21 | type_ref::TypeRef, | 18 | type_ref::TypeRef, |
22 | }; | 19 | }; |
23 | 20 | ||
@@ -41,13 +38,6 @@ pub trait PersistentHirDatabase: SourceDatabase + AsRef<HirInterner> { | |||
41 | #[salsa::invoke(crate::ids::SourceFileItems::file_item_query)] | 38 | #[salsa::invoke(crate::ids::SourceFileItems::file_item_query)] |
42 | fn file_item(&self, source_item_id: SourceItemId) -> TreeArc<SyntaxNode>; | 39 | fn file_item(&self, source_item_id: SourceItemId) -> TreeArc<SyntaxNode>; |
43 | 40 | ||
44 | #[salsa::invoke(crate::module_tree::Submodule::submodules_query)] | ||
45 | fn submodules( | ||
46 | &self, | ||
47 | file_id: HirFileId, | ||
48 | delc_id: Option<SourceFileItemId>, | ||
49 | ) -> Arc<Vec<crate::module_tree::Submodule>>; | ||
50 | |||
51 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_with_source_map_query)] | 41 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_with_source_map_query)] |
52 | fn lower_module_with_source_map( | 42 | fn lower_module_with_source_map( |
53 | &self, | 43 | &self, |
@@ -57,11 +47,14 @@ pub trait PersistentHirDatabase: SourceDatabase + AsRef<HirInterner> { | |||
57 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)] | 47 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)] |
58 | fn lower_module(&self, module: Module) -> Arc<LoweredModule>; | 48 | fn lower_module(&self, module: Module) -> Arc<LoweredModule>; |
59 | 49 | ||
50 | #[salsa::invoke(RawItems::raw_items_query)] | ||
51 | fn raw_items(&self, file_id: FileId) -> Arc<RawItems>; | ||
52 | |||
60 | #[salsa::invoke(crate::nameres::ItemMap::item_map_query)] | 53 | #[salsa::invoke(crate::nameres::ItemMap::item_map_query)] |
61 | fn item_map(&self, krate: Crate) -> Arc<ItemMap>; | 54 | fn item_map(&self, krate: Crate) -> Arc<ItemMap>; |
62 | 55 | ||
63 | #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)] | 56 | #[salsa::invoke(CrateDefMap::crate_def_map_query)] |
64 | fn module_tree(&self, krate: Crate) -> Arc<ModuleTree>; | 57 | fn crate_def_map(&self, krate: Crate) -> Arc<CrateDefMap>; |
65 | 58 | ||
66 | #[salsa::invoke(crate::impl_block::impls_in_module)] | 59 | #[salsa::invoke(crate::impl_block::impls_in_module)] |
67 | fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>; | 60 | fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>; |
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index e805ddcba..6ce00a372 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -296,6 +296,12 @@ impl AstItemDef<ast::TypeAliasDef> for TypeId { | |||
296 | pub struct SourceFileItemId(RawId); | 296 | pub struct SourceFileItemId(RawId); |
297 | impl_arena_id!(SourceFileItemId); | 297 | impl_arena_id!(SourceFileItemId); |
298 | 298 | ||
299 | impl SourceFileItemId { | ||
300 | pub(crate) fn with_file_id(self, file_id: HirFileId) -> SourceItemId { | ||
301 | SourceItemId { file_id, item_id: self } | ||
302 | } | ||
303 | } | ||
304 | |||
299 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 305 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
300 | pub struct SourceItemId { | 306 | pub struct SourceItemId { |
301 | pub(crate) file_id: HirFileId, | 307 | pub(crate) file_id: HirFileId, |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 4508a873e..61db4f6cc 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -26,7 +26,6 @@ pub mod source_binder; | |||
26 | mod ids; | 26 | mod ids; |
27 | mod macros; | 27 | mod macros; |
28 | mod name; | 28 | mod name; |
29 | mod module_tree; | ||
30 | mod nameres; | 29 | mod nameres; |
31 | mod adt; | 30 | mod adt; |
32 | mod type_alias; | 31 | mod type_alias; |
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs index 4d0f40e85..e69de29bb 100644 --- a/crates/ra_hir/src/module_tree.rs +++ b/crates/ra_hir/src/module_tree.rs | |||
@@ -1,340 +0,0 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use arrayvec::ArrayVec; | ||
4 | use relative_path::RelativePathBuf; | ||
5 | use ra_db::{FileId, SourceRoot}; | ||
6 | use ra_syntax::{ | ||
7 | SyntaxNode, TreeArc, | ||
8 | algo::generate, | ||
9 | ast::{self, AstNode, NameOwner}, | ||
10 | }; | ||
11 | use ra_arena::{Arena, RawId, impl_arena_id}; | ||
12 | use test_utils::tested_by; | ||
13 | |||
14 | use crate::{ | ||
15 | Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource, | ||
16 | PersistentHirDatabase, | ||
17 | Crate, | ||
18 | ids::SourceFileItemId, | ||
19 | }; | ||
20 | |||
21 | impl ModuleSource { | ||
22 | pub(crate) fn new( | ||
23 | db: &impl PersistentHirDatabase, | ||
24 | file_id: HirFileId, | ||
25 | decl_id: Option<SourceFileItemId>, | ||
26 | ) -> ModuleSource { | ||
27 | match decl_id { | ||
28 | Some(item_id) => { | ||
29 | let module = db.file_item(SourceItemId { file_id, item_id }); | ||
30 | let module = ast::Module::cast(&*module).unwrap(); | ||
31 | assert!(module.item_list().is_some(), "expected inline module"); | ||
32 | ModuleSource::Module(module.to_owned()) | ||
33 | } | ||
34 | None => { | ||
35 | let source_file = db.hir_parse(file_id); | ||
36 | ModuleSource::SourceFile(source_file) | ||
37 | } | ||
38 | } | ||
39 | } | ||
40 | } | ||
41 | |||
42 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] | ||
43 | pub struct Submodule { | ||
44 | name: Name, | ||
45 | is_declaration: bool, | ||
46 | decl_id: SourceFileItemId, | ||
47 | } | ||
48 | |||
49 | impl Submodule { | ||
50 | pub(crate) fn submodules_query( | ||
51 | db: &impl PersistentHirDatabase, | ||
52 | file_id: HirFileId, | ||
53 | decl_id: Option<SourceFileItemId>, | ||
54 | ) -> Arc<Vec<Submodule>> { | ||
55 | db.check_canceled(); | ||
56 | let file_items = db.file_items(file_id); | ||
57 | let module_source = ModuleSource::new(db, file_id, decl_id); | ||
58 | let submodules = match module_source { | ||
59 | ModuleSource::SourceFile(source_file) => { | ||
60 | collect_submodules(file_id, &file_items, &*source_file) | ||
61 | } | ||
62 | ModuleSource::Module(module) => { | ||
63 | collect_submodules(file_id, &file_items, module.item_list().unwrap()) | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | return Arc::new(submodules); | ||
68 | |||
69 | fn collect_submodules( | ||
70 | file_id: HirFileId, | ||
71 | file_items: &SourceFileItems, | ||
72 | root: &impl ast::ModuleItemOwner, | ||
73 | ) -> Vec<Submodule> { | ||
74 | root.items() | ||
75 | .filter_map(|item| match item.kind() { | ||
76 | ast::ModuleItemKind::Module(m) => Some(m), | ||
77 | _ => None, | ||
78 | }) | ||
79 | .filter_map(|module| { | ||
80 | let name = module.name()?.as_name(); | ||
81 | if !module.has_semi() && module.item_list().is_none() { | ||
82 | tested_by!(name_res_works_for_broken_modules); | ||
83 | return None; | ||
84 | } | ||
85 | let sub = Submodule { | ||
86 | name, | ||
87 | is_declaration: module.has_semi(), | ||
88 | decl_id: file_items.id_of(file_id, module.syntax()), | ||
89 | }; | ||
90 | Some(sub) | ||
91 | }) | ||
92 | .collect() | ||
93 | } | ||
94 | } | ||
95 | } | ||
96 | |||
97 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
98 | pub struct ModuleId(RawId); | ||
99 | impl_arena_id!(ModuleId); | ||
100 | |||
101 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
102 | pub struct LinkId(RawId); | ||
103 | impl_arena_id!(LinkId); | ||
104 | |||
105 | /// Physically, rust source is organized as a set of files, but logically it is | ||
106 | /// organized as a tree of modules. Usually, a single file corresponds to a | ||
107 | /// single module, but it is not neccessarily always the case. | ||
108 | /// | ||
109 | /// `ModuleTree` encapsulates the logic of transitioning from the fuzzy world of files | ||
110 | /// (which can have multiple parents) to the precise world of modules (which | ||
111 | /// always have one parent). | ||
112 | #[derive(Default, Debug, PartialEq, Eq)] | ||
113 | pub struct ModuleTree { | ||
114 | mods: Arena<ModuleId, ModuleData>, | ||
115 | links: Arena<LinkId, LinkData>, | ||
116 | } | ||
117 | |||
118 | #[derive(Debug, PartialEq, Eq)] | ||
119 | pub struct ModuleData { | ||
120 | file_id: HirFileId, | ||
121 | /// Points to `ast::Module`, `None` for the whole file. | ||
122 | decl_id: Option<SourceFileItemId>, | ||
123 | parent: Option<LinkId>, | ||
124 | children: Vec<LinkId>, | ||
125 | } | ||
126 | |||
127 | #[derive(Hash, Debug, PartialEq, Eq)] | ||
128 | struct LinkData { | ||
129 | source: SourceItemId, | ||
130 | owner: ModuleId, | ||
131 | name: Name, | ||
132 | points_to: Vec<ModuleId>, | ||
133 | problem: Option<Problem>, | ||
134 | } | ||
135 | |||
136 | impl ModuleTree { | ||
137 | pub(crate) fn module_tree_query( | ||
138 | db: &impl PersistentHirDatabase, | ||
139 | krate: Crate, | ||
140 | ) -> Arc<ModuleTree> { | ||
141 | db.check_canceled(); | ||
142 | let mut res = ModuleTree::default(); | ||
143 | res.init_crate(db, krate); | ||
144 | Arc::new(res) | ||
145 | } | ||
146 | |||
147 | pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a { | ||
148 | self.mods.iter().map(|(id, _)| id) | ||
149 | } | ||
150 | |||
151 | pub(crate) fn find_module_by_source( | ||
152 | &self, | ||
153 | file_id: HirFileId, | ||
154 | decl_id: Option<SourceFileItemId>, | ||
155 | ) -> Option<ModuleId> { | ||
156 | let (res, _) = | ||
157 | self.mods.iter().find(|(_, m)| (m.file_id, m.decl_id) == (file_id, decl_id))?; | ||
158 | Some(res) | ||
159 | } | ||
160 | |||
161 | fn init_crate(&mut self, db: &impl PersistentHirDatabase, krate: Crate) { | ||
162 | let crate_graph = db.crate_graph(); | ||
163 | let file_id = crate_graph.crate_root(krate.crate_id); | ||
164 | let source_root_id = db.file_source_root(file_id); | ||
165 | |||
166 | let source_root = db.source_root(source_root_id); | ||
167 | self.init_subtree(db, &source_root, None, file_id.into(), None); | ||
168 | } | ||
169 | |||
170 | fn init_subtree( | ||
171 | &mut self, | ||
172 | db: &impl PersistentHirDatabase, | ||
173 | source_root: &SourceRoot, | ||
174 | parent: Option<LinkId>, | ||
175 | file_id: HirFileId, | ||
176 | decl_id: Option<SourceFileItemId>, | ||
177 | ) -> ModuleId { | ||
178 | let is_root = parent.is_none(); | ||
179 | let id = self.alloc_mod(ModuleData { file_id, decl_id, parent, children: Vec::new() }); | ||
180 | for sub in db.submodules(file_id, decl_id).iter() { | ||
181 | let link = self.alloc_link(LinkData { | ||
182 | source: SourceItemId { file_id, item_id: sub.decl_id }, | ||
183 | name: sub.name.clone(), | ||
184 | owner: id, | ||
185 | points_to: Vec::new(), | ||
186 | problem: None, | ||
187 | }); | ||
188 | |||
189 | let (points_to, problem) = if sub.is_declaration { | ||
190 | let (points_to, problem) = resolve_submodule(db, file_id, &sub.name, is_root); | ||
191 | let points_to = points_to | ||
192 | .into_iter() | ||
193 | .map(|file_id| { | ||
194 | self.init_subtree(db, source_root, Some(link), file_id.into(), None) | ||
195 | }) | ||
196 | .collect::<Vec<_>>(); | ||
197 | (points_to, problem) | ||
198 | } else { | ||
199 | let points_to = | ||
200 | self.init_subtree(db, source_root, Some(link), file_id, Some(sub.decl_id)); | ||
201 | (vec![points_to], None) | ||
202 | }; | ||
203 | |||
204 | self.links[link].points_to = points_to; | ||
205 | self.links[link].problem = problem; | ||
206 | } | ||
207 | id | ||
208 | } | ||
209 | |||
210 | fn alloc_mod(&mut self, data: ModuleData) -> ModuleId { | ||
211 | self.mods.alloc(data) | ||
212 | } | ||
213 | |||
214 | fn alloc_link(&mut self, data: LinkData) -> LinkId { | ||
215 | let owner = data.owner; | ||
216 | let id = self.links.alloc(data); | ||
217 | self.mods[owner].children.push(id); | ||
218 | id | ||
219 | } | ||
220 | } | ||
221 | |||
222 | impl ModuleId { | ||
223 | pub(crate) fn file_id(self, tree: &ModuleTree) -> HirFileId { | ||
224 | tree.mods[self].file_id | ||
225 | } | ||
226 | pub(crate) fn decl_id(self, tree: &ModuleTree) -> Option<SourceFileItemId> { | ||
227 | tree.mods[self].decl_id | ||
228 | } | ||
229 | pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { | ||
230 | tree.mods[self].parent | ||
231 | } | ||
232 | pub(crate) fn parent(self, tree: &ModuleTree) -> Option<ModuleId> { | ||
233 | let link = self.parent_link(tree)?; | ||
234 | Some(tree.links[link].owner) | ||
235 | } | ||
236 | pub(crate) fn crate_root(self, tree: &ModuleTree) -> ModuleId { | ||
237 | generate(Some(self), move |it| it.parent(tree)).last().unwrap() | ||
238 | } | ||
239 | pub(crate) fn child(self, tree: &ModuleTree, name: &Name) -> Option<ModuleId> { | ||
240 | let link = tree.mods[self] | ||
241 | .children | ||
242 | .iter() | ||
243 | .map(|&it| &tree.links[it]) | ||
244 | .find(|it| it.name == *name)?; | ||
245 | Some(*link.points_to.first()?) | ||
246 | } | ||
247 | pub(crate) fn children<'a>( | ||
248 | self, | ||
249 | tree: &'a ModuleTree, | ||
250 | ) -> impl Iterator<Item = (Name, ModuleId)> + 'a { | ||
251 | tree.mods[self].children.iter().filter_map(move |&it| { | ||
252 | let link = &tree.links[it]; | ||
253 | let module = *link.points_to.first()?; | ||
254 | Some((link.name.clone(), module)) | ||
255 | }) | ||
256 | } | ||
257 | pub(crate) fn problems( | ||
258 | self, | ||
259 | tree: &ModuleTree, | ||
260 | db: &impl HirDatabase, | ||
261 | ) -> Vec<(TreeArc<SyntaxNode>, Problem)> { | ||
262 | tree.mods[self] | ||
263 | .children | ||
264 | .iter() | ||
265 | .filter_map(|&link| { | ||
266 | let p = tree.links[link].problem.clone()?; | ||
267 | let s = link.source(tree, db); | ||
268 | let s = s.name().unwrap().syntax().to_owned(); | ||
269 | Some((s, p)) | ||
270 | }) | ||
271 | .collect() | ||
272 | } | ||
273 | } | ||
274 | |||
275 | impl LinkId { | ||
276 | pub(crate) fn owner(self, tree: &ModuleTree) -> ModuleId { | ||
277 | tree.links[self].owner | ||
278 | } | ||
279 | pub(crate) fn name(self, tree: &ModuleTree) -> &Name { | ||
280 | &tree.links[self].name | ||
281 | } | ||
282 | pub(crate) fn source( | ||
283 | self, | ||
284 | tree: &ModuleTree, | ||
285 | db: &impl PersistentHirDatabase, | ||
286 | ) -> TreeArc<ast::Module> { | ||
287 | let syntax_node = db.file_item(tree.links[self].source); | ||
288 | ast::Module::cast(&syntax_node).unwrap().to_owned() | ||
289 | } | ||
290 | } | ||
291 | |||
292 | pub(crate) fn resolve_module_declaration( | ||
293 | db: &impl PersistentHirDatabase, | ||
294 | file_id: HirFileId, | ||
295 | name: &Name, | ||
296 | is_root: bool, | ||
297 | ) -> Option<FileId> { | ||
298 | resolve_submodule(db, file_id, name, is_root).0.first().map(|it| *it) | ||
299 | } | ||
300 | |||
301 | fn resolve_submodule( | ||
302 | db: &impl PersistentHirDatabase, | ||
303 | file_id: HirFileId, | ||
304 | name: &Name, | ||
305 | is_root: bool, | ||
306 | ) -> (Vec<FileId>, Option<Problem>) { | ||
307 | // FIXME: handle submodules of inline modules properly | ||
308 | let file_id = file_id.original_file(db); | ||
309 | let source_root_id = db.file_source_root(file_id); | ||
310 | let path = db.file_relative_path(file_id); | ||
311 | let root = RelativePathBuf::default(); | ||
312 | let dir_path = path.parent().unwrap_or(&root); | ||
313 | let mod_name = path.file_stem().unwrap_or("unknown"); | ||
314 | let is_dir_owner = is_root || mod_name == "mod"; | ||
315 | |||
316 | let file_mod = dir_path.join(format!("{}.rs", name)); | ||
317 | let dir_mod = dir_path.join(format!("{}/mod.rs", name)); | ||
318 | let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name)); | ||
319 | let mut candidates = ArrayVec::<[_; 2]>::new(); | ||
320 | if is_dir_owner { | ||
321 | candidates.push(file_mod.clone()); | ||
322 | candidates.push(dir_mod); | ||
323 | } else { | ||
324 | candidates.push(file_dir_mod.clone()); | ||
325 | }; | ||
326 | let sr = db.source_root(source_root_id); | ||
327 | let points_to = candidates | ||
328 | .into_iter() | ||
329 | .filter_map(|path| sr.files.get(&path)) | ||
330 | .map(|&it| it) | ||
331 | .collect::<Vec<_>>(); | ||
332 | let problem = if points_to.is_empty() { | ||
333 | Some(Problem::UnresolvedModule { | ||
334 | candidate: if is_dir_owner { file_mod } else { file_dir_mod }, | ||
335 | }) | ||
336 | } else { | ||
337 | None | ||
338 | }; | ||
339 | (points_to, problem) | ||
340 | } | ||
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 6f98ac071..baffbce6f 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -15,7 +15,7 @@ | |||
15 | //! so that the results of name resolution can be preserved unless the module | 15 | //! so that the results of name resolution can be preserved unless the module |
16 | //! structure itself is modified. | 16 | //! structure itself is modified. |
17 | pub(crate) mod lower; | 17 | pub(crate) mod lower; |
18 | mod crate_def_map; | 18 | pub(crate) mod crate_def_map; |
19 | 19 | ||
20 | use std::{time, sync::Arc}; | 20 | use std::{time, sync::Arc}; |
21 | 21 | ||
@@ -29,8 +29,10 @@ use crate::{ | |||
29 | Module, ModuleDef, | 29 | Module, ModuleDef, |
30 | Path, PathKind, PersistentHirDatabase, | 30 | Path, PathKind, PersistentHirDatabase, |
31 | Crate, Name, | 31 | Crate, Name, |
32 | module_tree::{ModuleId, ModuleTree}, | 32 | nameres::{ |
33 | nameres::lower::{ImportId, LoweredModule, ImportData}, | 33 | crate_def_map::{CrateDefMap, ModuleId}, |
34 | lower::{ImportId, LoweredModule, ImportData} | ||
35 | }, | ||
34 | }; | 36 | }; |
35 | 37 | ||
36 | /// `ItemMap` is the result of module name resolution. It contains, for each | 38 | /// `ItemMap` is the result of module name resolution. It contains, for each |
@@ -160,7 +162,7 @@ struct Resolver<'a, DB> { | |||
160 | db: &'a DB, | 162 | db: &'a DB, |
161 | input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, | 163 | input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, |
162 | krate: Crate, | 164 | krate: Crate, |
163 | module_tree: Arc<ModuleTree>, | 165 | def_map: Arc<CrateDefMap>, |
164 | processed_imports: FxHashSet<(ModuleId, ImportId)>, | 166 | processed_imports: FxHashSet<(ModuleId, ImportId)>, |
165 | /// If module `a` has `use b::*`, then this contains the mapping b -> a (and the import) | 167 | /// If module `a` has `use b::*`, then this contains the mapping b -> a (and the import) |
166 | glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, ImportId)>>, | 168 | glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, ImportId)>>, |
@@ -176,12 +178,11 @@ where | |||
176 | input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, | 178 | input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, |
177 | krate: Crate, | 179 | krate: Crate, |
178 | ) -> Resolver<'a, DB> { | 180 | ) -> Resolver<'a, DB> { |
179 | let module_tree = db.module_tree(krate); | ||
180 | Resolver { | 181 | Resolver { |
181 | db, | 182 | db, |
182 | input, | 183 | input, |
183 | krate, | 184 | krate, |
184 | module_tree, | 185 | def_map: db.crate_def_map(krate), |
185 | processed_imports: FxHashSet::default(), | 186 | processed_imports: FxHashSet::default(), |
186 | glob_imports: FxHashMap::default(), | 187 | glob_imports: FxHashMap::default(), |
187 | result: ItemMap { | 188 | result: ItemMap { |
@@ -254,9 +255,9 @@ where | |||
254 | } | 255 | } |
255 | 256 | ||
256 | // Populate modules | 257 | // Populate modules |
257 | for (name, module_id) in module_id.children(&self.module_tree) { | 258 | for (name, module_id) in self.def_map[module_id].children.iter() { |
258 | let module = Module { module_id, krate: self.krate }; | 259 | let module = Module { module_id: *module_id, krate: self.krate }; |
259 | self.add_module_item(&mut module_items, name, PerNs::types(module.into())); | 260 | self.add_module_item(&mut module_items, name.clone(), PerNs::types(module.into())); |
260 | } | 261 | } |
261 | 262 | ||
262 | self.result.per_module.insert(module_id, module_items); | 263 | self.result.per_module.insert(module_id, module_items); |
@@ -479,8 +480,8 @@ enum ReachedFixedPoint { | |||
479 | impl ItemMap { | 480 | impl ItemMap { |
480 | pub(crate) fn item_map_query(db: &impl PersistentHirDatabase, krate: Crate) -> Arc<ItemMap> { | 481 | pub(crate) fn item_map_query(db: &impl PersistentHirDatabase, krate: Crate) -> Arc<ItemMap> { |
481 | let start = time::Instant::now(); | 482 | let start = time::Instant::now(); |
482 | let module_tree = db.module_tree(krate); | 483 | let def_map = db.crate_def_map(krate); |
483 | let input = module_tree | 484 | let input = def_map |
484 | .modules() | 485 | .modules() |
485 | .map(|module_id| (module_id, db.lower_module(Module { krate, module_id }))) | 486 | .map(|module_id| (module_id, db.lower_module(Module { krate, module_id }))) |
486 | .collect::<FxHashMap<_, _>>(); | 487 | .collect::<FxHashMap<_, _>>(); |
diff --git a/crates/ra_hir/src/nameres/crate_def_map.rs b/crates/ra_hir/src/nameres/crate_def_map.rs index 483878c78..d7ccb6584 100644 --- a/crates/ra_hir/src/nameres/crate_def_map.rs +++ b/crates/ra_hir/src/nameres/crate_def_map.rs | |||
@@ -48,25 +48,40 @@ mod tests; | |||
48 | 48 | ||
49 | use rustc_hash::FxHashMap; | 49 | use rustc_hash::FxHashMap; |
50 | use test_utils::tested_by; | 50 | use test_utils::tested_by; |
51 | use ra_arena::Arena; | 51 | use ra_arena::{Arena, RawId, impl_arena_id}; |
52 | use ra_db::FileId; | ||
53 | |||
54 | use std::sync::Arc; | ||
52 | 55 | ||
53 | use crate::{ | 56 | use crate::{ |
54 | Name, Module, Path, PathKind, ModuleDef, Crate, | 57 | Name, Module, Path, PathKind, ModuleDef, Crate, Problem, HirFileId, |
55 | PersistentHirDatabase, | 58 | PersistentHirDatabase, |
56 | module_tree::ModuleId, | ||
57 | nameres::{ModuleScope, ResolveMode, ResolvePathResult, PerNs, Edition, ReachedFixedPoint}, | 59 | nameres::{ModuleScope, ResolveMode, ResolvePathResult, PerNs, Edition, ReachedFixedPoint}, |
60 | ids::{SourceItemId, SourceFileItemId}, | ||
58 | }; | 61 | }; |
59 | 62 | ||
60 | #[derive(Default, Debug)] | 63 | pub(crate) use self::raw::RawItems; |
61 | struct ModuleData { | 64 | |
62 | parent: Option<ModuleId>, | 65 | #[derive(Default, Debug, PartialEq, Eq)] |
63 | children: FxHashMap<Name, ModuleId>, | 66 | pub(crate) struct ModuleData { |
64 | scope: ModuleScope, | 67 | pub(crate) parent: Option<ModuleId>, |
68 | pub(crate) children: FxHashMap<Name, ModuleId>, | ||
69 | pub(crate) scope: ModuleScope, | ||
70 | /// None for root | ||
71 | pub(crate) declaration: Option<SourceItemId>, | ||
72 | /// None for inline modules. | ||
73 | /// | ||
74 | /// Note that non-inline modules, by definition, live inside non-macro file. | ||
75 | pub(crate) definition: Option<FileId>, | ||
65 | } | 76 | } |
66 | 77 | ||
78 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
79 | pub(crate) struct ModuleId(RawId); | ||
80 | impl_arena_id!(ModuleId); | ||
81 | |||
67 | /// Contans all top-level defs from a macro-expanded crate | 82 | /// Contans all top-level defs from a macro-expanded crate |
68 | #[derive(Debug)] | 83 | #[derive(Debug, PartialEq, Eq)] |
69 | pub(crate) struct CrateDefMap { | 84 | pub struct CrateDefMap { |
70 | krate: Crate, | 85 | krate: Crate, |
71 | edition: Edition, | 86 | edition: Edition, |
72 | /// The prelude module for this crate. This either comes from an import | 87 | /// The prelude module for this crate. This either comes from an import |
@@ -77,19 +92,85 @@ pub(crate) struct CrateDefMap { | |||
77 | root: ModuleId, | 92 | root: ModuleId, |
78 | modules: Arena<ModuleId, ModuleData>, | 93 | modules: Arena<ModuleId, ModuleData>, |
79 | public_macros: FxHashMap<Name, mbe::MacroRules>, | 94 | public_macros: FxHashMap<Name, mbe::MacroRules>, |
95 | problems: CrateDefMapProblems, | ||
96 | } | ||
97 | |||
98 | #[derive(Default, Debug, PartialEq, Eq)] | ||
99 | pub(crate) struct CrateDefMapProblems { | ||
100 | problems: Vec<(SourceItemId, Problem)>, | ||
101 | } | ||
102 | |||
103 | impl CrateDefMapProblems { | ||
104 | fn add(&mut self, source_item_id: SourceItemId, problem: Problem) { | ||
105 | self.problems.push((source_item_id, problem)) | ||
106 | } | ||
107 | |||
108 | pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a SourceItemId, &'a Problem)> + 'a { | ||
109 | self.problems.iter().map(|(s, p)| (s, p)) | ||
110 | } | ||
80 | } | 111 | } |
81 | 112 | ||
82 | impl std::ops::Index<ModuleId> for CrateDefMap { | 113 | impl std::ops::Index<ModuleId> for CrateDefMap { |
83 | type Output = ModuleScope; | 114 | type Output = ModuleData; |
84 | fn index(&self, id: ModuleId) -> &ModuleScope { | 115 | fn index(&self, id: ModuleId) -> &ModuleData { |
85 | &self.modules[id].scope | 116 | &self.modules[id] |
86 | } | 117 | } |
87 | } | 118 | } |
88 | 119 | ||
89 | impl CrateDefMap { | 120 | impl CrateDefMap { |
121 | pub(crate) fn crate_def_map_query( | ||
122 | db: &impl PersistentHirDatabase, | ||
123 | krate: Crate, | ||
124 | ) -> Arc<CrateDefMap> { | ||
125 | let def_map = { | ||
126 | let edition = krate.edition(db); | ||
127 | let mut modules: Arena<ModuleId, ModuleData> = Arena::default(); | ||
128 | let root = modules.alloc(ModuleData::default()); | ||
129 | CrateDefMap { | ||
130 | krate, | ||
131 | edition, | ||
132 | extern_prelude: FxHashMap::default(), | ||
133 | prelude: None, | ||
134 | root, | ||
135 | modules, | ||
136 | public_macros: FxHashMap::default(), | ||
137 | problems: CrateDefMapProblems::default(), | ||
138 | } | ||
139 | }; | ||
140 | let def_map = collector::collect_defs(db, def_map); | ||
141 | Arc::new(def_map) | ||
142 | } | ||
143 | |||
144 | pub(crate) fn root(&self) -> ModuleId { | ||
145 | self.root | ||
146 | } | ||
147 | |||
148 | pub(crate) fn problems(&self) -> &CrateDefMapProblems { | ||
149 | &self.problems | ||
150 | } | ||
151 | |||
152 | pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a { | ||
153 | self.modules.iter().map(|(id, _data)| id) | ||
154 | } | ||
155 | |||
156 | pub(crate) fn find_module_by_source( | ||
157 | &self, | ||
158 | file_id: HirFileId, | ||
159 | decl_id: Option<SourceFileItemId>, | ||
160 | ) -> Option<ModuleId> { | ||
161 | let decl_id = decl_id.map(|it| it.with_file_id(file_id)); | ||
162 | let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| { | ||
163 | if decl_id.is_some() { | ||
164 | module_data.declaration == decl_id | ||
165 | } else { | ||
166 | module_data.definition.map(|it| it.into()) == Some(file_id) | ||
167 | } | ||
168 | })?; | ||
169 | Some(module_id) | ||
170 | } | ||
171 | |||
90 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change | 172 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change |
91 | // the result. | 173 | // the result. |
92 | #[allow(unused)] | ||
93 | fn resolve_path_fp( | 174 | fn resolve_path_fp( |
94 | &self, | 175 | &self, |
95 | db: &impl PersistentHirDatabase, | 176 | db: &impl PersistentHirDatabase, |
@@ -182,7 +263,7 @@ impl CrateDefMap { | |||
182 | ); | 263 | ); |
183 | } | 264 | } |
184 | 265 | ||
185 | match self[module.module_id].items.get(&segment.name) { | 266 | match self[module.module_id].scope.items.get(&segment.name) { |
186 | Some(res) if !res.def.is_none() => res.def, | 267 | Some(res) if !res.def.is_none() => res.def, |
187 | _ => { | 268 | _ => { |
188 | log::debug!("path segment {:?} not found", segment.name); | 269 | log::debug!("path segment {:?} not found", segment.name); |
@@ -225,7 +306,8 @@ impl CrateDefMap { | |||
225 | } | 306 | } |
226 | 307 | ||
227 | fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { | 308 | fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { |
228 | let from_crate_root = self[self.root].items.get(name).map_or(PerNs::none(), |it| it.def); | 309 | let from_crate_root = |
310 | self[self.root].scope.items.get(name).map_or(PerNs::none(), |it| it.def); | ||
229 | let from_extern_prelude = self.resolve_name_in_extern_prelude(name); | 311 | let from_extern_prelude = self.resolve_name_in_extern_prelude(name); |
230 | 312 | ||
231 | from_crate_root.or(from_extern_prelude) | 313 | from_crate_root.or(from_extern_prelude) |
@@ -241,7 +323,7 @@ impl CrateDefMap { | |||
241 | // - current module / scope | 323 | // - current module / scope |
242 | // - extern prelude | 324 | // - extern prelude |
243 | // - std prelude | 325 | // - std prelude |
244 | let from_scope = self[module].items.get(name).map_or(PerNs::none(), |it| it.def); | 326 | let from_scope = self[module].scope.items.get(name).map_or(PerNs::none(), |it| it.def); |
245 | let from_extern_prelude = | 327 | let from_extern_prelude = |
246 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); | 328 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); |
247 | let from_prelude = self.resolve_in_prelude(db, name); | 329 | let from_prelude = self.resolve_in_prelude(db, name); |
@@ -256,7 +338,7 @@ impl CrateDefMap { | |||
256 | fn resolve_in_prelude(&self, db: &impl PersistentHirDatabase, name: &Name) -> PerNs<ModuleDef> { | 338 | fn resolve_in_prelude(&self, db: &impl PersistentHirDatabase, name: &Name) -> PerNs<ModuleDef> { |
257 | if let Some(prelude) = self.prelude { | 339 | if let Some(prelude) = self.prelude { |
258 | let resolution = if prelude.krate == self.krate { | 340 | let resolution = if prelude.krate == self.krate { |
259 | self[prelude.module_id].items.get(name).cloned() | 341 | self[prelude.module_id].scope.items.get(name).cloned() |
260 | } else { | 342 | } else { |
261 | db.item_map(prelude.krate)[prelude.module_id].items.get(name).cloned() | 343 | db.item_map(prelude.krate)[prelude.module_id].items.get(name).cloned() |
262 | }; | 344 | }; |
diff --git a/crates/ra_hir/src/nameres/crate_def_map/collector.rs b/crates/ra_hir/src/nameres/crate_def_map/collector.rs index cd328b755..2fbfa9e34 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/collector.rs +++ b/crates/ra_hir/src/nameres/crate_def_map/collector.rs | |||
@@ -1,42 +1,25 @@ | |||
1 | use std::sync::Arc; | 1 | use arrayvec::ArrayVec; |
2 | |||
3 | use rustc_hash::FxHashMap; | 2 | use rustc_hash::FxHashMap; |
4 | use ra_arena::Arena; | 3 | use relative_path::RelativePathBuf; |
5 | use test_utils::tested_by; | 4 | use test_utils::tested_by; |
5 | use ra_db::FileId; | ||
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, | 8 | Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, |
9 | Crate, PersistentHirDatabase, HirFileId, Name, Path, | 9 | PersistentHirDatabase, HirFileId, Name, Path, Problem, |
10 | KnownName, | 10 | KnownName, |
11 | nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode}, | 11 | nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode}, |
12 | ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, | 12 | ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, |
13 | module_tree::resolve_module_declaration, | ||
14 | }; | 13 | }; |
15 | 14 | ||
16 | use super::{CrateDefMap, ModuleId, ModuleData, raw}; | 15 | use super::{CrateDefMap, ModuleId, ModuleData, raw}; |
17 | 16 | ||
18 | #[allow(unused)] | 17 | pub(super) fn collect_defs( |
19 | pub(crate) fn crate_def_map_query( | ||
20 | db: &impl PersistentHirDatabase, | 18 | db: &impl PersistentHirDatabase, |
21 | krate: Crate, | 19 | mut def_map: CrateDefMap, |
22 | ) -> Arc<CrateDefMap> { | 20 | ) -> CrateDefMap { |
23 | let mut def_map = { | ||
24 | let edition = krate.edition(db); | ||
25 | let mut modules: Arena<ModuleId, ModuleData> = Arena::default(); | ||
26 | let root = modules.alloc(ModuleData::default()); | ||
27 | CrateDefMap { | ||
28 | krate, | ||
29 | edition, | ||
30 | extern_prelude: FxHashMap::default(), | ||
31 | prelude: None, | ||
32 | root, | ||
33 | modules, | ||
34 | public_macros: FxHashMap::default(), | ||
35 | } | ||
36 | }; | ||
37 | |||
38 | // populate external prelude | 21 | // populate external prelude |
39 | for dep in krate.dependencies(db) { | 22 | for dep in def_map.krate.dependencies(db) { |
40 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate); | 23 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate); |
41 | if let Some(module) = dep.krate.root_module(db) { | 24 | if let Some(module) = dep.krate.root_module(db) { |
42 | def_map.extern_prelude.insert(dep.name.clone(), module.into()); | 25 | def_map.extern_prelude.insert(dep.name.clone(), module.into()); |
@@ -52,7 +35,6 @@ pub(crate) fn crate_def_map_query( | |||
52 | 35 | ||
53 | let mut collector = DefCollector { | 36 | let mut collector = DefCollector { |
54 | db, | 37 | db, |
55 | krate, | ||
56 | def_map, | 38 | def_map, |
57 | glob_imports: FxHashMap::default(), | 39 | glob_imports: FxHashMap::default(), |
58 | unresolved_imports: Vec::new(), | 40 | unresolved_imports: Vec::new(), |
@@ -60,14 +42,12 @@ pub(crate) fn crate_def_map_query( | |||
60 | global_macro_scope: FxHashMap::default(), | 42 | global_macro_scope: FxHashMap::default(), |
61 | }; | 43 | }; |
62 | collector.collect(); | 44 | collector.collect(); |
63 | let def_map = collector.finish(); | 45 | collector.finish() |
64 | Arc::new(def_map) | ||
65 | } | 46 | } |
66 | 47 | ||
67 | /// Walks the tree of module recursively | 48 | /// Walks the tree of module recursively |
68 | struct DefCollector<DB> { | 49 | struct DefCollector<DB> { |
69 | db: DB, | 50 | db: DB, |
70 | krate: Crate, | ||
71 | def_map: CrateDefMap, | 51 | def_map: CrateDefMap, |
72 | glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, raw::ImportId)>>, | 52 | glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, raw::ImportId)>>, |
73 | unresolved_imports: Vec<(ModuleId, raw::ImportId, raw::ImportData)>, | 53 | unresolved_imports: Vec<(ModuleId, raw::ImportId, raw::ImportData)>, |
@@ -75,23 +55,16 @@ struct DefCollector<DB> { | |||
75 | global_macro_scope: FxHashMap<Name, mbe::MacroRules>, | 55 | global_macro_scope: FxHashMap<Name, mbe::MacroRules>, |
76 | } | 56 | } |
77 | 57 | ||
78 | /// Walks a single module, populating defs, imports and macros | ||
79 | struct ModCollector<'a, D> { | ||
80 | def_collector: D, | ||
81 | module_id: ModuleId, | ||
82 | file_id: HirFileId, | ||
83 | raw_items: &'a raw::RawItems, | ||
84 | } | ||
85 | |||
86 | impl<'a, DB> DefCollector<&'a DB> | 58 | impl<'a, DB> DefCollector<&'a DB> |
87 | where | 59 | where |
88 | DB: PersistentHirDatabase, | 60 | DB: PersistentHirDatabase, |
89 | { | 61 | { |
90 | fn collect(&mut self) { | 62 | fn collect(&mut self) { |
91 | let crate_graph = self.db.crate_graph(); | 63 | let crate_graph = self.db.crate_graph(); |
92 | let file_id = crate_graph.crate_root(self.krate.crate_id()); | 64 | let file_id = crate_graph.crate_root(self.def_map.krate.crate_id()); |
93 | let raw_items = raw::RawItems::raw_items_query(self.db, file_id); | 65 | let raw_items = self.db.raw_items(file_id); |
94 | let module_id = self.def_map.root; | 66 | let module_id = self.def_map.root; |
67 | self.def_map.modules[module_id].definition = Some(file_id); | ||
95 | ModCollector { | 68 | ModCollector { |
96 | def_collector: &mut *self, | 69 | def_collector: &mut *self, |
97 | module_id, | 70 | module_id, |
@@ -123,10 +96,6 @@ where | |||
123 | } | 96 | } |
124 | } | 97 | } |
125 | 98 | ||
126 | fn alloc_module(&mut self) -> ModuleId { | ||
127 | self.def_map.modules.alloc(ModuleData::default()) | ||
128 | } | ||
129 | |||
130 | fn resolve_imports(&mut self) -> ReachedFixedPoint { | 99 | fn resolve_imports(&mut self) -> ReachedFixedPoint { |
131 | let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); | 100 | let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); |
132 | let mut resolved = Vec::new(); | 101 | let mut resolved = Vec::new(); |
@@ -184,7 +153,7 @@ where | |||
184 | if import.is_prelude { | 153 | if import.is_prelude { |
185 | tested_by!(std_prelude); | 154 | tested_by!(std_prelude); |
186 | self.def_map.prelude = Some(m); | 155 | self.def_map.prelude = Some(m); |
187 | } else if m.krate != self.krate { | 156 | } else if m.krate != self.def_map.krate { |
188 | tested_by!(glob_across_crates); | 157 | tested_by!(glob_across_crates); |
189 | // glob import from other crate => we can just import everything once | 158 | // glob import from other crate => we can just import everything once |
190 | let item_map = self.db.item_map(m.krate); | 159 | let item_map = self.db.item_map(m.krate); |
@@ -199,7 +168,7 @@ where | |||
199 | // glob import from same crate => we do an initial | 168 | // glob import from same crate => we do an initial |
200 | // import, and then need to propagate any further | 169 | // import, and then need to propagate any further |
201 | // additions | 170 | // additions |
202 | let scope = &self.def_map[m.module_id]; | 171 | let scope = &self.def_map[m.module_id].scope; |
203 | let items = scope | 172 | let items = scope |
204 | .items | 173 | .items |
205 | .iter() | 174 | .iter() |
@@ -243,11 +212,9 @@ where | |||
243 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); | 212 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); |
244 | 213 | ||
245 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 | 214 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 |
246 | if let Some(root_module) = self.krate.root_module(self.db) { | 215 | if import.is_extern_crate && module_id == self.def_map.root { |
247 | if import.is_extern_crate && module_id == root_module.module_id { | 216 | if let Some(def) = def.take_types() { |
248 | if let Some(def) = def.take_types() { | 217 | self.def_map.extern_prelude.insert(name.clone(), def); |
249 | self.def_map.extern_prelude.insert(name.clone(), def); | ||
250 | } | ||
251 | } | 218 | } |
252 | } | 219 | } |
253 | let resolution = Resolution { def, import: Some(import_id) }; | 220 | let resolution = Resolution { def, import: Some(import_id) }; |
@@ -324,8 +291,7 @@ where | |||
324 | Some(it) => it, | 291 | Some(it) => it, |
325 | _ => return true, | 292 | _ => return true, |
326 | }; | 293 | }; |
327 | // FIXME: this should be a proper query | 294 | let def_map = self.db.crate_def_map(krate); |
328 | let def_map = crate_def_map_query(self.db, krate); | ||
329 | let rules = def_map.public_macros.get(&path.segments[1].name).cloned(); | 295 | let rules = def_map.public_macros.get(&path.segments[1].name).cloned(); |
330 | resolved.push((*module_id, *call_id, rules, tt.clone())); | 296 | resolved.push((*module_id, *call_id, rules, tt.clone())); |
331 | false | 297 | false |
@@ -367,6 +333,14 @@ where | |||
367 | } | 333 | } |
368 | } | 334 | } |
369 | 335 | ||
336 | /// Walks a single module, populating defs, imports and macros | ||
337 | struct ModCollector<'a, D> { | ||
338 | def_collector: D, | ||
339 | module_id: ModuleId, | ||
340 | file_id: HirFileId, | ||
341 | raw_items: &'a raw::RawItems, | ||
342 | } | ||
343 | |||
370 | impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> | 344 | impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> |
371 | where | 345 | where |
372 | DB: PersistentHirDatabase, | 346 | DB: PersistentHirDatabase, |
@@ -389,8 +363,12 @@ where | |||
389 | fn collect_module(&mut self, module: &raw::ModuleData) { | 363 | fn collect_module(&mut self, module: &raw::ModuleData) { |
390 | match module { | 364 | match module { |
391 | // inline module, just recurse | 365 | // inline module, just recurse |
392 | raw::ModuleData::Definition { name, items } => { | 366 | raw::ModuleData::Definition { name, items, source_item_id } => { |
393 | let module_id = self.push_child_module(name.clone()); | 367 | let module_id = self.push_child_module( |
368 | name.clone(), | ||
369 | source_item_id.with_file_id(self.file_id), | ||
370 | None, | ||
371 | ); | ||
394 | ModCollector { | 372 | ModCollector { |
395 | def_collector: &mut *self.def_collector, | 373 | def_collector: &mut *self.def_collector, |
396 | module_id, | 374 | module_id, |
@@ -400,13 +378,20 @@ where | |||
400 | .collect(&*items); | 378 | .collect(&*items); |
401 | } | 379 | } |
402 | // out of line module, resovle, parse and recurse | 380 | // out of line module, resovle, parse and recurse |
403 | raw::ModuleData::Declaration { name } => { | 381 | raw::ModuleData::Declaration { name, source_item_id } => { |
404 | let module_id = self.push_child_module(name.clone()); | 382 | let source_item_id = source_item_id.with_file_id(self.file_id); |
405 | let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); | 383 | let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); |
406 | if let Some(file_id) = | 384 | let (file_ids, problem) = |
407 | resolve_module_declaration(self.def_collector.db, self.file_id, name, is_root) | 385 | resolve_submodule(self.def_collector.db, self.file_id, name, is_root); |
408 | { | 386 | |
409 | let raw_items = raw::RawItems::raw_items_query(self.def_collector.db, file_id); | 387 | if let Some(problem) = problem { |
388 | self.def_collector.def_map.problems.add(source_item_id, problem) | ||
389 | } | ||
390 | |||
391 | if let Some(&file_id) = file_ids.first() { | ||
392 | let module_id = | ||
393 | self.push_child_module(name.clone(), source_item_id, Some(file_id)); | ||
394 | let raw_items = self.def_collector.db.raw_items(file_id); | ||
410 | ModCollector { | 395 | ModCollector { |
411 | def_collector: &mut *self.def_collector, | 396 | def_collector: &mut *self.def_collector, |
412 | module_id, | 397 | module_id, |
@@ -419,15 +404,23 @@ where | |||
419 | } | 404 | } |
420 | } | 405 | } |
421 | 406 | ||
422 | fn push_child_module(&mut self, name: Name) -> ModuleId { | 407 | fn push_child_module( |
423 | let res = self.def_collector.alloc_module(); | 408 | &mut self, |
424 | self.def_collector.def_map.modules[res].parent = Some(self.module_id); | 409 | name: Name, |
425 | self.def_collector.def_map.modules[self.module_id].children.insert(name, res); | 410 | declaration: SourceItemId, |
411 | definition: Option<FileId>, | ||
412 | ) -> ModuleId { | ||
413 | let modules = &mut self.def_collector.def_map.modules; | ||
414 | let res = modules.alloc(ModuleData::default()); | ||
415 | modules[res].parent = Some(self.module_id); | ||
416 | modules[res].declaration = Some(declaration); | ||
417 | modules[res].definition = definition; | ||
418 | modules[self.module_id].children.insert(name, res); | ||
426 | res | 419 | res |
427 | } | 420 | } |
428 | 421 | ||
429 | fn define_def(&mut self, def: &raw::DefData) { | 422 | fn define_def(&mut self, def: &raw::DefData) { |
430 | let module = Module { krate: self.def_collector.krate, module_id: self.module_id }; | 423 | let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id }; |
431 | let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into()); | 424 | let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into()); |
432 | macro_rules! id { | 425 | macro_rules! id { |
433 | () => { | 426 | () => { |
@@ -462,7 +455,7 @@ where | |||
462 | 455 | ||
463 | let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id }; | 456 | let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id }; |
464 | let macro_call_id = MacroCallLoc { | 457 | let macro_call_id = MacroCallLoc { |
465 | module: Module { krate: self.def_collector.krate, module_id: self.module_id }, | 458 | module: Module { krate: self.def_collector.def_map.krate, module_id: self.module_id }, |
466 | source_item_id, | 459 | source_item_id, |
467 | } | 460 | } |
468 | .id(self.def_collector.db); | 461 | .id(self.def_collector.db); |
@@ -491,3 +484,44 @@ where | |||
491 | fn is_macro_rules(path: &Path) -> bool { | 484 | fn is_macro_rules(path: &Path) -> bool { |
492 | path.as_ident().and_then(Name::as_known_name) == Some(KnownName::MacroRules) | 485 | path.as_ident().and_then(Name::as_known_name) == Some(KnownName::MacroRules) |
493 | } | 486 | } |
487 | |||
488 | fn resolve_submodule( | ||
489 | db: &impl PersistentHirDatabase, | ||
490 | file_id: HirFileId, | ||
491 | name: &Name, | ||
492 | is_root: bool, | ||
493 | ) -> (Vec<FileId>, Option<Problem>) { | ||
494 | // FIXME: handle submodules of inline modules properly | ||
495 | let file_id = file_id.original_file(db); | ||
496 | let source_root_id = db.file_source_root(file_id); | ||
497 | let path = db.file_relative_path(file_id); | ||
498 | let root = RelativePathBuf::default(); | ||
499 | let dir_path = path.parent().unwrap_or(&root); | ||
500 | let mod_name = path.file_stem().unwrap_or("unknown"); | ||
501 | let is_dir_owner = is_root || mod_name == "mod"; | ||
502 | |||
503 | let file_mod = dir_path.join(format!("{}.rs", name)); | ||
504 | let dir_mod = dir_path.join(format!("{}/mod.rs", name)); | ||
505 | let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name)); | ||
506 | let mut candidates = ArrayVec::<[_; 2]>::new(); | ||
507 | if is_dir_owner { | ||
508 | candidates.push(file_mod.clone()); | ||
509 | candidates.push(dir_mod); | ||
510 | } else { | ||
511 | candidates.push(file_dir_mod.clone()); | ||
512 | }; | ||
513 | let sr = db.source_root(source_root_id); | ||
514 | let points_to = candidates | ||
515 | .into_iter() | ||
516 | .filter_map(|path| sr.files.get(&path)) | ||
517 | .map(|&it| it) | ||
518 | .collect::<Vec<_>>(); | ||
519 | let problem = if points_to.is_empty() { | ||
520 | Some(Problem::UnresolvedModule { | ||
521 | candidate: if is_dir_owner { file_mod } else { file_dir_mod }, | ||
522 | }) | ||
523 | } else { | ||
524 | None | ||
525 | }; | ||
526 | (points_to, problem) | ||
527 | } | ||
diff --git a/crates/ra_hir/src/nameres/crate_def_map/raw.rs b/crates/ra_hir/src/nameres/crate_def_map/raw.rs index fe832b8da..f064f722c 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/raw.rs +++ b/crates/ra_hir/src/nameres/crate_def_map/raw.rs | |||
@@ -3,6 +3,7 @@ use std::{ | |||
3 | ops::Index, | 3 | ops::Index, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use test_utils::tested_by; | ||
6 | use ra_db::FileId; | 7 | use ra_db::FileId; |
7 | use ra_arena::{Arena, impl_arena_id, RawId}; | 8 | use ra_arena::{Arena, impl_arena_id, RawId}; |
8 | use ra_syntax::{ | 9 | use ra_syntax::{ |
@@ -15,8 +16,8 @@ use crate::{ | |||
15 | ids::{SourceFileItemId, SourceFileItems}, | 16 | ids::{SourceFileItemId, SourceFileItems}, |
16 | }; | 17 | }; |
17 | 18 | ||
18 | #[derive(Default, PartialEq, Eq)] | 19 | #[derive(Debug, Default, PartialEq, Eq)] |
19 | pub(crate) struct RawItems { | 20 | pub struct RawItems { |
20 | modules: Arena<Module, ModuleData>, | 21 | modules: Arena<Module, ModuleData>, |
21 | imports: Arena<ImportId, ImportData>, | 22 | imports: Arena<ImportId, ImportData>, |
22 | defs: Arena<Def, DefData>, | 23 | defs: Arena<Def, DefData>, |
@@ -26,18 +27,21 @@ pub(crate) struct RawItems { | |||
26 | } | 27 | } |
27 | 28 | ||
28 | impl RawItems { | 29 | impl RawItems { |
29 | pub(crate) fn items(&self) -> &[RawItem] { | 30 | pub(crate) fn raw_items_query( |
30 | &self.items | 31 | db: &impl PersistentHirDatabase, |
31 | } | 32 | file_id: FileId, |
32 | 33 | ) -> Arc<RawItems> { | |
33 | pub(crate) fn raw_items_query(db: &impl PersistentHirDatabase, file_id: FileId) -> RawItems { | ||
34 | let mut collector = RawItemsCollector { | 34 | let mut collector = RawItemsCollector { |
35 | raw_items: RawItems::default(), | 35 | raw_items: RawItems::default(), |
36 | source_file_items: db.file_items(file_id.into()), | 36 | source_file_items: db.file_items(file_id.into()), |
37 | }; | 37 | }; |
38 | let source_file = db.parse(file_id); | 38 | let source_file = db.parse(file_id); |
39 | collector.process_module(None, &*source_file); | 39 | collector.process_module(None, &*source_file); |
40 | collector.raw_items | 40 | Arc::new(collector.raw_items) |
41 | } | ||
42 | |||
43 | pub(crate) fn items(&self) -> &[RawItem] { | ||
44 | &self.items | ||
41 | } | 45 | } |
42 | 46 | ||
43 | // We can't use queries during name resolution for fear of cycles, so this | 47 | // We can't use queries during name resolution for fear of cycles, so this |
@@ -81,7 +85,7 @@ impl Index<Macro> for RawItems { | |||
81 | } | 85 | } |
82 | } | 86 | } |
83 | 87 | ||
84 | #[derive(PartialEq, Eq, Clone, Copy)] | 88 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] |
85 | pub(crate) enum RawItem { | 89 | pub(crate) enum RawItem { |
86 | Module(Module), | 90 | Module(Module), |
87 | Import(ImportId), | 91 | Import(ImportId), |
@@ -89,24 +93,24 @@ pub(crate) enum RawItem { | |||
89 | Macro(Macro), | 93 | Macro(Macro), |
90 | } | 94 | } |
91 | 95 | ||
92 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | 96 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
93 | pub(crate) struct Module(RawId); | 97 | pub(crate) struct Module(RawId); |
94 | impl_arena_id!(Module); | 98 | impl_arena_id!(Module); |
95 | 99 | ||
96 | #[derive(PartialEq, Eq)] | 100 | #[derive(Debug, PartialEq, Eq)] |
97 | pub(crate) enum ModuleData { | 101 | pub(crate) enum ModuleData { |
98 | Declaration { name: Name }, | 102 | Declaration { name: Name, source_item_id: SourceFileItemId }, |
99 | Definition { name: Name, items: Vec<RawItem> }, | 103 | Definition { name: Name, source_item_id: SourceFileItemId, items: Vec<RawItem> }, |
100 | } | 104 | } |
101 | 105 | ||
102 | pub(crate) use crate::nameres::lower::ImportId; | 106 | pub(crate) use crate::nameres::lower::ImportId; |
103 | pub(super) use crate::nameres::lower::ImportData; | 107 | pub(super) use crate::nameres::lower::ImportData; |
104 | 108 | ||
105 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | 109 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
106 | pub(crate) struct Def(RawId); | 110 | pub(crate) struct Def(RawId); |
107 | impl_arena_id!(Def); | 111 | impl_arena_id!(Def); |
108 | 112 | ||
109 | #[derive(PartialEq, Eq)] | 113 | #[derive(Debug, PartialEq, Eq)] |
110 | pub(crate) struct DefData { | 114 | pub(crate) struct DefData { |
111 | pub(crate) source_item_id: SourceFileItemId, | 115 | pub(crate) source_item_id: SourceFileItemId, |
112 | pub(crate) name: Name, | 116 | pub(crate) name: Name, |
@@ -124,11 +128,11 @@ pub(crate) enum DefKind { | |||
124 | TypeAlias, | 128 | TypeAlias, |
125 | } | 129 | } |
126 | 130 | ||
127 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | 131 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
128 | pub(crate) struct Macro(RawId); | 132 | pub(crate) struct Macro(RawId); |
129 | impl_arena_id!(Macro); | 133 | impl_arena_id!(Macro); |
130 | 134 | ||
131 | #[derive(PartialEq, Eq)] | 135 | #[derive(Debug, PartialEq, Eq)] |
132 | pub(crate) struct MacroData { | 136 | pub(crate) struct MacroData { |
133 | pub(crate) source_item_id: SourceFileItemId, | 137 | pub(crate) source_item_id: SourceFileItemId, |
134 | pub(crate) path: Path, | 138 | pub(crate) path: Path, |
@@ -191,18 +195,25 @@ impl RawItemsCollector { | |||
191 | Some(it) => it.as_name(), | 195 | Some(it) => it.as_name(), |
192 | None => return, | 196 | None => return, |
193 | }; | 197 | }; |
198 | let source_item_id = self.source_file_items.id_of_unchecked(module.syntax()); | ||
194 | if module.has_semi() { | 199 | if module.has_semi() { |
195 | let item = self.raw_items.modules.alloc(ModuleData::Declaration { name }); | 200 | let item = |
201 | self.raw_items.modules.alloc(ModuleData::Declaration { name, source_item_id }); | ||
196 | self.push_item(current_module, RawItem::Module(item)); | 202 | self.push_item(current_module, RawItem::Module(item)); |
197 | return; | 203 | return; |
198 | } | 204 | } |
199 | 205 | ||
200 | if let Some(item_list) = module.item_list() { | 206 | if let Some(item_list) = module.item_list() { |
201 | let item = | 207 | let item = self.raw_items.modules.alloc(ModuleData::Definition { |
202 | self.raw_items.modules.alloc(ModuleData::Definition { name, items: Vec::new() }); | 208 | name, |
209 | source_item_id, | ||
210 | items: Vec::new(), | ||
211 | }); | ||
203 | self.process_module(Some(item), item_list); | 212 | self.process_module(Some(item), item_list); |
204 | self.push_item(current_module, RawItem::Module(item)); | 213 | self.push_item(current_module, RawItem::Module(item)); |
214 | return; | ||
205 | } | 215 | } |
216 | tested_by!(name_res_works_for_broken_modules); | ||
206 | } | 217 | } |
207 | 218 | ||
208 | fn add_use_item(&mut self, current_module: Option<Module>, use_item: &ast::UseItem) { | 219 | fn add_use_item(&mut self, current_module: Option<Module>, use_item: &ast::UseItem) { |
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests.rs b/crates/ra_hir/src/nameres/crate_def_map/tests.rs index a56dbaf90..742a19e5c 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/tests.rs +++ b/crates/ra_hir/src/nameres/crate_def_map/tests.rs | |||
@@ -15,7 +15,7 @@ fn compute_crate_def_map(fixture: &str, graph: Option<CrateGraphFixture>) -> Arc | |||
15 | } | 15 | } |
16 | let crate_id = db.crate_graph().iter().next().unwrap(); | 16 | let crate_id = db.crate_graph().iter().next().unwrap(); |
17 | let krate = Crate { crate_id }; | 17 | let krate = Crate { crate_id }; |
18 | collector::crate_def_map_query(&db, krate) | 18 | db.crate_def_map(krate) |
19 | } | 19 | } |
20 | 20 | ||
21 | fn render_crate_def_map(map: &CrateDefMap) -> String { | 21 | fn render_crate_def_map(map: &CrateDefMap) -> String { |
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index 9b151bb0c..961e442a9 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -7,7 +7,7 @@ use crate::{ | |||
7 | ItemMap, | 7 | ItemMap, |
8 | PersistentHirDatabase, | 8 | PersistentHirDatabase, |
9 | mock::MockDatabase, | 9 | mock::MockDatabase, |
10 | module_tree::ModuleId, | 10 | nameres::crate_def_map::ModuleId, |
11 | }; | 11 | }; |
12 | use super::Resolution; | 12 | use super::Resolution; |
13 | 13 | ||
@@ -359,6 +359,7 @@ fn std_prelude() { | |||
359 | let main_id = db.file_id_of("/main.rs"); | 359 | let main_id = db.file_id_of("/main.rs"); |
360 | 360 | ||
361 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | 361 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); |
362 | eprintln!("module = {:?}", module); | ||
362 | let krate = module.krate(&db).unwrap(); | 363 | let krate = module.krate(&db).unwrap(); |
363 | let item_map = db.item_map(krate); | 364 | let item_map = db.item_map(krate); |
364 | 365 | ||
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 4a9921a85..62b699a64 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -80,8 +80,8 @@ fn module_from_source( | |||
80 | let source_root_id = db.file_source_root(file_id.as_original_file()); | 80 | let source_root_id = db.file_source_root(file_id.as_original_file()); |
81 | db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map( | 81 | db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map( |
82 | |krate| { | 82 | |krate| { |
83 | let module_tree = db.module_tree(krate); | 83 | let def_map = db.crate_def_map(krate); |
84 | let module_id = module_tree.find_module_by_source(file_id, decl_id)?; | 84 | let module_id = def_map.find_module_by_source(file_id, decl_id)?; |
85 | Some(Module { krate, module_id }) | 85 | Some(Module { krate, module_id }) |
86 | }, | 86 | }, |
87 | ) | 87 | ) |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 94b757af2..7c77474b0 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -7,10 +7,12 @@ use std::sync::Arc; | |||
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | HirDatabase, module_tree::ModuleId, Module, Crate, Name, Function, Trait, | 10 | HirDatabase, Module, Crate, Name, Function, Trait, |
11 | ids::TraitId, | 11 | ids::TraitId, |
12 | impl_block::{ImplId, ImplBlock, ImplItem}, | 12 | impl_block::{ImplId, ImplBlock, ImplItem}, |
13 | ty::{AdtDef, Ty}, | 13 | ty::{AdtDef, Ty}, |
14 | nameres::crate_def_map::ModuleId, | ||
15 | |||
14 | }; | 16 | }; |
15 | 17 | ||
16 | /// This is used as a key for indexing impls. | 18 | /// This is used as a key for indexing impls. |
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs index d64b5a4e0..2395930f0 100644 --- a/crates/ra_ide_api/src/runnables.rs +++ b/crates/ra_ide_api/src/runnables.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use itertools::Itertools; | 1 | use itertools::Itertools; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | TextRange, SyntaxNode, | 3 | TextRange, SyntaxNode, |
4 | ast::{self, AstNode, NameOwner, ModuleItemOwner}, | 4 | ast::{self, AstNode, NameOwner, ModuleItemOwner, AttrsOwner}, |
5 | }; | 5 | }; |
6 | use ra_db::SourceDatabase; | 6 | use ra_db::SourceDatabase; |
7 | 7 | ||