diff options
Diffstat (limited to 'support/texlab/src/symbol/bibtex_entry.rs')
-rw-r--r-- | support/texlab/src/symbol/bibtex_entry.rs | 216 |
1 files changed, 111 insertions, 105 deletions
diff --git a/support/texlab/src/symbol/bibtex_entry.rs b/support/texlab/src/symbol/bibtex_entry.rs index f19c2fb734..f719937e80 100644 --- a/support/texlab/src/symbol/bibtex_entry.rs +++ b/support/texlab/src/symbol/bibtex_entry.rs @@ -1,42 +1,47 @@ -use super::{LatexSymbol, LatexSymbolKind}; -use crate::syntax::*; -use crate::workspace::*; -use futures_boxed::boxed; -use lsp_types::*; +use super::types::{LatexSymbol, LatexSymbolKind}; +use crate::{ + feature::{FeatureProvider, FeatureRequest}, + protocol::DocumentSymbolParams, + syntax::{bibtex, BibtexEntryTypeCategory, SyntaxNode, LANGUAGE_DATA}, + workspace::DocumentContent, +}; +use async_trait::async_trait; +use petgraph::graph::NodeIndex; -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)] pub struct BibtexEntrySymbolProvider; +#[async_trait] impl FeatureProvider for BibtexEntrySymbolProvider { type Params = DocumentSymbolParams; type Output = Vec<LatexSymbol>; - #[boxed] - async fn execute<'a>(&'a self, request: &'a FeatureRequest<Self::Params>) -> Self::Output { + async fn execute<'a>(&'a self, req: &'a FeatureRequest<Self::Params>) -> Self::Output { let mut symbols = Vec::new(); - if let SyntaxTree::Bibtex(tree) = &request.document().tree { - for entry in tree - .entries() - .iter() - .filter(|entry| !entry.is_comment()) - .filter(|entry| entry.key.is_some()) - { - let category = LANGUAGE_DATA - .find_entry_type(&entry.ty.text()[1..]) - .map(|ty| ty.category) - .unwrap_or(BibtexEntryTypeCategory::Misc); + if let DocumentContent::Bibtex(tree) = &req.current().content { + for entry_node in tree.children(tree.root) { + if let Some(entry) = tree + .as_entry(entry_node) + .filter(|entry| !entry.is_comment()) + .filter(|entry| entry.key.is_some()) + { + let category = LANGUAGE_DATA + .find_entry_type(&entry.ty.text()[1..]) + .map(|ty| ty.category) + .unwrap_or(BibtexEntryTypeCategory::Misc); - let key = entry.key.as_ref().unwrap(); - let symbol = LatexSymbol { - name: key.text().to_owned(), - label: None, - kind: LatexSymbolKind::Entry(category), - deprecated: false, - full_range: entry.range(), - selection_range: key.range(), - children: Self::field_symbols(&entry), - }; - symbols.push(symbol); + let key = entry.key.as_ref().unwrap(); + let symbol = LatexSymbol { + name: key.text().to_owned(), + label: None, + kind: LatexSymbolKind::Entry(category), + deprecated: false, + full_range: entry.range(), + selection_range: key.range(), + children: Self::field_symbols(tree, entry_node), + }; + symbols.push(symbol); + } } } symbols @@ -44,9 +49,12 @@ impl FeatureProvider for BibtexEntrySymbolProvider { } impl BibtexEntrySymbolProvider { - fn field_symbols(entry: &BibtexEntry) -> Vec<LatexSymbol> { + fn field_symbols(tree: &bibtex::Tree, entry_node: NodeIndex) -> Vec<LatexSymbol> { let mut symbols = Vec::new(); - for field in &entry.fields { + for field in tree + .children(entry_node) + .filter_map(|node| tree.as_field(node)) + { let symbol = LatexSymbol { name: field.name.text().to_owned(), label: None, @@ -65,83 +73,81 @@ impl BibtexEntrySymbolProvider { #[cfg(test)] mod tests { use super::*; - use crate::range::RangeExt; + use crate::{ + feature::FeatureTester, + protocol::{Range, RangeExt}, + }; - #[test] - fn test_entry() { - let symbols = test_feature( - BibtexEntrySymbolProvider, - FeatureSpec { - files: vec![FeatureSpec::file( - "foo.bib", - "@article{key, foo = bar, baz = qux}", - )], - main_file: "foo.bib", - ..FeatureSpec::default() - }, - ); - assert_eq!( - symbols, - vec![LatexSymbol { - name: "key".into(), - label: None, - kind: LatexSymbolKind::Entry(BibtexEntryTypeCategory::Article), - deprecated: false, - full_range: Range::new_simple(0, 0, 0, 35), - selection_range: Range::new_simple(0, 9, 0, 12), - children: vec![ - LatexSymbol { - name: "foo".into(), - label: None, - kind: LatexSymbolKind::Field, - deprecated: false, - full_range: Range::new_simple(0, 14, 0, 24), - selection_range: Range::new_simple(0, 14, 0, 17), - children: Vec::new(), - }, - LatexSymbol { - name: "baz".into(), - label: None, - kind: LatexSymbolKind::Field, - deprecated: false, - full_range: Range::new_simple(0, 25, 0, 34), - selection_range: Range::new_simple(0, 25, 0, 28), - children: Vec::new(), - }, - ], - }] - ); + #[tokio::test] + async fn empty_latex_document() { + let actual_symbols = FeatureTester::new() + .file("main.tex", "") + .main("main.tex") + .test_symbol(BibtexEntrySymbolProvider) + .await; + + assert!(actual_symbols.is_empty()); } - #[test] - fn test_comment() { - let symbols = test_feature( - BibtexEntrySymbolProvider, - FeatureSpec { - files: vec![FeatureSpec::file( - "foo.bib", - "@comment{key, foo = bar, baz = qux}", - )], - main_file: "foo.bib", - ..FeatureSpec::default() - }, - ); - assert_eq!(symbols, Vec::new()); + #[tokio::test] + async fn empty_bibtex_document() { + let actual_symbols = FeatureTester::new() + .file("main.bib", "") + .main("main.bib") + .test_symbol(BibtexEntrySymbolProvider) + .await; + + assert!(actual_symbols.is_empty()); + } + + #[tokio::test] + async fn entry() { + let actual_symbols = FeatureTester::new() + .file("main.bib", r#"@article{key, foo = bar, baz = qux}"#) + .main("main.bib") + .test_symbol(BibtexEntrySymbolProvider) + .await; + + let expected_symbols = vec![LatexSymbol { + name: "key".into(), + label: None, + kind: LatexSymbolKind::Entry(BibtexEntryTypeCategory::Article), + deprecated: false, + full_range: Range::new_simple(0, 0, 0, 35), + selection_range: Range::new_simple(0, 9, 0, 12), + children: vec![ + LatexSymbol { + name: "foo".into(), + label: None, + kind: LatexSymbolKind::Field, + deprecated: false, + full_range: Range::new_simple(0, 14, 0, 24), + selection_range: Range::new_simple(0, 14, 0, 17), + children: Vec::new(), + }, + LatexSymbol { + name: "baz".into(), + label: None, + kind: LatexSymbolKind::Field, + deprecated: false, + full_range: Range::new_simple(0, 25, 0, 34), + selection_range: Range::new_simple(0, 25, 0, 28), + children: Vec::new(), + }, + ], + }]; + + assert_eq!(actual_symbols, expected_symbols); } - #[test] - fn test_latex() { - let symbols = test_feature( - BibtexEntrySymbolProvider, - FeatureSpec { - files: vec![FeatureSpec::file( - "foo.tex", - "@article{key, foo = bar, baz = qux}", - )], - main_file: "foo.tex", - ..FeatureSpec::default() - }, - ); - assert_eq!(symbols, Vec::new()); + #[tokio::test] + async fn comment() { + let actual_symbols = FeatureTester::new() + .file("main.bib", r#"@comment{key, foo = bar, baz = qux}"#) + .main("main.bib") + .test_symbol(BibtexEntrySymbolProvider) + .await; + + assert!(actual_symbols.is_empty()); } } |