diff options
Diffstat (limited to 'support/texlab/src/features/hover/citation.rs')
-rw-r--r-- | support/texlab/src/features/hover/citation.rs | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/support/texlab/src/features/hover/citation.rs b/support/texlab/src/features/hover/citation.rs new file mode 100644 index 0000000000..1fd6d6c06b --- /dev/null +++ b/support/texlab/src/features/hover/citation.rs @@ -0,0 +1,133 @@ +use cancellation::CancellationToken; +use lsp_types::{Hover, HoverContents, HoverParams}; + +use crate::{citation, features::cursor::CursorContext, LineIndexExt}; + +pub fn find_citation_hover( + context: &CursorContext<HoverParams>, + cancellation_token: &CancellationToken, +) -> Option<Hover> { + cancellation_token.result().ok()?; + let main_document = context.request.main_document(); + + let (key_text, key_range) = context + .find_citation_key_word() + .or_else(|| context.find_citation_key_command()) + .or_else(|| context.find_entry_key())?; + + let contents = context + .request + .subset + .documents + .iter() + .find_map(|document| { + document + .data + .as_bibtex() + .and_then(|data| citation::render_citation(&data.root, &key_text)) + })?; + + Some(Hover { + range: Some(main_document.line_index.line_col_lsp_range(key_range)), + contents: HoverContents::Markup(contents), + }) +} + +#[cfg(test)] +mod tests { + use lsp_types::{MarkupContent, MarkupKind, Range}; + + use crate::{features::testing::FeatureTester, RangeExt}; + + use super::*; + + #[test] + fn test_empty_latex_document() { + let request = FeatureTester::builder() + .files(vec![("main.tex", "")]) + .main("main.tex") + .line(0) + .character(0) + .build() + .hover(); + + let context = CursorContext::new(request); + let actual_hover = find_citation_hover(&context, CancellationToken::none()); + + assert_eq!(actual_hover, None); + } + + #[test] + fn test_empty_bibtex_document() { + let request = FeatureTester::builder() + .files(vec![("main.bib", "")]) + .main("main.bib") + .line(0) + .character(0) + .build() + .hover(); + + let context = CursorContext::new(request); + let actual_hover = find_citation_hover(&context, CancellationToken::none()); + + assert_eq!(actual_hover, None); + } + + #[test] + fn test_inside_cite() { + let request = FeatureTester::builder() + .files(vec![ + ( + "main.bib", + "@article{foo, author = {Foo Bar}, title = {Baz Qux}, year = 1337}", + ), + ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"), + ]) + .main("main.tex") + .line(1) + .character(7) + .build() + .hover(); + + let context = CursorContext::new(request); + let actual_hover = find_citation_hover(&context, CancellationToken::none()).unwrap(); + + let expected_hover = Hover { + contents: HoverContents::Markup(MarkupContent { + kind: MarkupKind::Markdown, + value: "Bar, F. (1337). *Baz Qux*.".into(), + }), + range: Some(Range::new_simple(1, 6, 1, 9)), + }; + assert_eq!(actual_hover, expected_hover); + } + + #[test] + fn test_inside_entry() { + let request = FeatureTester::builder() + .files(vec![ + ( + "main.bib", + "@article{foo, author = {Foo Bar}, title = {Baz Qux}, year = 1337}", + ), + ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"), + ]) + .main("main.bib") + .line(0) + .character(11) + .build() + .hover(); + + let context = CursorContext::new(request); + let actual_hover = find_citation_hover(&context, CancellationToken::none()).unwrap(); + + let expected_hover = Hover { + contents: HoverContents::Markup(MarkupContent { + kind: MarkupKind::Markdown, + value: "Bar, F. (1337). *Baz Qux*.".into(), + }), + range: Some(Range::new_simple(0, 9, 0, 12)), + }; + assert_eq!(actual_hover, expected_hover); + } +} |