diff options
Diffstat (limited to 'support/texlab/src/folding/bibtex_declaration.rs')
-rw-r--r-- | support/texlab/src/folding/bibtex_declaration.rs | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/support/texlab/src/folding/bibtex_declaration.rs b/support/texlab/src/folding/bibtex_declaration.rs new file mode 100644 index 0000000000..cea17daa7d --- /dev/null +++ b/support/texlab/src/folding/bibtex_declaration.rs @@ -0,0 +1,160 @@ +use crate::syntax::*; +use crate::workspace::*; +use futures_boxed::boxed; +use lsp_types::{FoldingRange, FoldingRangeKind, FoldingRangeParams}; + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct BibtexDeclarationFoldingProvider; + +impl FeatureProvider for BibtexDeclarationFoldingProvider { + type Params = FoldingRangeParams; + type Output = Vec<FoldingRange>; + + #[boxed] + async fn execute<'a>( + &'a self, + request: &'a FeatureRequest<FoldingRangeParams>, + ) -> Vec<FoldingRange> { + if let SyntaxTree::Bibtex(tree) = &request.document().tree { + tree.root.children.iter().flat_map(Self::fold).collect() + } else { + Vec::new() + } + } +} + +impl BibtexDeclarationFoldingProvider { + fn fold(declaration: &BibtexDeclaration) -> Option<FoldingRange> { + let ty = match declaration { + BibtexDeclaration::Comment(_) => None, + BibtexDeclaration::Preamble(preamble) => Some(&preamble.ty), + BibtexDeclaration::String(string) => Some(&string.ty), + BibtexDeclaration::Entry(entry) => Some(&entry.ty), + }?; + + let right = match declaration { + BibtexDeclaration::Comment(_) => None, + BibtexDeclaration::Preamble(preamble) => preamble.right.as_ref(), + BibtexDeclaration::String(string) => string.right.as_ref(), + BibtexDeclaration::Entry(entry) => entry.right.as_ref(), + }?; + + Some(FoldingRange { + start_line: ty.range().start.line, + start_character: Some(ty.range().start.character), + end_line: right.range().start.line, + end_character: Some(right.range().start.character), + kind: Some(FoldingRangeKind::Region), + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_preamble() { + let foldings = test_feature( + BibtexDeclarationFoldingProvider, + FeatureSpec { + files: vec![FeatureSpec::file("foo.bib", "\n@preamble{\"foo\"}")], + main_file: "foo.bib", + ..FeatureSpec::default() + }, + ); + assert_eq!( + foldings, + vec![FoldingRange { + start_line: 1, + start_character: Some(0), + end_line: 1, + end_character: Some(15), + kind: Some(FoldingRangeKind::Region), + }] + ); + } + + #[test] + fn test_string() { + let foldings = test_feature( + BibtexDeclarationFoldingProvider, + FeatureSpec { + files: vec![FeatureSpec::file("foo.bib", "@string{foo = \"bar\"}")], + main_file: "foo.bib", + ..FeatureSpec::default() + }, + ); + assert_eq!( + foldings, + vec![FoldingRange { + start_line: 0, + start_character: Some(0), + end_line: 0, + end_character: Some(19), + kind: Some(FoldingRangeKind::Region), + }] + ); + } + + #[test] + fn test_entry() { + let foldings = test_feature( + BibtexDeclarationFoldingProvider, + FeatureSpec { + files: vec![FeatureSpec::file("foo.bib", "@article{foo, bar = baz\n}")], + main_file: "foo.bib", + ..FeatureSpec::default() + }, + ); + assert_eq!( + foldings, + vec![FoldingRange { + start_line: 0, + start_character: Some(0), + end_line: 1, + end_character: Some(0), + kind: Some(FoldingRangeKind::Region), + }] + ); + } + + #[test] + fn test_comment() { + let foldings = test_feature( + BibtexDeclarationFoldingProvider, + FeatureSpec { + files: vec![FeatureSpec::file("foo.bib", "foo")], + main_file: "foo.bib", + ..FeatureSpec::default() + }, + ); + assert!(foldings.is_empty()); + } + + #[test] + fn test_entry_invalid() { + let foldings = test_feature( + BibtexDeclarationFoldingProvider, + FeatureSpec { + files: vec![FeatureSpec::file("foo.bib", "@article{foo,")], + main_file: "foo.bib", + ..FeatureSpec::default() + }, + ); + assert!(foldings.is_empty()); + } + + #[test] + fn test_latex() { + let foldings = test_feature( + BibtexDeclarationFoldingProvider, + FeatureSpec { + files: vec![FeatureSpec::file("foo.tex", "")], + main_file: "foo.tex", + ..FeatureSpec::default() + }, + ); + assert!(foldings.is_empty()); + } +} |