Skip to main content

aft/lsp/
document.rs

1use std::collections::HashMap;
2use std::path::{Path, PathBuf};
3
4/// Tracks document state for LSP synchronization.
5///
6/// LSP requires:
7/// 1. didOpen before didChange (document must be opened first)
8/// 2. Version numbers must be monotonically increasing
9/// 3. Full content sent with each change (TextDocumentSyncKind::Full)
10#[derive(Debug, Default)]
11pub struct DocumentStore {
12    /// Maps canonical file path -> current version number.
13    versions: HashMap<PathBuf, i32>,
14}
15
16impl DocumentStore {
17    pub fn new() -> Self {
18        Self {
19            versions: HashMap::new(),
20        }
21    }
22
23    /// Check if a document is already opened (tracked).
24    pub fn is_open(&self, path: &Path) -> bool {
25        self.versions.contains_key(path)
26    }
27
28    /// Open a new document. Returns the initial version (0).
29    pub fn open(&mut self, path: PathBuf) -> i32 {
30        let version = 0;
31        self.versions.insert(path, version);
32        version
33    }
34
35    /// Bump the version for an already-open document. Returns the new version.
36    /// Panics if document is not open.
37    pub fn bump_version(&mut self, path: &Path) -> i32 {
38        let version = self.versions.get_mut(path).expect("document not open");
39        *version += 1;
40        *version
41    }
42
43    /// Get current version, or None if not open.
44    pub fn version(&self, path: &Path) -> Option<i32> {
45        self.versions.get(path).copied()
46    }
47
48    /// Close a document and remove from tracking.
49    pub fn close(&mut self, path: &Path) -> Option<i32> {
50        self.versions.remove(path)
51    }
52
53    /// Get all open document paths.
54    pub fn open_documents(&self) -> Vec<&PathBuf> {
55        self.versions.keys().collect()
56    }
57}