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,
descriptors::{
DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery,
SubmodulesQuery, ItemMapQuery,
SubmodulesQuery, ItemMapQuery, InputModuleItemsQuery,
},
symbol_index::SymbolIndex,
syntax_ptr::SyntaxPtr,
@ -86,6 +86,7 @@ salsa::database_storage! {
impl DescriptorDatabase {
fn module_tree() for ModuleTreeQuery;
fn fn_scopes() for FnScopesQuery;
fn _input_module_items() for InputModuleItemsQuery;
fn _item_map() for ItemMapQuery;
fn _module_scope() for ModuleScopeQuery;
fn _fn_syntax() for FnSyntaxQuery;

View file

@ -11,7 +11,7 @@ use ra_syntax::{
use crate::{
db::SyntaxDatabase,
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,
loc2id::IdDatabase,
syntax_ptr::LocalSyntaxPtr,
@ -25,6 +25,10 @@ salsa::query_group! {
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>> {
type ItemMapQuery;
use fn module::nameres::item_map;

View file

@ -149,6 +149,13 @@ pub(crate) struct 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> {
self.mods
.iter()

View file

@ -5,7 +5,7 @@ use rustc_hash::FxHashMap;
use ra_syntax::{
SmolStr, SyntaxKind::{self, *},
ast::{self, NameOwner, AstNode}
ast::{self, NameOwner, AstNode, ModuleItemOwner}
};
use crate::{
@ -13,9 +13,9 @@ use crate::{
loc2id::{DefId, DefLoc},
descriptors::{
DescriptorDatabase,
module::{ModuleId, ModuleTree},
module::{ModuleId, ModuleTree, ModuleSourceNode},
},
syntax_ptr::{LocalSyntaxPtr, SyntaxPtr},
syntax_ptr::{LocalSyntaxPtr},
input::SourceRootId,
};
@ -25,20 +25,20 @@ use crate::{
/// 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
/// running name resolution.
#[derive(Debug, Default)]
struct InputModuleItems {
#[derive(Debug, Default, PartialEq, Eq)]
pub(crate) struct InputModuleItems {
items: Vec<ModuleItem>,
glob_imports: Vec<Path>,
imports: Vec<Path>,
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
struct Path {
kind: PathKind,
segments: Vec<(LocalSyntaxPtr, SmolStr)>,
}
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum PathKind {
Abs,
Self_,
@ -46,16 +46,58 @@ enum PathKind {
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(
db: &impl DescriptorDatabase,
source_root: SourceRootId,
) -> 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
/// module, the set of visible items.
#[derive(Debug, PartialEq, Eq)]
#[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct ItemMap {
per_module: FxHashMap<ModuleId, ModuleItems>,
}
@ -86,7 +128,7 @@ struct PerNs<T> {
values: Option<T>,
}
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
struct ModuleItem {
ptr: LocalSyntaxPtr,
name: SmolStr,
@ -94,7 +136,7 @@ struct ModuleItem {
vis: Vis,
}
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq)]
enum Vis {
Priv,
Other,
@ -116,11 +158,13 @@ impl InputModuleItems {
ast::ModuleItem::FnDef(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::ImplItem(it) => {
ast::ModuleItem::ImplItem(_) => {
// impls don't define items
}
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::StaticDef(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> {
db: &'a DB,
input: &'a FxHashMap<ModuleId, InputModuleItems>,
input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>,
source_root: SourceRootId,
module_tree: Arc<ModuleTree>,
result: ItemMap,
@ -237,14 +281,16 @@ impl<'a, DB> Resolver<'a, DB>
where
DB: DescriptorDatabase,
{
fn resolve(&mut self) {
fn resolve(&mut self) -> Cancelable<()> {
for (&module_id, items) in self.input.iter() {
self.populate_module(module_id, items)
}
for &module_id in self.input.keys() {
crate::db::check_canceled(self.db)?;
self.resolve_imports(module_id);
}
Ok(())
}
fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) {
@ -346,3 +392,46 @@ where
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());
}
}