diff options
Diffstat (limited to 'support/texlab/src/hover/latex_label.rs')
-rw-r--r-- | support/texlab/src/hover/latex_label.rs | 71 |
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 + } +} |