aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/descriptors
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-11-21 08:16:46 +0000
committerAleksey Kladov <[email protected]>2018-11-21 08:16:46 +0000
commit02c4f823485fb5302b8f8eb6fee84122ca73979c (patch)
tree48a495152b3aad1183c5f74419c61748f26c64e1 /crates/ra_analysis/src/descriptors
parent36aad851383c7fd1ca5ffaa99ba8cc96b85378c1 (diff)
simple test for item map
Diffstat (limited to 'crates/ra_analysis/src/descriptors')
-rw-r--r--crates/ra_analysis/src/descriptors/mod.rs6
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs7
-rw-r--r--crates/ra_analysis/src/descriptors/module/nameres.rs119
3 files changed, 116 insertions, 16 deletions
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::{
11use crate::{ 11use 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
151impl ModuleTree { 151impl 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
6use ra_syntax::{ 6use 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
11use crate::{ 11use 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)]
29struct InputModuleItems { 29pub(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)]
36struct Path { 36struct 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)]
42enum PathKind { 42enum PathKind {
43 Abs, 43 Abs,
44 Self_, 44 Self_,
@@ -46,16 +46,58 @@ enum PathKind {
46 Crate, 46 Crate,
47} 47}
48 48
49pub(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
49pub(crate) fn item_map( 73pub(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)]
59pub(crate) struct ItemMap { 101pub(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)]
90struct ModuleItem { 132struct 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)]
98enum Vis { 140enum 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
228struct Resolver<'a, DB> { 272struct 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>
237where 281where
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)]
397mod 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}