simple test for item map

This commit is contained in:
Aleksey Kladov 2018-11-21 11:16:46 +03:00
parent 36aad85138
commit 02c4f82348
4 changed files with 118 additions and 17 deletions

View file

@ -8,7 +8,7 @@ use crate::{
db, db,
descriptors::{ descriptors::{
DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery, DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery,
SubmodulesQuery, ItemMapQuery, SubmodulesQuery, ItemMapQuery, InputModuleItemsQuery,
}, },
symbol_index::SymbolIndex, symbol_index::SymbolIndex,
syntax_ptr::SyntaxPtr, syntax_ptr::SyntaxPtr,
@ -86,6 +86,7 @@ salsa::database_storage! {
impl DescriptorDatabase { impl DescriptorDatabase {
fn module_tree() for ModuleTreeQuery; fn module_tree() for ModuleTreeQuery;
fn fn_scopes() for FnScopesQuery; fn fn_scopes() for FnScopesQuery;
fn _input_module_items() for InputModuleItemsQuery;
fn _item_map() for ItemMapQuery; fn _item_map() for ItemMapQuery;
fn _module_scope() for ModuleScopeQuery; fn _module_scope() for ModuleScopeQuery;
fn _fn_syntax() for FnSyntaxQuery; fn _fn_syntax() for FnSyntaxQuery;

View file

@ -11,7 +11,7 @@ use ra_syntax::{
use crate::{ use crate::{
db::SyntaxDatabase, db::SyntaxDatabase,
descriptors::function::{resolve_local_name, FnId, FnScopes}, descriptors::function::{resolve_local_name, FnId, FnScopes},
descriptors::module::{ModuleId, ModuleScope, ModuleTree, ModuleSource, nameres::ItemMap}, descriptors::module::{ModuleId, ModuleScope, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems}},
input::SourceRootId, input::SourceRootId,
loc2id::IdDatabase, loc2id::IdDatabase,
syntax_ptr::LocalSyntaxPtr, syntax_ptr::LocalSyntaxPtr,
@ -25,6 +25,10 @@ salsa::query_group! {
use fn function::imp::fn_scopes; use fn function::imp::fn_scopes;
} }
fn _input_module_items(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<InputModuleItems>> {
type InputModuleItemsQuery;
use fn module::nameres::input_module_items;
}
fn _item_map(source_root_id: SourceRootId) -> Cancelable<Arc<ItemMap>> { fn _item_map(source_root_id: SourceRootId) -> Cancelable<Arc<ItemMap>> {
type ItemMapQuery; type ItemMapQuery;
use fn module::nameres::item_map; use fn module::nameres::item_map;

View file

@ -149,6 +149,13 @@ pub(crate) struct ModuleTree {
} }
impl ModuleTree { impl ModuleTree {
fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a {
self.mods
.iter()
.enumerate()
.map(|(idx, _)| ModuleId(idx as u32))
}
fn modules_for_source(&self, source: ModuleSource) -> Vec<ModuleId> { fn modules_for_source(&self, source: ModuleSource) -> Vec<ModuleId> {
self.mods self.mods
.iter() .iter()

View file

@ -5,7 +5,7 @@ use rustc_hash::FxHashMap;
use ra_syntax::{ use ra_syntax::{
SmolStr, SyntaxKind::{self, *}, SmolStr, SyntaxKind::{self, *},
ast::{self, NameOwner, AstNode} ast::{self, NameOwner, AstNode, ModuleItemOwner}
}; };
use crate::{ use crate::{
@ -13,9 +13,9 @@ use crate::{
loc2id::{DefId, DefLoc}, loc2id::{DefId, DefLoc},
descriptors::{ descriptors::{
DescriptorDatabase, DescriptorDatabase,
module::{ModuleId, ModuleTree}, module::{ModuleId, ModuleTree, ModuleSourceNode},
}, },
syntax_ptr::{LocalSyntaxPtr, SyntaxPtr}, syntax_ptr::{LocalSyntaxPtr},
input::SourceRootId, input::SourceRootId,
}; };
@ -25,20 +25,20 @@ use crate::{
/// This stands in-between raw syntax and name resolution and alow us to avoid /// This stands in-between raw syntax and name resolution and alow us to avoid
/// recomputing name res: if `InputModuleItems` are the same, we can avoid /// recomputing name res: if `InputModuleItems` are the same, we can avoid
/// running name resolution. /// running name resolution.
#[derive(Debug, Default)] #[derive(Debug, Default, PartialEq, Eq)]
struct InputModuleItems { pub(crate) struct InputModuleItems {
items: Vec<ModuleItem>, items: Vec<ModuleItem>,
glob_imports: Vec<Path>, glob_imports: Vec<Path>,
imports: Vec<Path>, imports: Vec<Path>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq)]
struct Path { struct Path {
kind: PathKind, kind: PathKind,
segments: Vec<(LocalSyntaxPtr, SmolStr)>, segments: Vec<(LocalSyntaxPtr, SmolStr)>,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum PathKind { enum PathKind {
Abs, Abs,
Self_, Self_,
@ -46,16 +46,58 @@ enum PathKind {
Crate, Crate,
} }
pub(crate) fn input_module_items(
db: &impl DescriptorDatabase,
source_root: SourceRootId,
module_id: ModuleId,
) -> Cancelable<Arc<InputModuleItems>> {
let module_tree = db._module_tree(source_root)?;
let source = module_id.source(&module_tree);
let res = match source.resolve(db) {
ModuleSourceNode::SourceFile(it) => {
let items = it.borrowed().items();
InputModuleItems::new(items)
}
ModuleSourceNode::Module(it) => {
let items = it
.borrowed()
.item_list()
.into_iter()
.flat_map(|it| it.items());
InputModuleItems::new(items)
}
};
Ok(Arc::new(res))
}
pub(crate) fn item_map( pub(crate) fn item_map(
db: &impl DescriptorDatabase, db: &impl DescriptorDatabase,
source_root: SourceRootId, source_root: SourceRootId,
) -> Cancelable<Arc<ItemMap>> { ) -> Cancelable<Arc<ItemMap>> {
unimplemented!() let module_tree = db._module_tree(source_root)?;
let input = module_tree
.modules()
.map(|id| {
let items = db._input_module_items(source_root, id)?;
Ok((id, items))
})
.collect::<Cancelable<FxHashMap<_, _>>>()?;
let mut resolver = Resolver {
db: db,
input: &input,
source_root,
module_tree,
result: ItemMap::default(),
};
resolver.resolve()?;
let res = resolver.result;
Ok(Arc::new(res))
} }
/// Item map is the result of the name resolution. Item map contains, for each /// Item map is the result of the name resolution. Item map contains, for each
/// module, the set of visible items. /// module, the set of visible items.
#[derive(Debug, PartialEq, Eq)] #[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct ItemMap { pub(crate) struct ItemMap {
per_module: FxHashMap<ModuleId, ModuleItems>, per_module: FxHashMap<ModuleId, ModuleItems>,
} }
@ -86,7 +128,7 @@ struct PerNs<T> {
values: Option<T>, values: Option<T>,
} }
#[derive(Debug)] #[derive(Debug, PartialEq, Eq)]
struct ModuleItem { struct ModuleItem {
ptr: LocalSyntaxPtr, ptr: LocalSyntaxPtr,
name: SmolStr, name: SmolStr,
@ -94,7 +136,7 @@ struct ModuleItem {
vis: Vis, vis: Vis,
} }
#[derive(Debug)] #[derive(Debug, PartialEq, Eq)]
enum Vis { enum Vis {
Priv, Priv,
Other, Other,
@ -116,11 +158,13 @@ impl InputModuleItems {
ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?),
ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?),
ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?),
ast::ModuleItem::ImplItem(it) => { ast::ModuleItem::ImplItem(_) => {
// impls don't define items // impls don't define items
} }
ast::ModuleItem::UseItem(it) => self.add_use_item(it), ast::ModuleItem::UseItem(it) => self.add_use_item(it),
ast::ModuleItem::ExternCrateItem(it) => (), ast::ModuleItem::ExternCrateItem(_) => {
// TODO
}
ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?),
ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?),
ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?),
@ -227,7 +271,7 @@ impl ModuleItem {
struct Resolver<'a, DB> { struct Resolver<'a, DB> {
db: &'a DB, db: &'a DB,
input: &'a FxHashMap<ModuleId, InputModuleItems>, input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>,
source_root: SourceRootId, source_root: SourceRootId,
module_tree: Arc<ModuleTree>, module_tree: Arc<ModuleTree>,
result: ItemMap, result: ItemMap,
@ -237,14 +281,16 @@ impl<'a, DB> Resolver<'a, DB>
where where
DB: DescriptorDatabase, DB: DescriptorDatabase,
{ {
fn resolve(&mut self) { fn resolve(&mut self) -> Cancelable<()> {
for (&module_id, items) in self.input.iter() { for (&module_id, items) in self.input.iter() {
self.populate_module(module_id, items) self.populate_module(module_id, items)
} }
for &module_id in self.input.keys() { for &module_id in self.input.keys() {
crate::db::check_canceled(self.db)?;
self.resolve_imports(module_id); self.resolve_imports(module_id);
} }
Ok(())
} }
fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) { fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) {
@ -346,3 +392,46 @@ where
f(module_items) f(module_items)
} }
} }
#[cfg(test)]
mod tests {
use crate::{
mock_analysis::analysis_and_position,
descriptors::{DescriptorDatabase, module::ModuleDescriptor},
input::FilesDatabase,
};
use super::*;
fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
let (analysis, pos) = analysis_and_position(fixture);
let db = analysis.imp.db;
let source_root = db.file_source_root(pos.file_id);
let descr = ModuleDescriptor::guess_from_position(&*db, pos)
.unwrap()
.unwrap();
let module_id = descr.module_id;
(db._item_map(source_root).unwrap(), module_id)
}
#[test]
fn test_item_map() {
let (item_map, module_id) = item_map(
"
//- /lib.rs
mod foo;
use crate::foo::bar::Baz;
<|>
//- /foo/mod.rs
pub mod bar;
//- /foo/bar.rs
pub struct Baz;
",
);
let name = SmolStr::from("Baz");
let resolution = &item_map.per_module[&module_id].items[&name];
assert!(resolution.def_id.is_some());
}
}