generalize location interner

This commit is contained in:
Aleksey Kladov 2018-11-28 02:49:28 +03:00
parent ec45dfea1e
commit b2de95879a
8 changed files with 101 additions and 51 deletions

View file

@ -8,7 +8,7 @@ use salsa::{self, Database};
use crate::{ use crate::{
hir, hir,
symbol_index, symbol_index,
loc2id::{IdMaps}, loc2id::{IdMaps, LocationIntener, DefId, DefLoc, FnId},
Cancelable, Canceled, FileId, Cancelable, Canceled, FileId,
}; };
@ -20,7 +20,7 @@ pub(crate) struct RootDatabase {
events: (), events: (),
runtime: salsa::Runtime<RootDatabase>, runtime: salsa::Runtime<RootDatabase>,
id_maps: IdMaps, id_maps: Arc<IdMaps>,
} }
impl salsa::Database for RootDatabase { impl salsa::Database for RootDatabase {
@ -45,7 +45,7 @@ impl Default for RootDatabase {
let mut db = RootDatabase { let mut db = RootDatabase {
events: Default::default(), events: Default::default(),
runtime: salsa::Runtime::default(), runtime: salsa::Runtime::default(),
id_maps: IdMaps::default(), id_maps: Default::default(),
}; };
db.query_mut(crate::input::SourceRootQuery) db.query_mut(crate::input::SourceRootQuery)
.set(crate::input::WORKSPACE, Default::default()); .set(crate::input::WORKSPACE, Default::default());
@ -84,6 +84,18 @@ impl BaseDatabase for RootDatabase {
} }
} }
impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase {
fn as_ref(&self) -> &LocationIntener<DefLoc, DefId> {
&self.id_maps.defs
}
}
impl AsRef<LocationIntener<hir::SourceItemId, FnId>> for RootDatabase {
fn as_ref(&self) -> &LocationIntener<hir::SourceItemId, FnId> {
&self.id_maps.fns
}
}
#[cfg(test)] #[cfg(test)]
impl RootDatabase { impl RootDatabase {
pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<RootDatabase>> { pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<RootDatabase>> {

View file

@ -8,20 +8,24 @@ use ra_syntax::{
use crate::{ use crate::{
FileId, FileId,
db::SyntaxDatabase, db::SyntaxDatabase,
hir::{SourceFileItems, SourceItemId}, hir::{
hir::query_definitions, SourceFileItems, SourceItemId,
hir::function::{FnId, FnScopes}, query_definitions,
hir::module::{ function::{FnScopes},
ModuleId, ModuleTree, ModuleSource, module::{ModuleId, ModuleTree, ModuleSource,
nameres::{ItemMap, InputModuleItems} nameres::{ItemMap, InputModuleItems}},
}, },
input::SourceRootId, input::SourceRootId,
loc2id::{DefLoc, DefId, FnId, LocationIntener},
Cancelable, Cancelable,
}; };
salsa::query_group! { salsa::query_group! {
pub(crate) trait HirDatabase: SyntaxDatabase { pub(crate) trait HirDatabase: SyntaxDatabase
+ AsRef<LocationIntener<DefLoc, DefId>>
+ AsRef<LocationIntener<SourceItemId, FnId>>
{
fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> { fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> {
type FnScopesQuery; type FnScopesQuery;
use fn query_definitions::fn_scopes; use fn query_definitions::fn_scopes;

View file

@ -23,7 +23,7 @@ impl FnId {
let file_items = db.file_items(file_id); let file_items = db.file_items(file_id);
let item_id = file_items.id_of(fn_def.syntax()); let item_id = file_items.id_of(fn_def.syntax());
let item_id = SourceItemId { file_id, item_id }; let item_id = SourceItemId { file_id, item_id };
db.id_maps().fn_id(item_id) FnId::from_loc(db, &item_id)
} }
} }

View file

@ -38,7 +38,7 @@ pub(crate) enum Def {
impl DefId { impl DefId {
pub(crate) fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> { pub(crate) fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
let loc = db.id_maps().def_loc(self); let loc = self.loc(db);
let res = match loc { let res = match loc {
DefLoc::Module { id, source_root } => { DefLoc::Module { id, source_root } => {
let descr = Module::new(db, source_root, id)?; let descr = Module::new(db, source_root, id)?;

View file

@ -134,7 +134,7 @@ impl Module {
id: self.module_id, id: self.module_id,
source_root: self.source_root_id, source_root: self.source_root_id,
}; };
db.id_maps().def_id(def_loc) def_loc.id(db)
} }
/// Finds a child module with the specified name. /// Finds a child module with the specified name.
@ -167,7 +167,7 @@ impl Module {
let segments = path.segments; let segments = path.segments;
for name in segments.iter() { for name in segments.iter() {
let module = match db.id_maps().def_loc(curr) { let module = match curr.loc(db) {
DefLoc::Module { id, source_root } => Module::new(db, source_root, id)?, DefLoc::Module { id, source_root } => Module::new(db, source_root, id)?,
_ => return Ok(None), _ => return Ok(None),
}; };

View file

@ -256,7 +256,7 @@ where
item_id: item.id, item_id: item.id,
}, },
}; };
let def_id = self.db.id_maps().def_id(def_loc); let def_id = def_loc.id(self.db);
let resolution = Resolution { let resolution = Resolution {
def_id: Some(def_id), def_id: Some(def_id),
import: None, import: None,
@ -269,7 +269,7 @@ where
id: mod_id, id: mod_id,
source_root: self.source_root, source_root: self.source_root,
}; };
let def_id = self.db.id_maps().def_id(def_loc); let def_id = def_loc.id(self.db);
let resolution = Resolution { let resolution = Resolution {
def_id: Some(def_id), def_id: Some(def_id),
import: None, import: None,
@ -318,7 +318,7 @@ where
}; };
if !is_last { if !is_last {
curr = match self.db.id_maps().def_loc(def_id) { curr = match def_id.loc(self.db) {
DefLoc::Module { id, .. } => id, DefLoc::Module { id, .. } => id,
_ => return, _ => return,
} }

View file

@ -26,7 +26,7 @@ use crate::{
/// Resolve `FnId` to the corresponding `SyntaxNode` /// Resolve `FnId` to the corresponding `SyntaxNode`
pub(super) fn fn_syntax(db: &impl HirDatabase, fn_id: FnId) -> FnDefNode { pub(super) fn fn_syntax(db: &impl HirDatabase, fn_id: FnId) -> FnDefNode {
let item_id = db.id_maps().fn_item_id(fn_id); let item_id = fn_id.loc(db);
let syntax = db.file_item(item_id); let syntax = db.file_item(item_id);
FnDef::cast(syntax.borrowed()).unwrap().owned() FnDef::cast(syntax.borrowed()).unwrap().owned()
} }

View file

@ -1,9 +1,6 @@
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{ use std::hash::Hash;
hash::Hash,
sync::Arc,
};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -23,19 +20,19 @@ use crate::{
/// bidirectional mapping between positional and numeric ids, we can use compact /// bidirectional mapping between positional and numeric ids, we can use compact
/// representation wich still allows us to get the actual item /// representation wich still allows us to get the actual item
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct Loc2IdMap<L, ID> struct Loc2IdMap<LOC, ID>
where where
ID: NumericId, ID: NumericId,
L: Clone + Eq + Hash, LOC: Clone + Eq + Hash,
{ {
loc2id: FxHashMap<L, ID>, loc2id: FxHashMap<LOC, ID>,
id2loc: FxHashMap<ID, L>, id2loc: FxHashMap<ID, LOC>,
} }
impl<L, ID> Default for Loc2IdMap<L, ID> impl<LOC, ID> Default for Loc2IdMap<LOC, ID>
where where
ID: NumericId, ID: NumericId,
L: Clone + Eq + Hash, LOC: Clone + Eq + Hash,
{ {
fn default() -> Self { fn default() -> Self {
Loc2IdMap { Loc2IdMap {
@ -45,12 +42,12 @@ where
} }
} }
impl<L, ID> Loc2IdMap<L, ID> impl<LOC, ID> Loc2IdMap<LOC, ID>
where where
ID: NumericId, ID: NumericId,
L: Clone + Eq + Hash, LOC: Clone + Eq + Hash,
{ {
pub fn loc2id(&mut self, loc: &L) -> ID { pub fn loc2id(&mut self, loc: &LOC) -> ID {
match self.loc2id.get(loc) { match self.loc2id.get(loc) {
Some(id) => return id.clone(), Some(id) => return id.clone(),
None => (), None => (),
@ -63,7 +60,7 @@ where
id id
} }
pub fn id2loc(&self, id: ID) -> L { pub fn id2loc(&self, id: ID) -> LOC {
self.id2loc[&id].clone() self.id2loc[&id].clone()
} }
} }
@ -90,6 +87,18 @@ macro_rules! impl_numeric_id {
pub(crate) struct FnId(u32); pub(crate) struct FnId(u32);
impl_numeric_id!(FnId); impl_numeric_id!(FnId);
impl FnId {
pub(crate) fn from_loc(
db: &impl AsRef<LocationIntener<SourceItemId, FnId>>,
loc: &SourceItemId,
) -> FnId {
db.as_ref().loc2id(loc)
}
pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
db.as_ref().id2loc(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct DefId(u32); pub(crate) struct DefId(u32);
impl_numeric_id!(DefId); impl_numeric_id!(DefId);
@ -105,29 +114,54 @@ pub(crate) enum DefLoc {
}, },
} }
#[derive(Debug, Default, Clone)] impl DefId {
pub(crate) struct IdMaps { pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
inner: Arc<IdMapsInner>, db.as_ref().id2loc(self)
}
} }
impl IdMaps { impl DefLoc {
pub(crate) fn fn_id(&self, item_id: SourceItemId) -> FnId { pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
self.inner.fns.lock().loc2id(&item_id) db.as_ref().loc2id(&self)
}
pub(crate) fn fn_item_id(&self, fn_id: FnId) -> SourceItemId {
self.inner.fns.lock().id2loc(fn_id)
}
pub(crate) fn def_id(&self, loc: DefLoc) -> DefId {
self.inner.defs.lock().loc2id(&loc)
}
pub(crate) fn def_loc(&self, def_id: DefId) -> DefLoc {
self.inner.defs.lock().id2loc(def_id)
} }
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct IdMapsInner { pub(crate) struct IdMaps {
fns: Mutex<Loc2IdMap<SourceItemId, FnId>>, pub(crate) fns: LocationIntener<SourceItemId, FnId>,
defs: Mutex<Loc2IdMap<DefLoc, DefId>>, pub(crate) defs: LocationIntener<DefLoc, DefId>,
}
#[derive(Debug)]
pub(crate) struct LocationIntener<LOC, ID>
where
ID: NumericId,
LOC: Clone + Eq + Hash,
{
map: Mutex<Loc2IdMap<LOC, ID>>,
}
impl<LOC, ID> Default for LocationIntener<LOC, ID>
where
ID: NumericId,
LOC: Clone + Eq + Hash,
{
fn default() -> Self {
LocationIntener {
map: Default::default(),
}
}
}
impl<LOC, ID> LocationIntener<LOC, ID>
where
ID: NumericId,
LOC: Clone + Eq + Hash,
{
fn loc2id(&self, loc: &LOC) -> ID {
self.map.lock().loc2id(loc)
}
fn id2loc(&self, id: ID) -> LOC {
self.map.lock().id2loc(id)
}
} }