diff options
Diffstat (limited to 'support/texlab/crates/base-db/src/workspace.rs')
-rw-r--r-- | support/texlab/crates/base-db/src/workspace.rs | 212 |
1 files changed, 12 insertions, 200 deletions
diff --git a/support/texlab/crates/base-db/src/workspace.rs b/support/texlab/crates/base-db/src/workspace.rs index 0fe347f1b3..1afd4712e9 100644 --- a/support/texlab/crates/base-db/src/workspace.rs +++ b/support/texlab/crates/base-db/src/workspace.rs @@ -4,14 +4,12 @@ use std::{ }; use distro::{Distro, Language}; -use itertools::Itertools; use line_index::LineCol; use rowan::{TextLen, TextRange}; -use rustc_hash::FxHashSet; -use syntax::latexmkrc::LatexmkrcData; +use rustc_hash::{FxHashMap, FxHashSet}; use url::Url; -use crate::{graph, Config, Document, DocumentData, DocumentParams, Owner}; +use crate::{deps, Config, Document, DocumentParams, Owner}; #[derive(Debug, Default)] pub struct Workspace { @@ -19,6 +17,7 @@ pub struct Workspace { config: Config, distro: Distro, folders: Vec<PathBuf>, + graphs: FxHashMap<Url, deps::Graph>, } impl Workspace { @@ -47,6 +46,10 @@ impl Workspace { &self.distro } + pub fn graphs(&self) -> &FxHashMap<Url, deps::Graph> { + &self.graphs + } + pub fn open( &mut self, uri: Url, @@ -65,6 +68,11 @@ impl Workspace { cursor, config: &self.config, })); + + self.graphs = self + .iter() + .map(|start| (start.uri.clone(), deps::Graph::new(self, start))) + .collect(); } pub fn load(&mut self, path: &Path, language: Language) -> std::io::Result<()> { @@ -114,83 +122,6 @@ impl Workspace { Some(()) } - pub fn watch( - &mut self, - watcher: &mut dyn notify::Watcher, - watched_dirs: &mut FxHashSet<PathBuf>, - ) { - self.iter() - .filter(|document| document.uri.scheme() == "file") - .flat_map(|document| { - let current_dir = &self.current_dir(&document.dir); - let doc_dir = document.dir.to_file_path(); - let aux_dir = self.aux_dir(current_dir).to_file_path(); - let log_dir = self.log_dir(current_dir).to_file_path(); - [aux_dir, log_dir, doc_dir] - }) - .flatten() - .for_each(|path| { - if !watched_dirs.contains(&path) { - let _ = watcher.watch(&path, notify::RecursiveMode::NonRecursive); - watched_dirs.insert(path); - } - }); - } - - pub fn current_dir(&self, base_dir: &Url) -> Url { - let root_dir = self.config.root_dir.as_deref(); - if let Some(dir) = root_dir.and_then(|path| base_dir.join(path).ok()) { - return dir; - } - - self.iter() - .filter(|document| matches!(document.data, DocumentData::Root | DocumentData::Tectonic)) - .flat_map(|document| document.uri.join(".")) - .find(|root_dir| base_dir.as_str().starts_with(root_dir.as_str())) - .unwrap_or_else(|| base_dir.clone()) - } - - pub fn aux_dir(&self, base_dir: &Url) -> Url { - self.output_dir(base_dir, &self.config.build.aux_dir, |data| { - data.aux_dir.as_deref() - }) - } - - pub fn log_dir(&self, base_dir: &Url) -> Url { - self.output_dir(base_dir, &self.config.build.log_dir, |_| None) - } - - pub fn pdf_dir(&self, base_dir: &Url) -> Url { - self.output_dir(base_dir, &self.config.build.pdf_dir, |_| None) - } - - fn current_latexmkrc(&self, base_dir: &Url) -> Option<&LatexmkrcData> { - self.documents - .iter() - .filter(|document| document.language == Language::Latexmkrc) - .find(|document| document.uri.join(".").as_ref() == Ok(base_dir)) - .and_then(|document| document.data.as_latexmkrc()) - } - - fn output_dir( - &self, - base_dir: &Url, - config: &str, - extract_latexmkrc: impl FnOnce(&LatexmkrcData) -> Option<&str>, - ) -> Url { - let mut dir: String = self - .current_latexmkrc(base_dir) - .and_then(|data| extract_latexmkrc(data).or_else(|| data.out_dir.as_deref())) - .unwrap_or(config) - .into(); - - if !dir.ends_with('/') { - dir.push('/'); - } - - base_dir.join(&dir).unwrap_or_else(|_| base_dir.clone()) - } - pub fn contains(&self, path: &Path) -> bool { if self.folders.is_empty() { return true; @@ -199,35 +130,6 @@ impl Workspace { self.folders.iter().any(|dir| path.starts_with(dir)) } - pub fn project(&self, child: &Document) -> Project { - let mut documents = FxHashSet::default(); - for graph in self - .iter() - .map(|start| graph::Graph::new(self, start)) - .filter(|graph| graph.preorder().contains(&child)) - { - documents.extend(graph.preorder()); - } - - Project { documents } - } - - pub fn parents(&self, child: &Document) -> FxHashSet<&Document> { - self.iter() - .filter(|document| { - let DocumentData::Tex(data) = &document.data else { - return false; - }; - data.semantics.can_be_root - }) - .filter(|parent| { - let graph = graph::Graph::new(self, parent); - let mut nodes = graph.preorder(); - nodes.contains(&child) - }) - .collect() - } - pub fn set_config(&mut self, config: Config) { self.config = config; self.reload(); @@ -280,94 +182,4 @@ impl Workspace { self.documents.insert(document); Some(()) } - - pub fn discover(&mut self, checked_paths: &mut FxHashSet<PathBuf>) { - loop { - let mut changed = false; - changed |= self.discover_parents(checked_paths); - changed |= self.discover_children(checked_paths); - if !changed { - break; - } - } - } - - fn discover_parents(&mut self, checked_paths: &mut FxHashSet<PathBuf>) -> bool { - let dirs = self - .iter() - .filter(|document| document.language != Language::Bib) - .filter_map(|document| document.path.as_deref()) - .flat_map(|path| path.ancestors().skip(1)) - .filter(|path| self.contains(path)) - .map(|path| path.to_path_buf()) - .collect::<FxHashSet<_>>(); - - let mut changed = false; - for dir in dirs { - if self - .iter() - .filter(|document| matches!(document.language, Language::Root | Language::Tectonic)) - .filter_map(|document| document.path.as_deref()) - .filter_map(|path| path.parent()) - .any(|marker| dir.starts_with(marker)) - { - continue; - } - - let Ok(entries) = std::fs::read_dir(dir) else { - continue; - }; - - for file in entries - .flatten() - .filter(|entry| entry.file_type().map_or(false, |type_| type_.is_file())) - .map(|entry| entry.path()) - { - let Some(lang) = Language::from_path(&file) else { - continue; - }; - - if !matches!( - lang, - Language::Tex | Language::Root | Language::Tectonic | Language::Latexmkrc - ) { - continue; - } - - if self.lookup_path(&file).is_none() && file.exists() { - changed |= self.load(&file, lang).is_ok(); - checked_paths.insert(file); - } - } - } - - changed - } - - fn discover_children(&mut self, checked_paths: &mut FxHashSet<PathBuf>) -> bool { - let files = self - .iter() - .map(|start| graph::Graph::new(self, start)) - .flat_map(|graph| graph.missing) - .filter(|uri| uri.scheme() == "file") - .flat_map(|uri| uri.to_file_path()) - .collect::<FxHashSet<_>>(); - - let mut changed = false; - for file in files { - let language = Language::from_path(&file).unwrap_or(Language::Tex); - - if self.lookup_path(&file).is_none() && file.exists() { - changed |= self.load(&file, language).is_ok(); - checked_paths.insert(file); - } - } - - changed - } -} - -#[derive(Debug)] -pub struct Project<'a> { - pub documents: FxHashSet<&'a Document>, } |