From b8d4bb76703bcb15578e2b23c5d256532180b894 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Tue, 3 Dec 2019 03:01:24 +0000 Subject: CTAN sync 201912030301 --- .../texlab/src/hover/bibtex_string_reference.rs | 106 +++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 support/texlab/src/hover/bibtex_string_reference.rs (limited to 'support/texlab/src/hover/bibtex_string_reference.rs') diff --git a/support/texlab/src/hover/bibtex_string_reference.rs b/support/texlab/src/hover/bibtex_string_reference.rs new file mode 100644 index 0000000000..28df138291 --- /dev/null +++ b/support/texlab/src/hover/bibtex_string_reference.rs @@ -0,0 +1,106 @@ +use crate::formatting::bibtex::{self, BibtexFormattingParams}; +use crate::syntax::*; +use crate::workspace::*; +use futures_boxed::boxed; +use lsp_types::*; + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct BibtexStringReferenceHoverProvider; + +impl FeatureProvider for BibtexStringReferenceHoverProvider { + type Params = TextDocumentPositionParams; + type Output = Option; + + #[boxed] + async fn execute<'a>(&'a self, request: &'a FeatureRequest) -> Self::Output { + if let SyntaxTree::Bibtex(tree) = &request.document().tree { + let reference = Self::find_reference(tree, request.params.position)?; + for declaration in &tree.root.children { + if let BibtexDeclaration::String(string) = &declaration { + let definition = Self::find_definition(string, reference); + if definition.is_some() { + return definition; + } + } + } + } + None + } +} + +impl BibtexStringReferenceHoverProvider { + fn find_reference(tree: &BibtexSyntaxTree, position: Position) -> Option<&BibtexToken> { + let mut results = tree.find(position); + results.reverse(); + match (&results[0], results.get(1)) { + (BibtexNode::Word(reference), Some(BibtexNode::Concat(_))) => Some(&reference.token), + (BibtexNode::Word(reference), Some(BibtexNode::Field(_))) => Some(&reference.token), + _ => None, + } + } + + fn find_definition(string: &BibtexString, reference: &BibtexToken) -> Option { + if string.name.as_ref()?.text() != reference.text() { + return None; + } + + let text = + bibtex::format_content(string.value.as_ref()?, &BibtexFormattingParams::default()); + Some(Hover { + contents: HoverContents::Markup(MarkupContent { + kind: MarkupKind::PlainText, + value: text, + }), + range: Some(reference.range()), + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::range::RangeExt; + + #[test] + fn test_inside_reference() { + let hover = test_feature( + BibtexStringReferenceHoverProvider, + FeatureSpec { + files: vec![FeatureSpec::file( + "foo.bib", + "@string{foo = \"Foo\"}\n@string{bar = \"Bar\"}\n@article{baz, author = bar}", + )], + main_file: "foo.bib", + position: Position::new(2, 24), + ..FeatureSpec::default() + }, + ); + assert_eq!( + hover, + Some(Hover { + contents: HoverContents::Markup(MarkupContent { + kind: MarkupKind::PlainText, + value: "\"Bar\"".into(), + }), + range: Some(Range::new_simple(2, 23, 2, 26)), + }) + ); + } + + #[test] + fn test_outside_reference() { + let hover = test_feature( + BibtexStringReferenceHoverProvider, + FeatureSpec { + files: vec![FeatureSpec::file( + "foo.bib", + "@string{foo = \"Foo\"}\n@string{bar = \"Bar\"}\n@article{baz, author = bar}", + )], + main_file: "foo.bib", + position: Position::new(2, 20), + ..FeatureSpec::default() + }, + ); + assert_eq!(hover, None); + } +} -- cgit v1.2.3