use std::{fmt, sync::Arc}; use derive_more::From; use lsp_types::Url; use crate::{ line_index::LineIndex, syntax::{ bibtex, build_log, latex::{self, LatexAnalyzerContext}, }, DocumentLanguage, Environment, }; #[derive(Debug, Clone)] pub struct LatexDocumentData { pub green: rowan::GreenNode, pub extras: Arc, } #[derive(Debug, Clone)] pub struct BibtexDocumentData { pub green: rowan::GreenNode, } #[derive(Debug, Clone, From)] pub enum DocumentData { Latex(Box), Bibtex(BibtexDocumentData), BuildLog(Arc), } impl DocumentData { #[must_use] pub fn language(&self) -> DocumentLanguage { match self { Self::Latex(_) => DocumentLanguage::Latex, Self::Bibtex(_) => DocumentLanguage::Bibtex, Self::BuildLog(_) => DocumentLanguage::BuildLog, } } #[must_use] pub fn as_latex(&self) -> Option<&LatexDocumentData> { if let Self::Latex(data) = self { Some(data) } else { None } } #[must_use] pub fn as_bibtex(&self) -> Option<&BibtexDocumentData> { if let Self::Bibtex(data) = self { Some(data) } else { None } } #[must_use] 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, pub text: Arc, pub line_index: Arc, pub data: DocumentData, } impl fmt::Debug for Document { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.uri) } } impl Document { #[must_use] pub fn parse( environment: &Environment, uri: Arc, text: Arc, language: DocumentLanguage, ) -> Self { let line_index = Arc::new(LineIndex::new(&text)); let data = match language { DocumentLanguage::Latex => { let green = latex::parse(&text).green; let root = latex::SyntaxNode::new_root(green.clone()); let base_uri = match &environment.options.root_directory { Some(root_dir) => { let root_dir = environment.current_directory.join(&root_dir); Url::from_directory_path(root_dir) .map_or_else(|()| Arc::clone(&uri), Arc::new) } None => Arc::clone(&uri), }; let mut context = LatexAnalyzerContext { environment, extras: latex::Extras::default(), document_uri: Arc::clone(&uri), base_uri, }; latex::analyze(&mut context, &root); let extras = Arc::new(context.extras); DocumentData::Latex(Box::new(LatexDocumentData { green, extras })) } DocumentLanguage::Bibtex => { let green = bibtex::parse(&text); DocumentData::Bibtex(BibtexDocumentData { green }) } DocumentLanguage::BuildLog => { let data = Arc::new(build_log::parse(&text)); DocumentData::BuildLog(data) } }; Self { uri, text, line_index, data, } } }