Skip to main content

logicaffeine_lsp/
state.rs

1use std::sync::atomic::{AtomicU64, Ordering};
2use std::sync::Arc;
3
4use dashmap::DashMap;
5use tower_lsp::lsp_types::{SemanticToken, Url};
6
7use crate::document::DocumentState;
8
9/// Global server state: the latest analyzed snapshot of every open document.
10///
11/// Snapshots are immutable `Arc`s: handlers clone the `Arc` out and drop the
12/// map guard immediately, so a guard can never be held across an `.await`.
13/// Text mutation and re-analysis live in the [`crate::scheduler`]; this map
14/// only ever swaps in completed snapshots.
15pub struct ServerState {
16    documents: DashMap<Url, Arc<DocumentState>>,
17    /// The last semantic-token emission per document, keyed for delta requests.
18    semantic_cache: DashMap<Url, (String, Arc<Vec<SemanticToken>>)>,
19    next_result_id: AtomicU64,
20}
21
22impl ServerState {
23    pub fn new() -> Self {
24        ServerState {
25            documents: DashMap::new(),
26            semantic_cache: DashMap::new(),
27            next_result_id: AtomicU64::new(1),
28        }
29    }
30
31    /// The latest snapshot for a document, if it is open and analyzed.
32    /// Every open document's latest snapshot — cross-file features consult
33    /// LIVE buffers before the disk-backed workspace index.
34    pub fn open_documents(&self) -> Vec<(Url, Arc<DocumentState>)> {
35        self.documents
36            .iter()
37            .map(|entry| (entry.key().clone(), Arc::clone(entry.value())))
38            .collect()
39    }
40
41    pub fn snapshot(&self, uri: &Url) -> Option<Arc<DocumentState>> {
42        self.documents.get(uri).map(|entry| Arc::clone(&entry))
43    }
44
45    /// Swap in a freshly analyzed snapshot.
46    pub fn install_snapshot(&self, uri: Url, document: DocumentState) -> Arc<DocumentState> {
47        let snapshot = Arc::new(document);
48        self.documents.insert(uri, Arc::clone(&snapshot));
49        snapshot
50    }
51
52    /// Remember a semantic-token emission and mint its result id.
53    pub fn cache_semantic_tokens(&self, uri: Url, data: Vec<SemanticToken>) -> String {
54        let id = self
55            .next_result_id
56            .fetch_add(1, Ordering::Relaxed)
57            .to_string();
58        self.semantic_cache.insert(uri, (id.clone(), Arc::new(data)));
59        id
60    }
61
62    /// The previous emission for a document, if any.
63    pub fn cached_semantic_tokens(&self, uri: &Url) -> Option<(String, Arc<Vec<SemanticToken>>)> {
64        self.semantic_cache
65            .get(uri)
66            .map(|entry| (entry.0.clone(), Arc::clone(&entry.1)))
67    }
68
69    pub fn close_document(&self, uri: &Url) {
70        self.documents.remove(uri);
71        self.semantic_cache.remove(uri);
72    }
73}