mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 21:28:51 +00:00
Add simplisitc global modification caching
This commit is contained in:
parent
3ae3b3eb06
commit
db14b4270c
3 changed files with 111 additions and 31 deletions
|
@ -2,50 +2,95 @@ use std::{
|
|||
hash::Hash,
|
||||
sync::Arc,
|
||||
cell::RefCell,
|
||||
fmt::Debug,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use libsyntax2::{File};
|
||||
use im;
|
||||
use {
|
||||
FileId,
|
||||
imp::{FileResolverImp},
|
||||
module_map_db::ModuleDescr,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct Db {
|
||||
file_resolver: FileResolverImp,
|
||||
files: im::HashMap<FileId, Arc<String>>,
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct DbHost {
|
||||
db: Arc<Db>,
|
||||
}
|
||||
|
||||
impl Db {
|
||||
pub(crate) fn new() -> Db {
|
||||
Db {
|
||||
impl DbHost {
|
||||
pub(crate) fn new() -> DbHost {
|
||||
let db = Db {
|
||||
file_resolver: FileResolverImp::default(),
|
||||
files: im::HashMap::new(),
|
||||
}
|
||||
cache: Mutex::new(Cache::new())
|
||||
};
|
||||
DbHost { db: Arc::new(db) }
|
||||
}
|
||||
pub(crate) fn change_file(&mut self, file_id: FileId, text: Option<String>) {
|
||||
let db = self.db_mut();
|
||||
match text {
|
||||
None => {
|
||||
self.files.remove(&file_id);
|
||||
db.files.remove(&file_id);
|
||||
}
|
||||
Some(text) => {
|
||||
self.files.insert(file_id, Arc::new(text));
|
||||
db.files.insert(file_id, Arc::new(text));
|
||||
}
|
||||
}
|
||||
}
|
||||
pub(crate) fn set_file_resolver(&mut self, file_resolver: FileResolverImp) {
|
||||
self.file_resolver = file_resolver
|
||||
let db = self.db_mut();
|
||||
db.file_resolver = file_resolver
|
||||
}
|
||||
pub(crate) fn query_ctx(&self) -> QueryCtx {
|
||||
QueryCtx {
|
||||
db: self.clone(),
|
||||
db: Arc::clone(&self.db),
|
||||
trace: RefCell::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
fn db_mut(&mut self) -> &mut Db {
|
||||
// NB: this "forks" the database & clears the cache
|
||||
let db = Arc::make_mut(&mut self.db);
|
||||
*db.cache.get_mut() = Default::default();
|
||||
db
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Db {
|
||||
file_resolver: FileResolverImp,
|
||||
files: im::HashMap<FileId, Arc<String>>,
|
||||
cache: Mutex<Cache>,
|
||||
}
|
||||
|
||||
impl Clone for Db {
|
||||
fn clone(&self) -> Db {
|
||||
Db {
|
||||
file_resolver: self.file_resolver.clone(),
|
||||
files: self.files.clone(),
|
||||
cache: Mutex::new(Cache::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub(crate) struct Cache {
|
||||
pub(crate) module_descr: QueryCache<ModuleDescr>
|
||||
}
|
||||
#[allow(type_alias_bounds)]
|
||||
pub(crate) type QueryCache<Q: Query> = im::HashMap<
|
||||
<Q as Query>::Params,
|
||||
<Q as Query>::Output
|
||||
>;
|
||||
|
||||
impl Cache {
|
||||
fn new() -> Cache {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct QueryCtx {
|
||||
db: Db,
|
||||
db: Arc<Db>,
|
||||
pub(crate) trace: RefCell<Vec<TraceEvent>>,
|
||||
}
|
||||
|
||||
|
@ -62,9 +107,7 @@ pub(crate) enum TraceEventKind {
|
|||
|
||||
impl QueryCtx {
|
||||
pub(crate) fn get<Q: Get>(&self, params: &Q::Params) -> Q::Output {
|
||||
self.trace(TraceEvent { query_id: Q::ID, kind: TraceEventKind::Start });
|
||||
let res = Q::get(self, params);
|
||||
self.trace(TraceEvent { query_id: Q::ID, kind: TraceEventKind::Finish });
|
||||
res
|
||||
}
|
||||
fn trace(&self, event: TraceEvent) {
|
||||
|
@ -74,26 +117,55 @@ impl QueryCtx {
|
|||
|
||||
pub(crate) trait Query {
|
||||
const ID: u32;
|
||||
type Params: Hash;
|
||||
type Output;
|
||||
type Params: Hash + Eq + Debug;
|
||||
type Output: Debug;
|
||||
}
|
||||
|
||||
pub(crate) trait Get: Query {
|
||||
fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<T: Eval> Get for T {
|
||||
impl<T: Eval> Get for T
|
||||
where
|
||||
T::Params: Clone,
|
||||
T::Output: Clone,
|
||||
{
|
||||
fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output {
|
||||
Self::eval(ctx, params)
|
||||
{
|
||||
let mut cache = ctx.db.cache.lock();
|
||||
if let Some(cache) = Self::cache(&mut cache) {
|
||||
if let Some(res) = cache.get(params) {
|
||||
return res.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.trace(TraceEvent { query_id: Self::ID, kind: TraceEventKind::Start });
|
||||
let res = Self::eval(ctx, params);
|
||||
ctx.trace(TraceEvent { query_id: Self::ID, kind: TraceEventKind::Finish });
|
||||
|
||||
let mut cache = ctx.db.cache.lock();
|
||||
if let Some(cache) = Self::cache(&mut cache) {
|
||||
cache.insert(params.clone(), res.clone());
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait Eval: Query {
|
||||
pub(crate) trait Eval: Query
|
||||
where
|
||||
Self::Params: Clone,
|
||||
Self::Output: Clone,
|
||||
{
|
||||
fn cache(_cache: &mut Cache) -> Option<&mut QueryCache<Self>> {
|
||||
None
|
||||
}
|
||||
fn eval(ctx: &QueryCtx, params: &Self::Params) -> Self::Output;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct DbFiles {
|
||||
db: Db,
|
||||
db: Arc<Db>,
|
||||
}
|
||||
|
||||
impl DbFiles {
|
||||
|
@ -113,7 +185,7 @@ impl Query for Files {
|
|||
}
|
||||
impl Get for Files {
|
||||
fn get(ctx: &QueryCtx, _params: &()) -> DbFiles {
|
||||
DbFiles { db: ctx.db.clone() }
|
||||
DbFiles { db: Arc::clone(&ctx.db) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ extern crate im;
|
|||
|
||||
mod symbol_index;
|
||||
mod module_map;
|
||||
mod module_map_db;
|
||||
pub(crate) mod module_map_db;
|
||||
mod imp;
|
||||
mod job;
|
||||
mod roots;
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
use std::sync::Arc;
|
||||
use {
|
||||
FileId,
|
||||
db::{Query, Eval, QueryCtx, FileSyntax, Files},
|
||||
db::{
|
||||
Query, Eval, QueryCtx, FileSyntax, Files,
|
||||
Cache, QueryCache,
|
||||
},
|
||||
module_map::resolve_submodule,
|
||||
};
|
||||
|
||||
enum ModuleDescr {}
|
||||
pub(crate) enum ModuleDescr {}
|
||||
impl Query for ModuleDescr {
|
||||
const ID: u32 = 30;
|
||||
type Params = FileId;
|
||||
|
@ -27,6 +30,9 @@ impl Query for ParentModule {
|
|||
}
|
||||
|
||||
impl Eval for ModuleDescr {
|
||||
fn cache(cache: &mut Cache) -> Option<&mut QueryCache<Self>> {
|
||||
Some(&mut cache.module_descr)
|
||||
}
|
||||
fn eval(ctx: &QueryCtx, file_id: &FileId) -> Arc<descr::ModuleDescr> {
|
||||
let file = ctx.get::<FileSyntax>(file_id);
|
||||
Arc::new(descr::ModuleDescr::new(file.ast()))
|
||||
|
@ -66,6 +72,7 @@ mod descr {
|
|||
ast::{self, NameOwner},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ModuleDescr {
|
||||
pub submodules: Vec<Submodule>
|
||||
}
|
||||
|
@ -85,7 +92,7 @@ mod descr {
|
|||
ModuleDescr { submodules } }
|
||||
}
|
||||
|
||||
#[derive(Clone, Hash)]
|
||||
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
|
||||
pub struct Submodule {
|
||||
pub name: SmolStr,
|
||||
}
|
||||
|
@ -98,7 +105,7 @@ mod tests {
|
|||
use im;
|
||||
use relative_path::{RelativePath, RelativePathBuf};
|
||||
use {
|
||||
db::{Query, Db, TraceEventKind},
|
||||
db::{Query, DbHost, TraceEventKind},
|
||||
imp::FileResolverImp,
|
||||
FileId, FileResolver,
|
||||
};
|
||||
|
@ -122,7 +129,7 @@ mod tests {
|
|||
struct Fixture {
|
||||
next_file_id: u32,
|
||||
fm: im::HashMap<FileId, RelativePathBuf>,
|
||||
db: Db,
|
||||
db: DbHost,
|
||||
}
|
||||
|
||||
impl Fixture {
|
||||
|
@ -130,7 +137,7 @@ mod tests {
|
|||
Fixture {
|
||||
next_file_id: 1,
|
||||
fm: im::HashMap::new(),
|
||||
db: Db::new(),
|
||||
db: DbHost::new(),
|
||||
}
|
||||
}
|
||||
fn add_file(&mut self, path: &str, text: &str) -> FileId {
|
||||
|
@ -185,10 +192,11 @@ mod tests {
|
|||
fn test_parent_module() {
|
||||
let mut f = Fixture::new();
|
||||
let foo = f.add_file("/foo.rs", "");
|
||||
f.check_parent_modules(foo, &[], &[(FileSyntax::ID, 1)]);
|
||||
f.check_parent_modules(foo, &[], &[(ModuleDescr::ID, 1)]);
|
||||
|
||||
let lib = f.add_file("/lib.rs", "mod foo;");
|
||||
f.check_parent_modules(foo, &[lib], &[(FileSyntax::ID, 2)]);
|
||||
f.check_parent_modules(foo, &[lib], &[(ModuleDescr::ID, 2)]);
|
||||
f.check_parent_modules(foo, &[lib], &[(ModuleDescr::ID, 0)]);
|
||||
|
||||
f.change_file(lib, "");
|
||||
f.check_parent_modules(foo, &[], &[(ModuleDescr::ID, 2)]);
|
||||
|
|
Loading…
Reference in a new issue