use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use dashmap::DashMap;
use tower_lsp::lsp_types::{SemanticToken, Url};
use crate::document::ast::ParsedDoc;
use crate::index::file_index::FileIndex;
pub(crate) const PARSED_CACHE_CAP: usize = 2048;
pub(crate) struct CacheRegistry {
pub(crate) token_cache: DashMap<Url, (String, Arc<Vec<SemanticToken>>)>,
pub(crate) text_cache: DashMap<Url, Arc<str>>,
pub(crate) parsed_cache: DashMap<Url, (Arc<str>, Arc<ParsedDoc>)>,
pub(crate) analysis_cache: DashMap<Url, (Arc<str>, u64, Arc<mir_analyzer::FileAnalysis>)>,
pub(crate) decl_version: AtomicU64,
pub(crate) decl_fingerprints: DashMap<Url, Arc<FileIndex>>,
pub(crate) type_map_cache:
DashMap<Url, (Arc<str>, usize, Arc<crate::types::type_map::TypeMap>)>,
}
impl CacheRegistry {
pub(crate) fn new() -> Self {
CacheRegistry {
token_cache: DashMap::new(),
text_cache: DashMap::new(),
parsed_cache: DashMap::new(),
analysis_cache: DashMap::new(),
decl_version: AtomicU64::new(0),
decl_fingerprints: DashMap::new(),
type_map_cache: DashMap::new(),
}
}
pub(crate) fn evict(&self, uri: &Url) {
self.token_cache.remove(uri);
self.text_cache.remove(uri);
self.parsed_cache.remove(uri);
self.analysis_cache.remove(uri);
self.decl_fingerprints.remove(uri);
self.type_map_cache.remove(uri);
}
pub(crate) fn evict_analysis(&self, uri: &Url) {
self.analysis_cache.remove(uri);
}
pub(crate) fn evict_analysis_all(&self) {
self.analysis_cache.clear();
}
pub(crate) fn evict_tokens(&self, uri: &Url) {
self.token_cache.remove(uri);
}
pub(crate) fn store_token(
&self,
uri: &Url,
result_id: String,
tokens: Arc<Vec<SemanticToken>>,
) {
self.token_cache.insert(uri.clone(), (result_id, tokens));
}
pub(crate) fn get_token(&self, uri: &Url, result_id: &str) -> Option<Arc<Vec<SemanticToken>>> {
self.token_cache
.get(uri)
.filter(|e| e.0.as_str() == result_id)
.map(|e| Arc::clone(&e.1))
}
pub(crate) fn insert_parsed(&self, uri: Url, text: Arc<str>, doc: Arc<ParsedDoc>) {
if self.parsed_cache.len() >= PARSED_CACHE_CAP {
let drop_target = self.parsed_cache.len() / 2;
let mut dropped = 0usize;
self.parsed_cache.retain(|_, _| {
if dropped < drop_target {
dropped += 1;
false
} else {
true
}
});
}
self.parsed_cache.insert(uri, (text, doc));
}
pub(crate) fn decl_version(&self) -> u64 {
self.decl_version.load(Ordering::Acquire)
}
pub(crate) fn bump_decl_version(&self) {
self.decl_version.fetch_add(1, Ordering::Release);
}
}