summaryrefslogtreecommitdiff
path: root/support/texlab/src/workspace
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-05-26 03:01:06 +0000
committerNorbert Preining <norbert@preining.info>2022-05-26 03:01:06 +0000
commit02d941fa9c9895bb08a84ac9afe3559abd1ba8ad (patch)
tree481d1d368c6d295a779b590d23bcd5397bcba628 /support/texlab/src/workspace
parentf01a37f8311f33e32441d25bdadcda9dcdbd165d (diff)
CTAN sync 202205260301
Diffstat (limited to 'support/texlab/src/workspace')
-rw-r--r--support/texlab/src/workspace/api.rs89
-rw-r--r--support/texlab/src/workspace/children_expand.rs98
-rw-r--r--support/texlab/src/workspace/document.rs127
-rw-r--r--support/texlab/src/workspace/parent_expand.rs129
-rw-r--r--support/texlab/src/workspace/storage.rs145
-rw-r--r--support/texlab/src/workspace/watch.rs108
6 files changed, 0 insertions, 696 deletions
diff --git a/support/texlab/src/workspace/api.rs b/support/texlab/src/workspace/api.rs
deleted file mode 100644
index 6a3c3d02c9..0000000000
--- a/support/texlab/src/workspace/api.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-use std::{fs, path::PathBuf, sync::Arc};
-
-use anyhow::Result;
-use notify::RecursiveMode;
-
-use crate::{DocumentLanguage, Uri};
-
-use super::Document;
-
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
-pub enum WorkspaceSource {
- Client,
- Server,
-}
-
-#[derive(Debug, Clone)]
-pub struct WorkspaceSubset {
- pub documents: Vec<Arc<Document>>,
-}
-
-pub type OpenHandler = Arc<dyn Fn(Arc<dyn Workspace>, Arc<Document>) + Send + Sync + 'static>;
-
-pub trait Workspace: Send + Sync {
- fn open(
- &self,
- uri: Arc<Uri>,
- text: String,
- language: DocumentLanguage,
- source: WorkspaceSource,
- ) -> Arc<Document>;
-
- fn register_open_handler(&self, handler: OpenHandler);
-
- fn reload(&self, path: PathBuf) -> Result<Option<Arc<Document>>> {
- let uri = Arc::new(Uri::from_file_path(path.clone()).unwrap());
-
- if self.is_open(&uri) && !uri.as_str().ends_with(".log") {
- return Ok(self.get(&uri));
- }
-
- if let Some(language) = DocumentLanguage::by_path(&path) {
- let data = fs::read(&path)?;
- let text = String::from_utf8_lossy(&data).into_owned();
- Ok(Some(self.open(
- uri,
- text,
- language,
- WorkspaceSource::Server,
- )))
- } else {
- Ok(None)
- }
- }
-
- fn load(&self, path: PathBuf) -> Result<Option<Arc<Document>>> {
- let uri = Arc::new(Uri::from_file_path(path.clone()).unwrap());
-
- if let Some(document) = self.get(&uri) {
- return Ok(Some(document));
- }
-
- let data = fs::read(&path)?;
- let text = String::from_utf8_lossy(&data).into_owned();
- if let Some(language) = DocumentLanguage::by_path(&path) {
- Ok(Some(self.open(
- uri,
- text,
- language,
- WorkspaceSource::Server,
- )))
- } else {
- Ok(None)
- }
- }
-
- fn documents(&self) -> Vec<Arc<Document>>;
-
- fn has(&self, uri: &Uri) -> bool;
-
- fn get(&self, uri: &Uri) -> Option<Arc<Document>>;
-
- fn close(&self, uri: &Uri);
-
- fn is_open(&self, uri: &Uri) -> bool;
-
- fn subset(&self, uri: Arc<Uri>) -> Option<WorkspaceSubset>;
-
- fn watch(&self, path: PathBuf, mode: RecursiveMode) -> Result<()>;
-}
diff --git a/support/texlab/src/workspace/children_expand.rs b/support/texlab/src/workspace/children_expand.rs
deleted file mode 100644
index 8fecf2d503..0000000000
--- a/support/texlab/src/workspace/children_expand.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-use std::{path::PathBuf, sync::Arc};
-
-use anyhow::Result;
-use notify::RecursiveMode;
-use rayon::iter::{IntoParallelIterator, ParallelIterator};
-
-use crate::{
- component_db::COMPONENT_DATABASE, Document, DocumentLanguage, OpenHandler, Uri, Workspace,
- WorkspaceSource, WorkspaceSubset,
-};
-
-pub struct ChildrenExpander<W> {
- workspace: Arc<W>,
-}
-
-impl<W> ChildrenExpander<W>
-where
- W: Workspace + Send + Sync + 'static,
-{
- pub fn new(workspace: Arc<W>) -> Self {
- workspace.register_open_handler(Arc::new(move |workspace, document| {
- Self::expand(workspace.as_ref(), document.as_ref());
- }));
- Self { workspace }
- }
-
- fn expand(workspace: &dyn Workspace, 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);
- }
- }
-
- all_targets.into_par_iter().for_each(|targets| {
- for path in targets
- .iter()
- .filter(|uri| uri.scheme() == "file" && uri.fragment().is_none())
- .filter_map(|uri| uri.to_file_path().ok())
- {
- if workspace.load(path).is_ok() {
- break;
- }
- }
- });
- }
- }
-}
-
-impl<W: Workspace> Workspace for ChildrenExpander<W> {
- fn open(
- &self,
- uri: Arc<Uri>,
- text: String,
- language: DocumentLanguage,
- source: WorkspaceSource,
- ) -> Arc<Document> {
- self.workspace.open(uri, text, language, source)
- }
-
- fn register_open_handler(&self, handler: OpenHandler) {
- self.workspace.register_open_handler(handler)
- }
-
- fn documents(&self) -> Vec<Arc<Document>> {
- self.workspace.documents()
- }
-
- fn has(&self, uri: &Uri) -> bool {
- self.workspace.has(uri)
- }
-
- fn get(&self, uri: &Uri) -> Option<Arc<Document>> {
- self.workspace.get(uri)
- }
-
- fn close(&self, uri: &Uri) {
- self.workspace.close(uri)
- }
-
- fn is_open(&self, uri: &Uri) -> bool {
- self.workspace.is_open(uri)
- }
-
- fn subset(&self, uri: Arc<Uri>) -> Option<WorkspaceSubset> {
- self.workspace.subset(uri)
- }
-
- fn watch(&self, path: PathBuf, mode: RecursiveMode) -> Result<()> {
- self.workspace.watch(path, mode)
- }
-}
diff --git a/support/texlab/src/workspace/document.rs b/support/texlab/src/workspace/document.rs
deleted file mode 100644
index a98be226c1..0000000000
--- a/support/texlab/src/workspace/document.rs
+++ /dev/null
@@ -1,127 +0,0 @@
-use std::{fmt, sync::Arc};
-
-use derive_more::From;
-
-use crate::{
- line_index::LineIndex,
- syntax::{
- bibtex, build_log,
- latex::{self, LatexAnalyzerContext},
- },
- DocumentLanguage, ServerContext, Uri,
-};
-
-#[derive(Debug, Clone)]
-pub struct LatexDocumentData {
- pub root: latex::SyntaxNode,
- pub extras: latex::Extras,
-}
-
-#[derive(Debug, Clone)]
-pub struct BibtexDocumentData {
- pub root: bibtex::SyntaxNode,
-}
-
-#[derive(Debug, Clone, From)]
-pub enum DocumentData {
- Latex(LatexDocumentData),
- Bibtex(BibtexDocumentData),
- BuildLog(build_log::Parse),
-}
-
-impl DocumentData {
- pub fn language(&self) -> DocumentLanguage {
- match self {
- Self::Latex(_) => DocumentLanguage::Latex,
- Self::Bibtex(_) => DocumentLanguage::Bibtex,
- Self::BuildLog(_) => DocumentLanguage::BuildLog,
- }
- }
-
- pub fn as_latex(&self) -> Option<&LatexDocumentData> {
- if let Self::Latex(data) = self {
- Some(data)
- } else {
- None
- }
- }
-
- pub fn as_bibtex(&self) -> Option<&BibtexDocumentData> {
- if let Self::Bibtex(data) = self {
- Some(data)
- } else {
- None
- }
- }
-
- pub fn as_build_log(&self) -> Option<&build_log::Parse> {
- if let Self::BuildLog(v) = self {
- Some(v)
- } else {
- None
- }
- }
-}
-
-#[derive(Clone)]
-pub struct Document {
- pub uri: Arc<Uri>,
- pub text: String,
- pub line_index: LineIndex,
- pub data: DocumentData,
-}
-
-impl fmt::Debug for Document {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", self.uri)
- }
-}
-
-impl Document {
- pub fn parse(
- context: Arc<ServerContext>,
- uri: Arc<Uri>,
- text: String,
- language: DocumentLanguage,
- ) -> Self {
- let line_index = LineIndex::new(&text);
- let data = match language {
- DocumentLanguage::Latex => {
- let root = latex::parse(&text).root;
-
- let base_uri = match &context.options.read().unwrap().root_directory {
- Some(root_dir) => Uri::from_directory_path(root_dir)
- .map(Arc::new)
- .unwrap_or_else(|()| Arc::clone(&uri)),
- None => Arc::clone(&uri),
- };
- let mut context = LatexAnalyzerContext {
- inner: context,
- extras: latex::Extras::default(),
- document_uri: Arc::clone(&uri),
- base_uri,
- };
- latex::analyze(&mut context, &root);
- let extras = context.extras;
-
- LatexDocumentData { root, extras }.into()
- }
- DocumentLanguage::Bibtex => {
- let root = bibtex::parse(&text).root;
- BibtexDocumentData { root }.into()
- }
- DocumentLanguage::BuildLog => DocumentData::BuildLog(build_log::parse(&text)),
- };
-
- Self {
- uri,
- text,
- line_index,
- data,
- }
- }
-
- pub fn language(&self) -> DocumentLanguage {
- self.data.language()
- }
-}
diff --git a/support/texlab/src/workspace/parent_expand.rs b/support/texlab/src/workspace/parent_expand.rs
deleted file mode 100644
index 0eef06ce92..0000000000
--- a/support/texlab/src/workspace/parent_expand.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-use std::{fs, path::PathBuf, sync::Arc};
-
-use anyhow::Result;
-use notify::RecursiveMode;
-use rayon::iter::{IntoParallelIterator, ParallelIterator};
-use rustc_hash::FxHashSet;
-
-use crate::{
- Document, DocumentLanguage, OpenHandler, Uri, Workspace, WorkspaceSource, WorkspaceSubset,
-};
-
-pub struct ParentExpander<W> {
- workspace: W,
-}
-
-impl<W: Workspace> ParentExpander<W> {
- pub fn new(workspace: W) -> Self {
- Self { workspace }
- }
-}
-
-impl<W> Workspace for ParentExpander<W>
-where
- W: Workspace + Send + Sync + 'static,
-{
- fn open(
- &self,
- uri: Arc<Uri>,
- text: String,
- language: DocumentLanguage,
- source: WorkspaceSource,
- ) -> Arc<Document> {
- let document = self
- .workspace
- .open(Arc::clone(&uri), text, language, source);
-
- let all_current_paths = self
- .workspace
- .documents()
- .into_iter()
- .filter_map(|doc| doc.uri.to_file_path().ok())
- .collect::<FxHashSet<_>>();
-
- if uri.scheme() == "file" {
- if let Ok(mut path) = uri.to_file_path() {
- while path.pop() && !self.has_parent(Arc::clone(&uri)).unwrap_or(false) {
- let mut files = Vec::new();
- fs::read_dir(&path)
- .into_iter()
- .flatten()
- .filter_map(|entry| entry.ok())
- .filter(|entry| entry.file_type().ok().filter(|ty| ty.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| {
- files.push(path);
- });
- files.into_par_iter().for_each(|path| {
- let _ = self.workspace.load(path);
- });
- }
- }
- }
-
- document
- }
-
- fn register_open_handler(&self, handler: OpenHandler) {
- self.workspace.register_open_handler(handler)
- }
-
- fn documents(&self) -> Vec<Arc<Document>> {
- self.workspace.documents()
- }
-
- fn has(&self, uri: &Uri) -> bool {
- self.workspace.has(uri)
- }
-
- fn get(&self, uri: &Uri) -> Option<Arc<Document>> {
- self.workspace.get(uri)
- }
-
- fn close(&self, uri: &Uri) {
- self.workspace.close(uri)
- }
-
- fn is_open(&self, uri: &Uri) -> bool {
- self.workspace.is_open(uri)
- }
-
- fn subset(&self, uri: Arc<Uri>) -> Option<WorkspaceSubset> {
- self.workspace.subset(uri)
- }
-
- fn watch(&self, path: PathBuf, mode: RecursiveMode) -> Result<()> {
- self.workspace.watch(path, mode)
- }
-}
-
-impl<W> ParentExpander<W>
-where
- W: Workspace + Send + Sync + 'static,
-{
- fn has_parent(&self, uri: Arc<Uri>) -> Option<bool> {
- let subset = self.subset(Arc::clone(&uri))?;
- Some(subset.documents.iter().any(|document| {
- document
- .data
- .as_latex()
- .map(|data| {
- data.extras.has_document_environment
- && !data
- .extras
- .explicit_links
- .iter()
- .filter_map(|link| link.as_component_name())
- .any(|name| name == "subfiles.cls")
- })
- .unwrap_or(false)
- }))
- }
-}
diff --git a/support/texlab/src/workspace/storage.rs b/support/texlab/src/workspace/storage.rs
deleted file mode 100644
index 5f067a16aa..0000000000
--- a/support/texlab/src/workspace/storage.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-use std::{
- path::PathBuf,
- sync::{Arc, Mutex},
-};
-
-use anyhow::Result;
-use notify::RecursiveMode;
-use petgraph::{graphmap::UnGraphMap, visit::Dfs};
-use rustc_hash::{FxHashMap, FxHashSet};
-
-use crate::{
- Document, DocumentLanguage, OpenHandler, ServerContext, Uri, Workspace, WorkspaceSource,
- WorkspaceSubset,
-};
-
-#[derive(Clone)]
-pub struct Storage {
- context: Arc<ServerContext>,
- documents_by_uri: Arc<Mutex<FxHashMap<Arc<Uri>, Arc<Document>>>>,
- opened_documents: Arc<Mutex<FxHashSet<Arc<Uri>>>>,
- open_handlers: Arc<Mutex<Vec<OpenHandler>>>,
-}
-
-impl Storage {
- pub fn new(context: Arc<ServerContext>) -> Self {
- Self {
- context,
- documents_by_uri: Arc::default(),
- opened_documents: Arc::default(),
- open_handlers: Arc::default(),
- }
- }
-}
-
-impl Workspace for Storage {
- fn open(
- &self,
- uri: Arc<Uri>,
- text: String,
- language: DocumentLanguage,
- source: WorkspaceSource,
- ) -> Arc<Document> {
- log::debug!("(Re)Loading document: {}", uri);
- let document = Arc::new(Document::parse(
- Arc::clone(&self.context),
- Arc::clone(&uri),
- text,
- language,
- ));
- {
- self.documents_by_uri
- .lock()
- .unwrap()
- .insert(Arc::clone(&uri), Arc::clone(&document));
- }
-
- if source == WorkspaceSource::Client {
- self.opened_documents.lock().unwrap().insert(uri);
- }
-
- let handlers = { self.open_handlers.lock().unwrap().clone() };
- for handler in handlers {
- handler(Arc::new(self.clone()), Arc::clone(&document));
- }
-
- document
- }
-
- fn register_open_handler(&self, handler: OpenHandler) {
- self.open_handlers.lock().unwrap().push(handler);
- }
-
- fn documents(&self) -> Vec<Arc<Document>> {
- self.documents_by_uri
- .lock()
- .unwrap()
- .values()
- .cloned()
- .collect()
- }
-
- fn has(&self, uri: &Uri) -> bool {
- self.documents_by_uri.lock().unwrap().contains_key(uri)
- }
-
- fn get(&self, uri: &Uri) -> Option<Arc<Document>> {
- self.documents_by_uri.lock().unwrap().get(uri).cloned()
- }
-
- fn close(&self, uri: &Uri) {
- self.opened_documents.lock().unwrap().remove(uri);
- }
-
- fn is_open(&self, uri: &Uri) -> bool {
- self.opened_documents.lock().unwrap().contains(uri)
- }
-
- fn subset(&self, uri: Arc<Uri>) -> Option<WorkspaceSubset> {
- let all_current_uris: Vec<Arc<Uri>> = self
- .documents_by_uri
- .lock()
- .unwrap()
- .keys()
- .cloned()
- .collect();
-
- let mut edges = Vec::new();
- for (i, uri) in all_current_uris.iter().enumerate() {
- let document = self.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_current_uris.iter().position(|uri| uri == target) {
- edges.push((i, j, ()));
- break;
- }
- }
- }
- }
- }
-
- let graph = UnGraphMap::from_edges(edges);
- let start = all_current_uris.iter().position(|u| *u == uri)?;
- let mut dfs = Dfs::new(&graph, start);
- let mut documents = Vec::new();
- while let Some(i) = dfs.next(&graph) {
- documents.push(self.get(&all_current_uris[i])?);
- }
-
- Some(WorkspaceSubset { documents })
- }
-
- fn watch(&self, _path: PathBuf, _mode: RecursiveMode) -> Result<()> {
- Ok(())
- }
-}
diff --git a/support/texlab/src/workspace/watch.rs b/support/texlab/src/workspace/watch.rs
deleted file mode 100644
index 4cc1834620..0000000000
--- a/support/texlab/src/workspace/watch.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-use std::{
- path::PathBuf,
- sync::{Arc, Mutex},
-};
-
-use anyhow::Result;
-use log::warn;
-use notify::{RecommendedWatcher, RecursiveMode, Watcher};
-use rustc_hash::FxHashSet;
-
-use crate::{
- Document, DocumentLanguage, OpenHandler, Uri, Workspace, WorkspaceSource, WorkspaceSubset,
-};
-
-pub struct DocumentWatcher<W> {
- workspace: Arc<W>,
- watcher: Mutex<RecommendedWatcher>,
- watched_paths: Mutex<FxHashSet<PathBuf>>,
-}
-
-impl<W> DocumentWatcher<W>
-where
- W: Workspace + Send + Sync + 'static,
-{
- pub fn new(workspace: Arc<W>) -> Result<Self> {
- let watcher = Self::create_watcher(Arc::clone(&workspace))?;
- Ok(Self {
- workspace,
- watcher: Mutex::new(watcher),
- watched_paths: Mutex::default(),
- })
- }
-
- fn create_watcher(workspace: Arc<W>) -> Result<RecommendedWatcher> {
- let watcher = notify::recommended_watcher(move |event: notify::Result<notify::Event>| {
- if let Ok(event) = event {
- if event.kind.is_modify() {
- for path in event.paths {
- let _ = workspace.reload(path);
- }
- }
- }
- })?;
- Ok(watcher)
- }
-}
-
-impl<W: Workspace> Workspace for DocumentWatcher<W> {
- fn open(
- &self,
- uri: Arc<Uri>,
- text: String,
- language: DocumentLanguage,
- source: WorkspaceSource,
- ) -> Arc<Document> {
- let document = self.workspace.open(uri, text, language, source);
- if document.uri.scheme() == "file" {
- if let Ok(mut path) = document.uri.to_file_path() {
- path.pop();
- if let Err(why) = self.watch(path, RecursiveMode::NonRecursive) {
- warn!(
- "Failed to watch folder of document \"{}\": {}",
- document.uri, why
- );
- }
- }
- }
- document
- }
-
- fn register_open_handler(&self, handler: OpenHandler) {
- self.workspace.register_open_handler(handler);
- }
-
- fn documents(&self) -> Vec<Arc<Document>> {
- self.workspace.documents()
- }
-
- fn has(&self, uri: &Uri) -> bool {
- self.workspace.has(uri)
- }
-
- fn get(&self, uri: &Uri) -> Option<Arc<Document>> {
- self.workspace.get(uri)
- }
-
- fn close(&self, uri: &Uri) {
- self.workspace.close(uri)
- }
-
- fn is_open(&self, uri: &Uri) -> bool {
- self.workspace.is_open(uri)
- }
-
- fn subset(&self, uri: Arc<Uri>) -> Option<WorkspaceSubset> {
- self.workspace.subset(uri)
- }
-
- fn watch(&self, path: PathBuf, mode: RecursiveMode) -> Result<()> {
- let mut watched_paths = self.watched_paths.lock().unwrap();
- if !watched_paths.contains(&path) {
- self.watcher.lock().unwrap().watch(&path, mode)?;
- watched_paths.insert(path);
- }
-
- Ok(())
- }
-}