Skip to main content

oak_hover/
lib.rs

1#![feature(new_range_api)]
2#![warn(missing_docs)]
3#![doc = "Hover information provider for Oak languages."]
4//! Hover support for the Oak language framework.
5//!
6//! This crate provides traits and structures for providing hover information
7//! (documentation, type info, etc.) for code elements in an editor.
8
9use core::range::Range;
10use oak_core::{language::Language, tree::RedNode};
11
12/// Represents hover information.
13#[derive(Debug, Clone)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub struct Hover {
16    /// The hover's content as a markdown string.
17    pub contents: String,
18    /// An optional span to which this hover applies.
19    #[cfg_attr(feature = "serde", serde(with = "serde_range_opt", bound(serialize = "", deserialize = "")))]
20    pub range: Option<Range<usize>>,
21}
22
23#[cfg(feature = "serde")]
24mod serde_range_opt {
25    use super::*;
26    use serde::{Deserialize, Deserializer, Serializer};
27
28    pub fn serialize<S>(value: &Option<Range<usize>>, serializer: S) -> Result<S::Ok, S::Error>
29    where
30        S: Serializer,
31    {
32        match value {
33            Some(range) => oak_core::serde_range::serialize(range, serializer),
34            None => serializer.serialize_none(),
35        }
36    }
37
38    #[derive(Deserialize)]
39    struct RangeDef {
40        start: usize,
41        end: usize,
42    }
43
44    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Range<usize>>, D::Error>
45    where
46        D: Deserializer<'de>,
47    {
48        let opt: Option<RangeDef> = Option::deserialize(deserializer)?;
49        Ok(opt.map(|def| Range { start: def.start, end: def.end }))
50    }
51}
52
53/// Trait for languages that support hover information.
54pub trait HoverProvider<L: Language> {
55    /// Returns hover information at the given range.
56    fn hover(&self, root: &RedNode<L>, range: Range<usize>) -> Option<Hover>;
57}