summaryrefslogtreecommitdiff
path: root/support/texlab/src/features/hover/component.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/features/hover/component.rs')
-rw-r--r--support/texlab/src/features/hover/component.rs105
1 files changed, 105 insertions, 0 deletions
diff --git a/support/texlab/src/features/hover/component.rs b/support/texlab/src/features/hover/component.rs
new file mode 100644
index 0000000000..abfdb781f1
--- /dev/null
+++ b/support/texlab/src/features/hover/component.rs
@@ -0,0 +1,105 @@
+use cancellation::CancellationToken;
+use lsp_types::{Hover, HoverContents, HoverParams};
+
+use crate::{
+ component_db::COMPONENT_DATABASE, features::cursor::CursorContext, syntax::latex, LineIndexExt,
+};
+
+pub fn find_component_hover(
+ context: &CursorContext<HoverParams>,
+ token: &CancellationToken,
+) -> Option<Hover> {
+ let main_document = context.request.main_document();
+ let data = main_document.data.as_latex()?;
+ for link in &data.extras.explicit_links {
+ if token.is_canceled() {
+ break;
+ }
+
+ if matches!(
+ link.kind,
+ latex::ExplicitLinkKind::Package | latex::ExplicitLinkKind::Class
+ ) && link.stem_range.contains_inclusive(context.offset)
+ {
+ let docs = COMPONENT_DATABASE.documentation(&link.stem)?;
+ return Some(Hover {
+ contents: HoverContents::Markup(docs),
+ range: Some(main_document.line_index.line_col_lsp_range(link.stem_range)),
+ });
+ }
+ }
+ None
+}
+
+#[cfg(test)]
+mod tests {
+ use lsp_types::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_component_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_component_hover(&context, CancellationToken::none());
+
+ assert_eq!(actual_hover, None);
+ }
+
+ #[test]
+ fn test_known_package() {
+ let request = FeatureTester::builder()
+ .files(vec![("main.tex", r#"\usepackage{amsmath}"#)])
+ .main("main.tex")
+ .line(0)
+ .character(15)
+ .build()
+ .hover();
+
+ let context = CursorContext::new(request);
+ let actual_hover = find_component_hover(&context, CancellationToken::none()).unwrap();
+
+ assert_eq!(actual_hover.range.unwrap(), Range::new_simple(0, 12, 0, 19));
+ }
+
+ #[test]
+ fn test_unknown_class() {
+ let request = FeatureTester::builder()
+ .files(vec![("main.tex", r#"\documentclass{abcdefghijklmnop}"#)])
+ .main("main.tex")
+ .line(0)
+ .character(20)
+ .build()
+ .hover();
+
+ let context = CursorContext::new(request);
+ let actual_hover = find_component_hover(&context, CancellationToken::none());
+
+ assert_eq!(actual_hover, None);
+ }
+}