diff options
author | Aleksey Kladov <[email protected]> | 2018-11-21 08:16:46 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-11-21 08:16:46 +0000 |
commit | 02c4f823485fb5302b8f8eb6fee84122ca73979c (patch) | |
tree | 48a495152b3aad1183c5f74419c61748f26c64e1 | |
parent | 36aad851383c7fd1ca5ffaa99ba8cc96b85378c1 (diff) |
simple test for item map
-rw-r--r-- | crates/ra_analysis/src/db.rs | 3 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/mod.rs | 6 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/mod.rs | 7 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/nameres.rs | 119 |
4 files changed, 118 insertions, 17 deletions
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index cecce3447..9a5cd4b24 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs | |||
@@ -8,7 +8,7 @@ use crate::{ | |||
8 | db, | 8 | db, |
9 | descriptors::{ | 9 | descriptors::{ |
10 | DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery, | 10 | DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery, |
11 | SubmodulesQuery, ItemMapQuery, | 11 | SubmodulesQuery, ItemMapQuery, InputModuleItemsQuery, |
12 | }, | 12 | }, |
13 | symbol_index::SymbolIndex, | 13 | symbol_index::SymbolIndex, |
14 | syntax_ptr::SyntaxPtr, | 14 | syntax_ptr::SyntaxPtr, |
@@ -86,6 +86,7 @@ salsa::database_storage! { | |||
86 | impl DescriptorDatabase { | 86 | impl DescriptorDatabase { |
87 | fn module_tree() for ModuleTreeQuery; | 87 | fn module_tree() for ModuleTreeQuery; |
88 | fn fn_scopes() for FnScopesQuery; | 88 | fn fn_scopes() for FnScopesQuery; |
89 | fn _input_module_items() for InputModuleItemsQuery; | ||
89 | fn _item_map() for ItemMapQuery; | 90 | fn _item_map() for ItemMapQuery; |
90 | fn _module_scope() for ModuleScopeQuery; | 91 | fn _module_scope() for ModuleScopeQuery; |
91 | fn _fn_syntax() for FnSyntaxQuery; | 92 | fn _fn_syntax() for FnSyntaxQuery; |
diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs index 30bc5eca2..a32042b84 100644 --- a/crates/ra_analysis/src/descriptors/mod.rs +++ b/crates/ra_analysis/src/descriptors/mod.rs | |||
@@ -11,7 +11,7 @@ use ra_syntax::{ | |||
11 | use crate::{ | 11 | use crate::{ |
12 | db::SyntaxDatabase, | 12 | db::SyntaxDatabase, |
13 | descriptors::function::{resolve_local_name, FnId, FnScopes}, | 13 | descriptors::function::{resolve_local_name, FnId, FnScopes}, |
14 | descriptors::module::{ModuleId, ModuleScope, ModuleTree, ModuleSource, nameres::ItemMap}, | 14 | descriptors::module::{ModuleId, ModuleScope, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems}}, |
15 | input::SourceRootId, | 15 | input::SourceRootId, |
16 | loc2id::IdDatabase, | 16 | loc2id::IdDatabase, |
17 | syntax_ptr::LocalSyntaxPtr, | 17 | syntax_ptr::LocalSyntaxPtr, |
@@ -25,6 +25,10 @@ salsa::query_group! { | |||
25 | use fn function::imp::fn_scopes; | 25 | use fn function::imp::fn_scopes; |
26 | } | 26 | } |
27 | 27 | ||
28 | fn _input_module_items(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<InputModuleItems>> { | ||
29 | type InputModuleItemsQuery; | ||
30 | use fn module::nameres::input_module_items; | ||
31 | } | ||
28 | fn _item_map(source_root_id: SourceRootId) -> Cancelable<Arc<ItemMap>> { | 32 | fn _item_map(source_root_id: SourceRootId) -> Cancelable<Arc<ItemMap>> { |
29 | type ItemMapQuery; | 33 | type ItemMapQuery; |
30 | use fn module::nameres::item_map; | 34 | use fn module::nameres::item_map; |
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index 124926a40..95d9bcc27 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs | |||
@@ -149,6 +149,13 @@ pub(crate) struct ModuleTree { | |||
149 | } | 149 | } |
150 | 150 | ||
151 | impl ModuleTree { | 151 | impl ModuleTree { |
152 | fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a { | ||
153 | self.mods | ||
154 | .iter() | ||
155 | .enumerate() | ||
156 | .map(|(idx, _)| ModuleId(idx as u32)) | ||
157 | } | ||
158 | |||
152 | fn modules_for_source(&self, source: ModuleSource) -> Vec<ModuleId> { | 159 | fn modules_for_source(&self, source: ModuleSource) -> Vec<ModuleId> { |
153 | self.mods | 160 | self.mods |
154 | .iter() | 161 | .iter() |
diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 657e5bd1c..2fae93c9d 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs | |||
@@ -5,7 +5,7 @@ use rustc_hash::FxHashMap; | |||
5 | 5 | ||
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
7 | SmolStr, SyntaxKind::{self, *}, | 7 | SmolStr, SyntaxKind::{self, *}, |
8 | ast::{self, NameOwner, AstNode} | 8 | ast::{self, NameOwner, AstNode, ModuleItemOwner} |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
@@ -13,9 +13,9 @@ use crate::{ | |||
13 | loc2id::{DefId, DefLoc}, | 13 | loc2id::{DefId, DefLoc}, |
14 | descriptors::{ | 14 | descriptors::{ |
15 | DescriptorDatabase, | 15 | DescriptorDatabase, |
16 | module::{ModuleId, ModuleTree}, | 16 | module::{ModuleId, ModuleTree, ModuleSourceNode}, |
17 | }, | 17 | }, |
18 | syntax_ptr::{LocalSyntaxPtr, SyntaxPtr}, | 18 | syntax_ptr::{LocalSyntaxPtr}, |
19 | input::SourceRootId, | 19 | input::SourceRootId, |
20 | }; | 20 | }; |
21 | 21 | ||
@@ -25,20 +25,20 @@ use crate::{ | |||
25 | /// This stands in-between raw syntax and name resolution and alow us to avoid | 25 | /// This stands in-between raw syntax and name resolution and alow us to avoid |
26 | /// recomputing name res: if `InputModuleItems` are the same, we can avoid | 26 | /// recomputing name res: if `InputModuleItems` are the same, we can avoid |
27 | /// running name resolution. | 27 | /// running name resolution. |
28 | #[derive(Debug, Default)] | 28 | #[derive(Debug, Default, PartialEq, Eq)] |
29 | struct InputModuleItems { | 29 | pub(crate) struct InputModuleItems { |
30 | items: Vec<ModuleItem>, | 30 | items: Vec<ModuleItem>, |
31 | glob_imports: Vec<Path>, | 31 | glob_imports: Vec<Path>, |
32 | imports: Vec<Path>, | 32 | imports: Vec<Path>, |
33 | } | 33 | } |
34 | 34 | ||
35 | #[derive(Debug, Clone)] | 35 | #[derive(Debug, Clone, PartialEq, Eq)] |
36 | struct Path { | 36 | struct Path { |
37 | kind: PathKind, | 37 | kind: PathKind, |
38 | segments: Vec<(LocalSyntaxPtr, SmolStr)>, | 38 | segments: Vec<(LocalSyntaxPtr, SmolStr)>, |
39 | } | 39 | } |
40 | 40 | ||
41 | #[derive(Debug, Clone, Copy)] | 41 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
42 | enum PathKind { | 42 | enum PathKind { |
43 | Abs, | 43 | Abs, |
44 | Self_, | 44 | Self_, |
@@ -46,16 +46,58 @@ enum PathKind { | |||
46 | Crate, | 46 | Crate, |
47 | } | 47 | } |
48 | 48 | ||
49 | pub(crate) fn input_module_items( | ||
50 | db: &impl DescriptorDatabase, | ||
51 | source_root: SourceRootId, | ||
52 | module_id: ModuleId, | ||
53 | ) -> Cancelable<Arc<InputModuleItems>> { | ||
54 | let module_tree = db._module_tree(source_root)?; | ||
55 | let source = module_id.source(&module_tree); | ||
56 | let res = match source.resolve(db) { | ||
57 | ModuleSourceNode::SourceFile(it) => { | ||
58 | let items = it.borrowed().items(); | ||
59 | InputModuleItems::new(items) | ||
60 | } | ||
61 | ModuleSourceNode::Module(it) => { | ||
62 | let items = it | ||
63 | .borrowed() | ||
64 | .item_list() | ||
65 | .into_iter() | ||
66 | .flat_map(|it| it.items()); | ||
67 | InputModuleItems::new(items) | ||
68 | } | ||
69 | }; | ||
70 | Ok(Arc::new(res)) | ||
71 | } | ||
72 | |||
49 | pub(crate) fn item_map( | 73 | pub(crate) fn item_map( |
50 | db: &impl DescriptorDatabase, | 74 | db: &impl DescriptorDatabase, |
51 | source_root: SourceRootId, | 75 | source_root: SourceRootId, |
52 | ) -> Cancelable<Arc<ItemMap>> { | 76 | ) -> Cancelable<Arc<ItemMap>> { |
53 | unimplemented!() | 77 | let module_tree = db._module_tree(source_root)?; |
78 | let input = module_tree | ||
79 | .modules() | ||
80 | .map(|id| { | ||
81 | let items = db._input_module_items(source_root, id)?; | ||
82 | Ok((id, items)) | ||
83 | }) | ||
84 | .collect::<Cancelable<FxHashMap<_, _>>>()?; | ||
85 | |||
86 | let mut resolver = Resolver { | ||
87 | db: db, | ||
88 | input: &input, | ||
89 | source_root, | ||
90 | module_tree, | ||
91 | result: ItemMap::default(), | ||
92 | }; | ||
93 | resolver.resolve()?; | ||
94 | let res = resolver.result; | ||
95 | Ok(Arc::new(res)) | ||
54 | } | 96 | } |
55 | 97 | ||
56 | /// Item map is the result of the name resolution. Item map contains, for each | 98 | /// Item map is the result of the name resolution. Item map contains, for each |
57 | /// module, the set of visible items. | 99 | /// module, the set of visible items. |
58 | #[derive(Debug, PartialEq, Eq)] | 100 | #[derive(Default, Debug, PartialEq, Eq)] |
59 | pub(crate) struct ItemMap { | 101 | pub(crate) struct ItemMap { |
60 | per_module: FxHashMap<ModuleId, ModuleItems>, | 102 | per_module: FxHashMap<ModuleId, ModuleItems>, |
61 | } | 103 | } |
@@ -86,7 +128,7 @@ struct PerNs<T> { | |||
86 | values: Option<T>, | 128 | values: Option<T>, |
87 | } | 129 | } |
88 | 130 | ||
89 | #[derive(Debug)] | 131 | #[derive(Debug, PartialEq, Eq)] |
90 | struct ModuleItem { | 132 | struct ModuleItem { |
91 | ptr: LocalSyntaxPtr, | 133 | ptr: LocalSyntaxPtr, |
92 | name: SmolStr, | 134 | name: SmolStr, |
@@ -94,7 +136,7 @@ struct ModuleItem { | |||
94 | vis: Vis, | 136 | vis: Vis, |
95 | } | 137 | } |
96 | 138 | ||
97 | #[derive(Debug)] | 139 | #[derive(Debug, PartialEq, Eq)] |
98 | enum Vis { | 140 | enum Vis { |
99 | Priv, | 141 | Priv, |
100 | Other, | 142 | Other, |
@@ -116,11 +158,13 @@ impl InputModuleItems { | |||
116 | ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?), | 158 | ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?), |
117 | ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?), | 159 | ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?), |
118 | ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?), | 160 | ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?), |
119 | ast::ModuleItem::ImplItem(it) => { | 161 | ast::ModuleItem::ImplItem(_) => { |
120 | // impls don't define items | 162 | // impls don't define items |
121 | } | 163 | } |
122 | ast::ModuleItem::UseItem(it) => self.add_use_item(it), | 164 | ast::ModuleItem::UseItem(it) => self.add_use_item(it), |
123 | ast::ModuleItem::ExternCrateItem(it) => (), | 165 | ast::ModuleItem::ExternCrateItem(_) => { |
166 | // TODO | ||
167 | } | ||
124 | ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?), | 168 | ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?), |
125 | ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?), | 169 | ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?), |
126 | ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?), | 170 | ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?), |
@@ -227,7 +271,7 @@ impl ModuleItem { | |||
227 | 271 | ||
228 | struct Resolver<'a, DB> { | 272 | struct Resolver<'a, DB> { |
229 | db: &'a DB, | 273 | db: &'a DB, |
230 | input: &'a FxHashMap<ModuleId, InputModuleItems>, | 274 | input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>, |
231 | source_root: SourceRootId, | 275 | source_root: SourceRootId, |
232 | module_tree: Arc<ModuleTree>, | 276 | module_tree: Arc<ModuleTree>, |
233 | result: ItemMap, | 277 | result: ItemMap, |
@@ -237,14 +281,16 @@ impl<'a, DB> Resolver<'a, DB> | |||
237 | where | 281 | where |
238 | DB: DescriptorDatabase, | 282 | DB: DescriptorDatabase, |
239 | { | 283 | { |
240 | fn resolve(&mut self) { | 284 | fn resolve(&mut self) -> Cancelable<()> { |
241 | for (&module_id, items) in self.input.iter() { | 285 | for (&module_id, items) in self.input.iter() { |
242 | self.populate_module(module_id, items) | 286 | self.populate_module(module_id, items) |
243 | } | 287 | } |
244 | 288 | ||
245 | for &module_id in self.input.keys() { | 289 | for &module_id in self.input.keys() { |
290 | crate::db::check_canceled(self.db)?; | ||
246 | self.resolve_imports(module_id); | 291 | self.resolve_imports(module_id); |
247 | } | 292 | } |
293 | Ok(()) | ||
248 | } | 294 | } |
249 | 295 | ||
250 | fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) { | 296 | fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) { |
@@ -346,3 +392,46 @@ where | |||
346 | f(module_items) | 392 | f(module_items) |
347 | } | 393 | } |
348 | } | 394 | } |
395 | |||
396 | #[cfg(test)] | ||
397 | mod tests { | ||
398 | use crate::{ | ||
399 | mock_analysis::analysis_and_position, | ||
400 | descriptors::{DescriptorDatabase, module::ModuleDescriptor}, | ||
401 | input::FilesDatabase, | ||
402 | }; | ||
403 | use super::*; | ||
404 | |||
405 | fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { | ||
406 | let (analysis, pos) = analysis_and_position(fixture); | ||
407 | let db = analysis.imp.db; | ||
408 | let source_root = db.file_source_root(pos.file_id); | ||
409 | let descr = ModuleDescriptor::guess_from_position(&*db, pos) | ||
410 | .unwrap() | ||
411 | .unwrap(); | ||
412 | let module_id = descr.module_id; | ||
413 | (db._item_map(source_root).unwrap(), module_id) | ||
414 | } | ||
415 | |||
416 | #[test] | ||
417 | fn test_item_map() { | ||
418 | let (item_map, module_id) = item_map( | ||
419 | " | ||
420 | //- /lib.rs | ||
421 | mod foo; | ||
422 | |||
423 | use crate::foo::bar::Baz; | ||
424 | <|> | ||
425 | |||
426 | //- /foo/mod.rs | ||
427 | pub mod bar; | ||
428 | |||
429 | //- /foo/bar.rs | ||
430 | pub struct Baz; | ||
431 | ", | ||
432 | ); | ||
433 | let name = SmolStr::from("Baz"); | ||
434 | let resolution = &item_map.per_module[&module_id].items[&name]; | ||
435 | assert!(resolution.def_id.is_some()); | ||
436 | } | ||
437 | } | ||