mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-16 09:48:10 +00:00
generalize location interner
This commit is contained in:
parent
ec45dfea1e
commit
b2de95879a
8 changed files with 101 additions and 51 deletions
|
@ -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>> {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)?;
|
||||||
|
|
|
@ -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),
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue