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<HoverContents>) -> 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::<HoverRequest>(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(),
})),
)
}