use anyhow::Result; use lsp_types::{ request::HoverRequest, ClientCapabilities, Hover, HoverContents, HoverParams, MarkupContent, MarkupKind, }; use texlab::{component_db::COMPONENT_DATABASE, LANGUAGE_DATA}; use crate::lsp::{client::Client, fixture}; fn check(fixture: &str, contents: Option) -> Result<()> { let mut client = Client::spawn()?; client.initialize(ClientCapabilities::default(), None)?; let fixture = fixture::parse(fixture); for file in fixture.files { client.open(file.name, file.lang, file.text)?; } let range = fixture .ranges .values() .next() .and_then(|map| map.values().next()) .map(|file_range| file_range.range); let actual_hover = client.request::(HoverParams { text_document_position_params: fixture.cursor.unwrap().into_params(&client)?, work_done_progress_params: Default::default(), })?; client.shutdown()?; let expected_hover = contents.map(|contents| Hover { range, contents }); assert_eq!(actual_hover, expected_hover); Ok(()) } #[test] fn empty_latex_document() -> Result<()> { check( r#" %TEX main.tex %SRC %CUR ^ "#, None, ) } #[test] fn empty_bibtex_document() -> Result<()> { check( r#" %BIB main.bib %SRC %CUR ^ "#, None, ) } #[test] fn citation_inside_cite() -> Result<()> { check( r#" %BIB main.bib %SRC @article{foo, author = {Foo Bar}, title = {Baz Qux}, year = 1337} %TEX main.tex %SRC \addbibresource{main.bib} %SRC \cite{foo} %CUR ^ %1.1 ^^^ "#, Some(HoverContents::Markup(MarkupContent { kind: MarkupKind::Markdown, value: "F. Bar: \"Baz Qux\". (1337).".to_string(), })), ) } #[test] fn citation_inside_entry() -> Result<()> { check( r#" %BIB main.bib %SRC @article{foo, author = {Foo Bar}, title = {Baz Qux}, year = 1337} %CUR ^ %1.1 ^^^ %TEX main.tex %SRC \addbibresource{main.bib} %SRC \cite{foo} "#, Some(HoverContents::Markup(MarkupContent { kind: MarkupKind::Markdown, value: "F. Bar: \"Baz Qux\". (1337).".to_string(), })), ) } #[test] fn component_known_package() -> Result<()> { check( r#" %TEX main.tex %SRC \usepackage{amsmath} %CUR ^ %1.1 ^^^^^^^ "#, COMPONENT_DATABASE .documentation("amsmath") .map(HoverContents::Markup), ) } #[test] fn component_unknown_class() -> Result<()> { check( r#" %TEX main.tex %SRC \documentclass{abcdefghijklmnop} %CUR ^ "#, None, ) } #[test] fn entry_type_known_type() -> Result<()> { check( r#" %BIB main.bib %SRC @article{foo,} %CUR ^ %1.1 ^^^^^^^^ "#, Some(HoverContents::Markup(MarkupContent { kind: MarkupKind::Markdown, value: LANGUAGE_DATA .entry_type_documentation("article") .unwrap() .to_string(), })), ) } #[test] fn entry_type_unknown_field() -> Result<()> { check( r#" %BIB main.bib %SRC @foo{bar,} %CUR ^ "#, None, ) } #[test] fn entry_type_key() -> Result<()> { check( r#" %BIB main.bib %SRC @foo{bar,} %CUR ^ "#, None, ) } #[test] fn field_known() -> Result<()> { check( r#" %BIB main.bib %SRC @article{foo, author = bar} %CUR ^ %1.1 ^^^^^^ "#, Some(HoverContents::Markup(MarkupContent { kind: MarkupKind::Markdown, value: LANGUAGE_DATA .field_documentation("author") .unwrap() .to_string(), })), ) } #[test] fn field_unknown() -> Result<()> { check( r#" %BIB main.bib %SRC @article{foo, bar = baz} %CUR ^ "#, None, ) } #[test] fn section() -> Result<()> { check( r#" %TEX main.tex %SRC \section{Foo} %SRC \label{sec:foo} %CUR ^ %1.1 ^^^^^^^ "#, Some(HoverContents::Markup(MarkupContent { kind: MarkupKind::PlainText, value: "Section (Foo)".to_string(), })), ) } #[test] fn string_inside_reference() -> Result<()> { check( r#" %BIB main.bib %SRC @string{foo = "Foo"} %SRC @string{bar = "Bar"} %SRC @article{baz, author = bar} %CUR ^ %1.1 ^^^ "#, Some(HoverContents::Markup(MarkupContent { kind: MarkupKind::PlainText, value: "Bar".to_string(), })), ) } #[test] fn string_inside_field() -> Result<()> { check( r#" %BIB main.bib %SRC @string{foo = "Foo"} %SRC @string{bar = "Bar"} %SRC @article{baz, author = bar} %CUR ^ "#, None, ) } #[test] fn label_theorem_child_file() -> Result<()> { check( r#" %TEX main.tex %SRC \documentclass{article} %SRC \newtheorem{lemma}{Lemma} %SRC \include{child} %SRC \ref{thm:foo} %CUR ^ %1.1 ^^^^^^^ %TEX child.tex %SRC \begin{lemma}\label{thm:foo} %SRC 1 + 1 = 2 %SRC \end{lemma} "#, Some(HoverContents::Markup(MarkupContent { kind: MarkupKind::PlainText, value: "Lemma".to_string(), })), ) } #[test] fn label_theorem_child_file_mumber() -> Result<()> { check( r#" %TEX main.tex %SRC \documentclass{article} %SRC \newtheorem{lemma}{Lemma} %SRC \include{child} %SRC \ref{thm:foo} %CUR ^ %1.1 ^^^^^^^ %TEX child.tex %SRC \begin{lemma}[Foo]\label{thm:foo} %SRC 1 + 1 = 2 %SRC \end{lemma} %TEX child.aux %SRC \newlabel{thm:foo}{{1}{1}{Foo}{lemma.1}{}} "#, Some(HoverContents::Markup(MarkupContent { kind: MarkupKind::PlainText, value: "Lemma 1 (Foo)".to_string(), })), ) }