summaryrefslogtreecommitdiff
path: root/support/texlab/crates/base-db/src/graph.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/crates/base-db/src/graph.rs')
-rw-r--r--support/texlab/crates/base-db/src/graph.rs191
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);
- }
- }
- }
-}