diff options
Diffstat (limited to 'support/texlab/src/workspace.rs')
-rw-r--r-- | support/texlab/src/workspace.rs | 225 |
1 files changed, 0 insertions, 225 deletions
diff --git a/support/texlab/src/workspace.rs b/support/texlab/src/workspace.rs deleted file mode 100644 index e01a2fede4..0000000000 --- a/support/texlab/src/workspace.rs +++ /dev/null @@ -1,225 +0,0 @@ -use std::{ - fs::{self, FileType}, - path::PathBuf, - sync::Arc, -}; - -use anyhow::Result; -use crossbeam_channel::Sender; -use lsp_types::Url; -use petgraph::{graphmap::UnGraphMap, visit::Dfs}; -use rustc_hash::{FxHashMap, FxHashSet}; - -use crate::{ - component_db::COMPONENT_DATABASE, syntax::latex::ExplicitLink, Document, DocumentLanguage, - Environment, -}; - -#[derive(Debug, Clone)] -pub enum WorkspaceEvent { - Changed(Workspace, Document), -} - -#[derive(Debug, Clone, Default)] -pub struct Workspace { - pub documents_by_uri: FxHashMap<Arc<Url>, Document>, - pub viewport: FxHashSet<Arc<Url>>, - pub listeners: Vec<Sender<WorkspaceEvent>>, - pub environment: Environment, -} - -impl Workspace { - #[must_use] - pub fn new(environment: Environment) -> Self { - Self { - environment, - ..Self::default() - } - } - - pub fn open( - &mut self, - uri: Arc<Url>, - text: Arc<String>, - language: DocumentLanguage, - ) -> Result<Document> { - log::debug!("(Re)Loading document: {}", uri); - let document = Document::parse(&self.environment, Arc::clone(&uri), text, language); - - self.documents_by_uri - .insert(Arc::clone(&uri), document.clone()); - - for listener in &self.listeners { - listener.send(WorkspaceEvent::Changed(self.clone(), document.clone()))?; - } - - self.expand_parent(&document); - self.expand_children(&document); - Ok(document) - } - - pub fn reload(&mut self, path: PathBuf) -> Result<Option<Document>> { - let uri = Arc::new(Url::from_file_path(path.clone()).unwrap()); - - if self.is_open(&uri) && !uri.as_str().ends_with(".log") { - return Ok(self.documents_by_uri.get(&uri).cloned()); - } - - if let Some(language) = DocumentLanguage::by_path(&path) { - let data = fs::read(&path)?; - let text = Arc::new(String::from_utf8_lossy(&data).into_owned()); - Ok(Some(self.open(uri, text, language)?)) - } else { - Ok(None) - } - } - - pub fn load(&mut self, path: PathBuf) -> Result<Option<Document>> { - let uri = Arc::new(Url::from_file_path(path.clone()).unwrap()); - - if let Some(document) = self.documents_by_uri.get(&uri).cloned() { - return Ok(Some(document)); - } - - let data = fs::read(&path)?; - let text = Arc::new(String::from_utf8_lossy(&data).into_owned()); - if let Some(language) = DocumentLanguage::by_path(&path) { - Ok(Some(self.open(uri, text, language)?)) - } else { - Ok(None) - } - } - - pub fn close(&mut self, uri: &Url) { - self.viewport.remove(uri); - } - - pub fn is_open(&self, uri: &Url) -> bool { - self.viewport.contains(uri) - } - - pub fn slice(&self, uri: &Url) -> Self { - let all_uris: Vec<_> = self.documents_by_uri.keys().cloned().collect(); - - all_uris - .iter() - .position(|u| u.as_ref() == uri) - .map(|start| { - let mut edges = Vec::new(); - for (i, uri) in all_uris.iter().enumerate() { - let document = self.documents_by_uri.get(uri); - if let Some(data) = document - .as_ref() - .and_then(|document| document.data.as_latex()) - { - let extras = &data.extras; - let mut all_targets = - vec![&extras.implicit_links.aux, &extras.implicit_links.log]; - for link in &extras.explicit_links { - all_targets.push(&link.targets); - } - - for targets in all_targets { - for target in targets { - if let Some(j) = all_uris.iter().position(|uri| uri == target) { - edges.push((i, j, ())); - break; - } - } - } - } - } - - let mut slice = self.clone(); - slice.documents_by_uri = FxHashMap::default(); - let graph = UnGraphMap::from_edges(edges); - let mut dfs = Dfs::new(&graph, start); - while let Some(i) = dfs.next(&graph) { - let uri = &all_uris[i]; - let doc = self.documents_by_uri[uri].clone(); - slice.documents_by_uri.insert(Arc::clone(uri), doc); - } - - slice - }) - .unwrap_or_default() - } - - #[must_use] - pub fn find_parent(&self, uri: &Url) -> Option<Document> { - self.slice(uri) - .documents_by_uri - .values() - .find(|document| { - document.data.as_latex().map_or(false, |data| { - data.extras.has_document_environment - && !data - .extras - .explicit_links - .iter() - .filter_map(ExplicitLink::as_component_name) - .any(|name| name == "subfiles.cls") - }) - }) - .cloned() - } - - fn expand_parent(&mut self, document: &Document) { - let all_current_paths = self - .documents_by_uri - .values() - .filter_map(|doc| doc.uri.to_file_path().ok()) - .collect::<FxHashSet<_>>(); - - if document.uri.scheme() == "file" { - if let Ok(mut path) = document.uri.to_file_path() { - while path.pop() && self.find_parent(&document.uri).is_none() { - std::fs::read_dir(&path) - .into_iter() - .flatten() - .filter_map(Result::ok) - .filter(|entry| entry.file_type().ok().filter(FileType::is_file).is_some()) - .map(|entry| entry.path()) - .filter(|path| { - matches!( - DocumentLanguage::by_path(path), - Some(DocumentLanguage::Latex) - ) - }) - .filter(|path| !all_current_paths.contains(path)) - .for_each(|path| { - let _ = self.load(path); - }); - } - } - } - } - - fn expand_children(&mut self, document: &Document) { - if let Some(data) = document.data.as_latex() { - let extras = &data.extras; - let mut all_targets = vec![&extras.implicit_links.aux, &extras.implicit_links.log]; - for link in &extras.explicit_links { - if link - .as_component_name() - .and_then(|name| COMPONENT_DATABASE.find(&name)) - .is_none() - { - all_targets.push(&link.targets); - } - } - - for targets in all_targets { - for path in targets - .iter() - .filter(|uri| uri.scheme() == "file" && uri.fragment().is_none()) - .filter_map(|uri| uri.to_file_path().ok()) - { - if self.load(path).is_ok() { - break; - } - } - } - } - } -} |