diff options
Diffstat (limited to 'support/texlab/src/folding/bibtex_decl.rs')
-rw-r--r-- | support/texlab/src/folding/bibtex_decl.rs | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/support/texlab/src/folding/bibtex_decl.rs b/support/texlab/src/folding/bibtex_decl.rs new file mode 100644 index 0000000000..f0ffa787e1 --- /dev/null +++ b/support/texlab/src/folding/bibtex_decl.rs @@ -0,0 +1,159 @@ +use crate::{ + feature::{FeatureProvider, FeatureRequest}, + protocol::{FoldingRange, FoldingRangeKind, FoldingRangeParams}, + syntax::{bibtex, SyntaxNode}, + workspace::DocumentContent, +}; +use async_trait::async_trait; +use petgraph::graph::NodeIndex; + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)] +pub struct BibtexDeclarationFoldingProvider; + +#[async_trait] +impl FeatureProvider for BibtexDeclarationFoldingProvider { + type Params = FoldingRangeParams; + type Output = Vec<FoldingRange>; + + async fn execute<'a>(&'a self, req: &'a FeatureRequest<Self::Params>) -> Self::Output { + if let DocumentContent::Bibtex(tree) = &req.current().content { + tree.children(tree.root) + .filter_map(|decl| Self::fold(tree, decl)) + .collect() + } else { + Vec::new() + } + } +} + +impl BibtexDeclarationFoldingProvider { + fn fold(tree: &bibtex::Tree, decl: NodeIndex) -> Option<FoldingRange> { + let (ty, right) = match &tree.graph[decl] { + bibtex::Node::Preamble(preamble) => (Some(&preamble.ty), preamble.right.as_ref()), + bibtex::Node::String(string) => (Some(&string.ty), string.right.as_ref()), + bibtex::Node::Entry(entry) => (Some(&entry.ty), entry.right.as_ref()), + bibtex::Node::Root(_) + | bibtex::Node::Comment(_) + | bibtex::Node::Field(_) + | bibtex::Node::Word(_) + | bibtex::Node::Command(_) + | bibtex::Node::QuotedContent(_) + | bibtex::Node::BracedContent(_) + | bibtex::Node::Concat(_) => (None, None), + }; + + Some(FoldingRange { + start_line: ty?.start().line, + start_character: Some(ty?.start().character), + end_line: right?.end().line, + end_character: Some(right?.end().character), + kind: Some(FoldingRangeKind::Region), + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::feature::FeatureTester; + use indoc::indoc; + + #[tokio::test] + async fn preamble() { + let actual_foldings = FeatureTester::new() + .file("main.bib", r#"@preamble{"foo"}"#) + .main("main.bib") + .test_folding(BibtexDeclarationFoldingProvider) + .await; + + let expected_foldings = vec![FoldingRange { + start_line: 0, + start_character: Some(0), + end_line: 0, + end_character: Some(16), + kind: Some(FoldingRangeKind::Region), + }]; + + assert_eq!(actual_foldings, expected_foldings); + } + + #[tokio::test] + async fn string() { + let actual_foldings = FeatureTester::new() + .file("main.bib", r#"@string{foo = "bar"}"#) + .main("main.bib") + .test_folding(BibtexDeclarationFoldingProvider) + .await; + + let expected_foldings = vec![FoldingRange { + start_line: 0, + start_character: Some(0), + end_line: 0, + end_character: Some(20), + kind: Some(FoldingRangeKind::Region), + }]; + + assert_eq!(actual_foldings, expected_foldings); + } + + #[tokio::test] + async fn entry() { + let actual_foldings = FeatureTester::new() + .file( + "main.bib", + indoc!( + r#" + @article{foo, + bar = baz + } + "# + ), + ) + .main("main.bib") + .test_folding(BibtexDeclarationFoldingProvider) + .await; + + let expected_foldings = vec![FoldingRange { + start_line: 0, + start_character: Some(0), + end_line: 2, + end_character: Some(1), + kind: Some(FoldingRangeKind::Region), + }]; + + assert_eq!(actual_foldings, expected_foldings); + } + + #[tokio::test] + async fn comment() { + let actual_foldings = FeatureTester::new() + .file("main.bib", "foo") + .main("main.bib") + .test_folding(BibtexDeclarationFoldingProvider) + .await; + + assert!(actual_foldings.is_empty()); + } + + #[tokio::test] + async fn entry_invalid() { + let actual_foldings = FeatureTester::new() + .file("main.bib", "@article{foo,") + .main("main.bib") + .test_folding(BibtexDeclarationFoldingProvider) + .await; + + assert!(actual_foldings.is_empty()); + } + + #[tokio::test] + async fn latex() { + let actual_foldings = FeatureTester::new() + .file("main.tex", "foo") + .main("main.tex") + .test_folding(BibtexDeclarationFoldingProvider) + .await; + + assert!(actual_foldings.is_empty()); + } +} |