use super::{Error, Result};
use std::{
fmt::{self, Display},
ops::Range,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Severity {
Info,
Warning,
Error,
}
impl Display for Severity {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Info => f.write_str("info"),
Self::Warning => f.write_str("warning"),
Self::Error => f.write_str("error"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Annotation {
range: Range<usize>,
pub header: Option<String>,
pub text: Option<String>,
pub severity: Severity,
}
pub trait AnnotationText {
fn into_option_string(self) -> Option<String>;
}
impl AnnotationText for String {
fn into_option_string(self) -> Option<String> {
Some(self)
}
}
impl AnnotationText for &'_ str {
fn into_option_string(self) -> Option<String> {
Some(self.into())
}
}
impl AnnotationText for Option<String> {
fn into_option_string(self) -> Option<String> {
self
}
}
impl Annotation {
pub fn new(
range: Range<usize>,
severity: Severity,
header: impl AnnotationText,
text: impl AnnotationText,
) -> Result<Self> {
if range.end < range.start {
Err(Error::InvalidRange(range.start, range.end))
} else {
Ok(Self {
range,
severity,
header: header.into_option_string(),
text: text.into_option_string(),
})
}
}
pub fn info(
range: Range<usize>,
header: impl AnnotationText,
text: impl AnnotationText,
) -> Result<Self> {
Self::new(range, Severity::Info, header, text)
}
pub fn warning(
range: Range<usize>,
header: impl AnnotationText,
text: impl AnnotationText,
) -> Result<Self> {
Self::new(range, Severity::Warning, header, text)
}
pub fn error(
range: Range<usize>,
header: impl AnnotationText,
text: impl AnnotationText,
) -> Result<Self> {
Self::new(range, Severity::Error, header, text)
}
pub fn range(&self) -> &Range<usize> {
&self.range
}
}