diff options
Diffstat (limited to 'support/texlab/src/symbol/mod.rs')
-rw-r--r-- | support/texlab/src/symbol/mod.rs | 231 |
1 files changed, 74 insertions, 157 deletions
diff --git a/support/texlab/src/symbol/mod.rs b/support/texlab/src/symbol/mod.rs index ec68d70c3e..b292f15bb2 100644 --- a/support/texlab/src/symbol/mod.rs +++ b/support/texlab/src/symbol/mod.rs @@ -2,122 +2,30 @@ mod bibtex_entry; mod bibtex_string; mod latex_section; mod project_order; - -use self::bibtex_entry::BibtexEntrySymbolProvider; -use self::bibtex_string::BibtexStringSymbolProvider; -use self::latex_section::LatexSectionSymbolProvider; -use self::project_order::ProjectOrdering; -use crate::capabilities::ClientCapabilitiesExt; -use crate::lsp_kind::Structure; -use crate::syntax::*; -use crate::workspace::*; -use futures_boxed::boxed; -use lsp_types::*; -use serde::{Deserialize, Serialize}; -use std::cmp::Reverse; -use std::sync::Arc; +mod types; pub use self::latex_section::{build_section_tree, LatexSectionNode, LatexSectionTree}; -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum LatexSymbolKind { - Section, - Figure, - Algorithm, - Table, - Listing, - Enumeration, - EnumerationItem, - Theorem, - Equation, - Entry(BibtexEntryTypeCategory), - Field, - String, -} - -impl Into<SymbolKind> for LatexSymbolKind { - fn into(self) -> SymbolKind { - match self { - Self::Section => Structure::Section.symbol_kind(), - Self::Figure | Self::Algorithm | Self::Table | Self::Listing => { - Structure::Float.symbol_kind() - } - Self::Enumeration => Structure::Environment.symbol_kind(), - Self::EnumerationItem => Structure::Item.symbol_kind(), - Self::Theorem => Structure::Theorem.symbol_kind(), - Self::Equation => Structure::Equation.symbol_kind(), - Self::Entry(category) => Structure::Entry(category).symbol_kind(), - Self::Field => Structure::Field.symbol_kind(), - Self::String => Structure::Entry(BibtexEntryTypeCategory::String).symbol_kind(), - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone)] -pub struct LatexSymbol { - pub name: String, - pub label: Option<String>, - pub kind: LatexSymbolKind, - pub deprecated: bool, - pub full_range: Range, - pub selection_range: Range, - pub children: Vec<LatexSymbol>, -} - -impl LatexSymbol { - pub fn search_text(&self) -> String { - let kind = match self.kind { - LatexSymbolKind::Section => "latex section", - LatexSymbolKind::Figure => "latex float figure", - LatexSymbolKind::Algorithm => "latex float algorithm", - LatexSymbolKind::Table => "latex float table", - LatexSymbolKind::Listing => "latex float listing", - LatexSymbolKind::Enumeration => "latex enumeration", - LatexSymbolKind::EnumerationItem => "latex enumeration item", - LatexSymbolKind::Theorem => "latex math", - LatexSymbolKind::Equation => "latex math equation", - LatexSymbolKind::Entry(_) => "bibtex entry", - LatexSymbolKind::Field => "bibtex field", - LatexSymbolKind::String => "bibtex string", - }; - format!("{} {}", kind, self.name).to_lowercase() - } - - pub fn flatten(mut self, buffer: &mut Vec<Self>) { - if self.kind == LatexSymbolKind::Field { - return; - } - for symbol in self.children.drain(..) { - symbol.flatten(buffer); - } - buffer.push(self); - } - - pub fn into_symbol_info(self, uri: Uri) -> SymbolInformation { - SymbolInformation { - name: self.name, - deprecated: Some(self.deprecated), - kind: self.kind.into(), - container_name: None, - location: Location::new(uri.clone().into(), self.full_range), - } - } -} - -impl Into<DocumentSymbol> for LatexSymbol { - fn into(self) -> DocumentSymbol { - let children = self.children.into_iter().map(Into::into).collect(); - DocumentSymbol { - name: self.name, - deprecated: Some(self.deprecated), - detail: self.label, - kind: self.kind.into(), - selection_range: self.selection_range, - range: self.full_range, - children: Some(children), - } - } -} +use self::{ + bibtex_entry::BibtexEntrySymbolProvider, bibtex_string::BibtexStringSymbolProvider, + latex_section::LatexSectionSymbolProvider, project_order::ProjectOrdering, types::LatexSymbol, +}; +use crate::{ + feature::{ConcatProvider, DocumentView, FeatureProvider, FeatureRequest}, + protocol::{ + ClientCapabilities, ClientCapabilitiesExt, DocumentSymbolParams, DocumentSymbolResponse, + Options, PartialResultParams, SymbolInformation, TextDocumentIdentifier, Uri, + WorkDoneProgressParams, WorkspaceSymbolParams, + }, + tex::Distribution, + workspace::Snapshot, +}; +use async_trait::async_trait; +use std::{ + cmp::Reverse, + path::{Path, PathBuf}, + sync::Arc, +}; pub struct SymbolProvider { provider: ConcatProvider<DocumentSymbolParams, LatexSymbol>, @@ -141,44 +49,37 @@ impl Default for SymbolProvider { } } +#[async_trait] impl FeatureProvider for SymbolProvider { type Params = DocumentSymbolParams; type Output = Vec<LatexSymbol>; - #[boxed] - async fn execute<'a>(&'a self, request: &'a FeatureRequest<Self::Params>) -> Self::Output { - self.provider.execute(request).await + async fn execute<'a>(&'a self, req: &'a FeatureRequest<Self::Params>) -> Self::Output { + self.provider.execute(req).await } } -#[serde(untagged)] -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub enum SymbolResponse { - Flat(Vec<SymbolInformation>), - Hierarchical(Vec<DocumentSymbol>), -} - -impl SymbolResponse { - pub fn new( - client_capabilities: &ClientCapabilities, - workspace: &Workspace, - uri: &Uri, - symbols: Vec<LatexSymbol>, - ) -> Self { - if client_capabilities.has_hierarchical_document_symbol_support() { - Self::Hierarchical(symbols.into_iter().map(Into::into).collect()) - } else { - let mut buffer = Vec::new(); - for symbol in symbols { - symbol.flatten(&mut buffer); - } - let mut buffer = buffer - .into_iter() - .map(|symbol| symbol.into_symbol_info(uri.clone())) - .collect(); - sort_symbols(workspace, &mut buffer); - Self::Flat(buffer) +pub fn document_symbols( + client_capabilities: &ClientCapabilities, + snapshot: &Snapshot, + uri: &Uri, + options: &Options, + current_dir: &Path, + symbols: Vec<LatexSymbol>, +) -> DocumentSymbolResponse { + if client_capabilities.has_hierarchical_document_symbol_support() { + DocumentSymbolResponse::Nested(symbols.into_iter().map(Into::into).collect()) + } else { + let mut buffer = Vec::new(); + for symbol in symbols { + symbol.flatten(&mut buffer); } + let mut buffer = buffer + .into_iter() + .map(|symbol| symbol.into_symbol_info(uri.clone())) + .collect(); + sort_symbols(snapshot, options, ¤t_dir, &mut buffer); + DocumentSymbolResponse::Flat(buffer) } } @@ -187,28 +88,39 @@ struct WorkspaceSymbol { search_text: String, } -pub async fn workspace_symbols( - distribution: Arc<Box<dyn tex::Distribution>>, +pub async fn workspace_symbols<'a>( + distro: Arc<dyn Distribution>, client_capabilities: Arc<ClientCapabilities>, - workspace: Arc<Workspace>, - params: &WorkspaceSymbolParams, + snapshot: Arc<Snapshot>, + options: &'a Options, + current_dir: Arc<PathBuf>, + params: &'a WorkspaceSymbolParams, ) -> Vec<SymbolInformation> { let provider = SymbolProvider::new(); let mut symbols = Vec::new(); - for document in &workspace.documents { - let uri: Uri = document.uri.clone(); - let request = FeatureRequest { - client_capabilities: Arc::clone(&client_capabilities), - view: DocumentView::new(Arc::clone(&workspace), Arc::clone(&document)), + for doc in &snapshot.0 { + let uri: Uri = doc.uri.clone(); + let req = FeatureRequest { params: DocumentSymbolParams { text_document: TextDocumentIdentifier::new(uri.clone().into()), + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), }, - distribution: Arc::clone(&distribution), + view: DocumentView::analyze( + Arc::clone(&snapshot), + Arc::clone(&doc), + &options, + ¤t_dir, + ), + distro: distro.clone(), + client_capabilities: Arc::clone(&client_capabilities), + options: options.clone(), + current_dir: Arc::clone(¤t_dir), }; let mut buffer = Vec::new(); - for symbol in provider.execute(&request).await { + for symbol in provider.execute(&req).await { symbol.flatten(&mut buffer); } @@ -239,12 +151,17 @@ pub async fn workspace_symbols( filtered.push(symbol.info); } } - sort_symbols(&workspace, &mut filtered); + sort_symbols(&snapshot, options, ¤t_dir, &mut filtered); filtered } -fn sort_symbols(workspace: &Workspace, symbols: &mut Vec<SymbolInformation>) { - let ordering = ProjectOrdering::new(workspace); +fn sort_symbols( + snapshot: &Snapshot, + options: &Options, + current_dir: &Path, + symbols: &mut Vec<SymbolInformation>, +) { + let ordering = ProjectOrdering::analyze(snapshot, options, current_dir); symbols.sort_by(|left, right| { let left_key = ( ordering.get(&Uri::from(left.location.uri.clone())), |