diff options
Diffstat (limited to 'support/texlab/crates/base-db/src/graph.rs')
-rw-r--r-- | support/texlab/crates/base-db/src/graph.rs | 191 |
1 files changed, 0 insertions, 191 deletions
diff --git a/support/texlab/crates/base-db/src/graph.rs b/support/texlab/crates/base-db/src/graph.rs deleted file mode 100644 index 2148c7e269..0000000000 --- a/support/texlab/crates/base-db/src/graph.rs +++ /dev/null @@ -1,191 +0,0 @@ -use std::{ffi::OsStr, path::PathBuf}; - -use distro::Language; -use itertools::Itertools; -use once_cell::sync::Lazy; -use percent_encoding::percent_decode_str; -use rustc_hash::FxHashSet; -use url::Url; - -use crate::{semantics, Document, DocumentData, Workspace}; - -pub static HOME_DIR: Lazy<Option<PathBuf>> = Lazy::new(dirs::home_dir); - -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub struct Edge<'a> { - pub source: &'a Document, - pub target: &'a Document, - pub weight: Option<EdgeWeight<'a>>, -} - -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub struct EdgeWeight<'a> { - pub link: &'a semantics::tex::Link, - pub old_base_dir: Url, - pub new_base_dir: Url, -} - -#[derive(Debug)] -pub struct Graph<'a> { - pub workspace: &'a Workspace, - pub start: &'a Document, - pub edges: Vec<Edge<'a>>, - pub missing: Vec<Url>, -} - -impl<'a> Graph<'a> { - pub fn new(workspace: &'a Workspace, start: &'a Document) -> Self { - let mut graph = Self { - workspace, - start, - edges: Vec::new(), - missing: Vec::new(), - }; - - let base_dir = workspace.current_dir(&start.dir); - let mut stack = vec![(start, base_dir)]; - let mut visited = FxHashSet::default(); - - while let Some((source, base_dir)) = stack.pop() { - let index = graph.edges.len(); - graph.add_explicit_edges(source, &base_dir); - for edge in &graph.edges[index..] { - let Some(weight) = edge.weight.as_ref() else { - continue; - }; - - if visited.insert(&edge.target.uri) { - stack.push((edge.target, weight.new_base_dir.clone())); - } - } - - graph.add_implicit_edges(source, &base_dir); - } - - graph - } - - pub fn preorder(&self) -> impl DoubleEndedIterator<Item = &'a Document> + '_ { - std::iter::once(self.start) - .chain(self.edges.iter().map(|group| group.target)) - .unique_by(|document| &document.uri) - } - - fn add_explicit_edges(&mut self, source: &'a Document, base_dir: &Url) { - let DocumentData::Tex(data) = &source.data else { - return; - }; - - let uri = source.uri.as_str(); - let is_pkg = uri.ends_with(".sty") || uri.ends_with(".cls"); - if is_pkg && !self.workspace.config().syntax.follow_package_links { - return; - } - - for link in &data.semantics.links { - self.add_link(source, base_dir, link); - } - } - - fn add_link(&mut self, source: &'a Document, base_dir: &Url, link: &'a semantics::tex::Link) { - let home_dir = HOME_DIR.as_deref(); - - let stem = &link.path.text; - let mut file_names = vec![stem.clone()]; - link.kind - .extensions() - .iter() - .map(|ext| format!("{stem}.{ext}")) - .for_each(|name| file_names.push(name)); - - let file_name_db = &self.workspace.distro().file_name_db; - let distro_files = file_names - .iter() - .filter_map(|name| file_name_db.get(name)) - .filter(|path| { - home_dir.map_or(false, |dir| path.starts_with(dir)) - || Language::from_path(path) == Some(Language::Bib) - }) - .flat_map(Url::from_file_path); - - for target_uri in file_names - .iter() - .flat_map(|file_name| base_dir.join(file_name)) - .chain(distro_files) - { - match self.workspace.lookup(&target_uri) { - Some(target) => { - let new_base_dir = link - .base_dir - .as_deref() - .and_then(|path| base_dir.join(path).ok()) - .unwrap_or_else(|| base_dir.clone()); - - let weight = Some(EdgeWeight { - link, - old_base_dir: base_dir.clone(), - new_base_dir, - }); - - self.edges.push(Edge { - source, - target, - weight, - }); - - break; - } - None => { - self.missing.push(target_uri); - } - }; - } - } - - fn add_implicit_edges(&mut self, source: &'a Document, base_dir: &Url) { - if source.language == Language::Tex { - let aux_dir = self.workspace.aux_dir(base_dir); - let log_dir = self.workspace.log_dir(base_dir); - - let relative_path = base_dir.make_relative(&source.uri).unwrap(); - - self.add_artifact(source, &aux_dir.join(&relative_path).unwrap(), "aux"); - self.add_artifact(source, &aux_dir, "aux"); - self.add_artifact(source, base_dir, "aux"); - - self.add_artifact(source, &log_dir.join(&relative_path).unwrap(), "log"); - self.add_artifact(source, &log_dir, "log"); - self.add_artifact(source, base_dir, "log"); - } - } - - fn add_artifact(&mut self, source: &'a Document, base_dir: &Url, extension: &str) { - let mut path = PathBuf::from( - percent_decode_str(source.uri.path()) - .decode_utf8_lossy() - .as_ref(), - ); - - path.set_extension(extension); - let Some(target_uri) = path - .file_name() - .and_then(OsStr::to_str) - .and_then(|name| base_dir.join(name).ok()) - else { - return; - }; - - match self.workspace.lookup(&target_uri) { - Some(target) => { - self.edges.push(Edge { - source, - target, - weight: None, - }); - } - None => { - self.missing.push(target_uri); - } - } - } -} |