summaryrefslogtreecommitdiff
path: root/support/texlab/src/hover/latex_label.rs
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-12-03 03:01:24 +0000
committerNorbert Preining <norbert@preining.info>2019-12-03 03:01:24 +0000
commitb8d4bb76703bcb15578e2b23c5d256532180b894 (patch)
treebedd1df7a00521a2bd986b3c0289d6556a59e39b /support/texlab/src/hover/latex_label.rs
parent02e4625a78a5029e8b5dc2a4ec70193b232f497e (diff)
CTAN sync 201912030301
Diffstat (limited to 'support/texlab/src/hover/latex_label.rs')
-rw-r--r--support/texlab/src/hover/latex_label.rs71
1 files changed, 71 insertions, 0 deletions
diff --git a/support/texlab/src/hover/latex_label.rs b/support/texlab/src/hover/latex_label.rs
new file mode 100644
index 0000000000..2b3a8f51e7
--- /dev/null
+++ b/support/texlab/src/hover/latex_label.rs
@@ -0,0 +1,71 @@
+use crate::range::RangeExt;
+use crate::syntax::*;
+use crate::workspace::*;
+use futures_boxed::boxed;
+use lsp_types::*;
+use std::sync::Arc;
+
+pub struct LatexLabelHoverProvider;
+
+impl FeatureProvider for LatexLabelHoverProvider {
+ type Params = TextDocumentPositionParams;
+ type Output = Option<Hover>;
+
+ #[boxed]
+ async fn execute<'a>(&'a self, request: &'a FeatureRequest<Self::Params>) -> Self::Output {
+ if let SyntaxTree::Latex(tree) = &request.document().tree {
+ let reference = Self::find_reference(tree, request.params.position)?;
+ let (document, definition) = Self::find_definition(&request.view, reference)?;
+
+ let workspace = Arc::clone(&request.view.workspace);
+ let view = DocumentView::new(workspace, document);
+ let outline = Outline::from(&view);
+ let outline_context = OutlineContext::parse(&view, &definition, &outline)?;
+ let markup = outline_context.documentation();
+ Some(Hover {
+ contents: HoverContents::Markup(markup),
+ range: Some(reference.range()),
+ })
+ } else {
+ None
+ }
+ }
+}
+
+impl LatexLabelHoverProvider {
+ fn find_reference(tree: &LatexSyntaxTree, position: Position) -> Option<&LatexToken> {
+ for label in &tree.structure.labels {
+ let names = label.names();
+ if names.len() == 1 && label.range().contains(position) {
+ return Some(&label.names()[0]);
+ }
+
+ for name in &names {
+ if name.range().contains(position) {
+ return Some(name);
+ }
+ }
+ }
+ None
+ }
+
+ fn find_definition<'a, 'b>(
+ view: &'a DocumentView,
+ reference: &'b LatexToken,
+ ) -> Option<(Arc<Document>, &'a LatexLabel)> {
+ for document in &view.related_documents {
+ if let SyntaxTree::Latex(tree) = &document.tree {
+ for label in &tree.structure.labels {
+ if label.kind == LatexLabelKind::Definition {
+ for name in label.names() {
+ if name.text() == reference.text() {
+ return Some((Arc::clone(&document), label));
+ }
+ }
+ }
+ }
+ }
+ }
+ None
+ }
+}