auto_lsp_default/db/
mod.rs1pub mod lexer;
23pub mod tracked;
24
25use auto_lsp_core::document::Document;
26use auto_lsp_core::errors::{DataBaseError, TreeSitterError};
27use auto_lsp_core::parsers::Parsers;
28use dashmap::{DashMap, Entry};
29use lsp_types::Url;
30use salsa::Setter;
31use salsa::{Database, Storage};
32use std::{hash::Hash, sync::Arc};
33use texter::core::text::Text;
34
35#[salsa::input]
39pub struct File {
40 #[id]
41 pub url: Url,
42 pub parsers: &'static Parsers,
43 #[return_ref]
44 pub document: Arc<Document>,
45}
46
47#[salsa::db]
55#[derive(Default, Clone)]
56pub struct BaseDb {
57 storage: Storage<Self>,
58 pub(crate) files: DashMap<Url, File>,
59}
60
61impl BaseDb {
62 pub fn with_logger(
64 event_callback: Option<Box<dyn Fn(salsa::Event) + Send + Sync + 'static>>,
65 ) -> Self {
66 Self {
67 storage: Storage::new(event_callback),
68 files: DashMap::default(),
69 }
70 }
71}
72
73#[salsa::db]
77pub trait BaseDatabase: Database {
78 fn get_files(&self) -> &DashMap<Url, File>;
79
80 fn get_file(&self, url: &Url) -> Option<File> {
81 self.get_files().get(url).map(|file| *file)
82 }
83}
84
85#[salsa::db]
87impl salsa::Database for BaseDb {}
88impl std::panic::RefUnwindSafe for BaseDb {}
89
90#[salsa::db]
92impl BaseDatabase for BaseDb {
93 fn get_files(&self) -> &DashMap<Url, File> {
94 &self.files
95 }
96}
97
98pub trait FileManager: BaseDatabase + salsa::Database {
102 fn add_file_from_texter(
103 &mut self,
104 parsers: &'static Parsers,
105 url: &Url,
106 texter: Text,
107 ) -> Result<(), DataBaseError> {
108 let tree = parsers
109 .parser
110 .write()
111 .parse(texter.text.as_bytes(), None)
112 .ok_or_else(|| DataBaseError::from((url, TreeSitterError::TreeSitterParser)))?;
113
114 let document = Document { texter, tree };
115 let file = File::new(self, url.clone(), parsers, Arc::new(document));
116
117 match self.get_files().entry(url.clone()) {
118 Entry::Occupied(_) => Err(DataBaseError::FileAlreadyExists { uri: url.clone() }),
119 Entry::Vacant(entry) => {
120 entry.insert(file);
121 Ok(())
122 }
123 }
124 }
125
126 fn update(
127 &mut self,
128 url: &Url,
129 changes: &[lsp_types::TextDocumentContentChangeEvent],
130 ) -> Result<(), DataBaseError> {
131 let file = *self
132 .get_files()
133 .get_mut(url)
134 .ok_or_else(|| DataBaseError::FileNotFound { uri: url.clone() })?;
135
136 let mut doc = (*file.document(self)).clone();
137
138 doc.update(&mut file.parsers(self).parser.write(), changes)
139 .map_err(|e| DataBaseError::from((url, e)))?;
140
141 file.set_document(self).to(Arc::new(doc));
142 Ok(())
143 }
144
145 fn remove_file(&mut self, url: &Url) -> Result<(), DataBaseError> {
146 match self.get_files().remove(url) {
147 None => Err(DataBaseError::FileNotFound { uri: url.clone() }),
148 Some(_) => Ok(()),
149 }
150 }
151}
152
153impl<T> FileManager for T where T: BaseDatabase + salsa::Database {}