1 use cancellation::CancellationToken;
2 use lsp_types::{Hover, HoverContents, HoverParams};
3
4 use crate::{
5 component_db::COMPONENT_DATABASE, features::cursor::CursorContext, syntax::latex, LineIndexExt,
6 };
7
find_component_hover( context: &CursorContext<HoverParams>, token: &CancellationToken, ) -> Option<Hover>8 pub fn find_component_hover(
9 context: &CursorContext<HoverParams>,
10 token: &CancellationToken,
11 ) -> Option<Hover> {
12 let main_document = context.request.main_document();
13 let data = main_document.data.as_latex()?;
14 for link in &data.extras.explicit_links {
15 if token.is_canceled() {
16 break;
17 }
18
19 if matches!(
20 link.kind,
21 latex::ExplicitLinkKind::Package | latex::ExplicitLinkKind::Class
22 ) && link.stem_range.contains_inclusive(context.offset)
23 {
24 let docs = COMPONENT_DATABASE.documentation(&link.stem)?;
25 return Some(Hover {
26 contents: HoverContents::Markup(docs),
27 range: Some(main_document.line_index.line_col_lsp_range(link.stem_range)),
28 });
29 }
30 }
31 None
32 }
33
34 #[cfg(test)]
35 mod tests {
36 use lsp_types::Range;
37
38 use crate::{features::testing::FeatureTester, RangeExt};
39
40 use super::*;
41
42 #[test]
test_empty_latex_document()43 fn test_empty_latex_document() {
44 let request = FeatureTester::builder()
45 .files(vec![("main.tex", "")])
46 .main("main.tex")
47 .line(0)
48 .character(0)
49 .build()
50 .hover();
51
52 let context = CursorContext::new(request);
53 let actual_hover = find_component_hover(&context, CancellationToken::none());
54
55 assert_eq!(actual_hover, None);
56 }
57
58 #[test]
test_empty_bibtex_document()59 fn test_empty_bibtex_document() {
60 let request = FeatureTester::builder()
61 .files(vec![("main.bib", "")])
62 .main("main.bib")
63 .line(0)
64 .character(0)
65 .build()
66 .hover();
67
68 let context = CursorContext::new(request);
69 let actual_hover = find_component_hover(&context, CancellationToken::none());
70
71 assert_eq!(actual_hover, None);
72 }
73
74 #[test]
test_known_package()75 fn test_known_package() {
76 let request = FeatureTester::builder()
77 .files(vec![("main.tex", r#"\usepackage{amsmath}"#)])
78 .main("main.tex")
79 .line(0)
80 .character(15)
81 .build()
82 .hover();
83
84 let context = CursorContext::new(request);
85 let actual_hover = find_component_hover(&context, CancellationToken::none()).unwrap();
86
87 assert_eq!(actual_hover.range.unwrap(), Range::new_simple(0, 12, 0, 19));
88 }
89
90 #[test]
test_unknown_class()91 fn test_unknown_class() {
92 let request = FeatureTester::builder()
93 .files(vec![("main.tex", r#"\documentclass{abcdefghijklmnop}"#)])
94 .main("main.tex")
95 .line(0)
96 .character(20)
97 .build()
98 .hover();
99
100 let context = CursorContext::new(request);
101 let actual_hover = find_component_hover(&context, CancellationToken::none());
102
103 assert_eq!(actual_hover, None);
104 }
105 }
106