codebook_lsp/
file_cache.rs

1use std::{
2    num::NonZero,
3    sync::{Arc, RwLock},
4};
5
6use lru::LruCache;
7use tower_lsp::lsp_types::{TextDocumentItem, Url};
8
9#[derive(Debug, Clone)]
10pub struct TextDocumentCacheItem {
11    pub text: String,
12    pub uri: Url,
13    pub version: Option<i32>,
14    pub language_id: Option<String>,
15}
16
17impl TextDocumentCacheItem {
18    pub fn new(
19        uri: &Url,
20        version: Option<i32>,
21        language_id: Option<&str>,
22        text: Option<&str>,
23    ) -> Self {
24        Self {
25            uri: uri.clone(),
26            version,
27            language_id: language_id.map(|id| id.to_string()),
28            text: match text {
29                Some(text) => text.to_string(),
30                None => String::new(),
31            },
32        }
33    }
34}
35
36#[derive(Debug)]
37pub struct TextDocumentCache {
38    documents: Arc<RwLock<LruCache<String, TextDocumentCacheItem>>>,
39}
40
41impl Default for TextDocumentCache {
42    fn default() -> Self {
43        Self {
44            documents: Arc::new(RwLock::new(LruCache::new(NonZero::new(1000).unwrap()))),
45        }
46    }
47}
48
49impl TextDocumentCache {
50    pub fn get(&self, uri: &str) -> Option<TextDocumentCacheItem> {
51        self.documents.write().unwrap().get(uri).cloned()
52    }
53
54    pub fn insert(&self, document: &TextDocumentItem) {
55        let document = TextDocumentCacheItem::new(
56            &document.uri,
57            Some(document.version),
58            Some(&document.language_id),
59            Some(&document.text),
60        );
61        self.documents
62            .write()
63            .unwrap()
64            .put(document.uri.to_string(), document);
65    }
66
67    pub fn update(&self, uri: &Url, text: &str) {
68        let key = uri.to_string();
69        let mut cache = self.documents.write().unwrap();
70        let item = cache.get(&key);
71        match item {
72            Some(item) => {
73                let new_item = TextDocumentCacheItem::new(
74                    uri,
75                    item.version,
76                    item.language_id.as_deref(),
77                    Some(text),
78                );
79                cache.put(key, new_item);
80            }
81            None => {
82                let item = TextDocumentCacheItem::new(uri, None, None, Some(text));
83                cache.put(key, item);
84            }
85        }
86    }
87
88    pub fn remove(&self, uri: &Url) {
89        self.documents.write().unwrap().pop(uri.as_str());
90    }
91
92    pub fn cached_urls(&self) -> Vec<Url> {
93        self.documents
94            .read()
95            .unwrap()
96            .iter()
97            .map(|(_, v)| v.uri.clone())
98            .collect()
99    }
100}