use crate::location::SourceLocation;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(tag = "kind"))]
pub enum Annotation {
Message {
text: String,
location: SourceLocation,
},
Suggestion {
text: String,
location: SourceLocation,
},
}
impl Annotation {
#[must_use]
pub fn text(&self) -> &str {
match self {
Self::Message { text, .. } | Self::Suggestion { text, .. } => text,
}
}
#[must_use]
pub fn location(&self) -> &SourceLocation {
match self {
Self::Message { location, .. } | Self::Suggestion { location, .. } => location,
}
}
}
pub(crate) fn headline(annotations: &[Annotation]) -> Option<&str> {
annotations
.iter()
.rev()
.find_map(|annotation| match annotation {
Annotation::Message { text, .. } => Some(text.as_str()),
Annotation::Suggestion { .. } => None,
})
}
pub struct Message {
pub(crate) text: String,
}
impl Message {
#[must_use]
pub fn new(text: impl Into<String>) -> Self {
Self { text: text.into() }
}
}
pub trait IntoMessage {
fn into_message(self) -> Message;
}
impl IntoMessage for &str {
fn into_message(self) -> Message {
Message::new(self)
}
}
impl IntoMessage for String {
fn into_message(self) -> Message {
Message::new(self)
}
}
impl<F, M> IntoMessage for F
where
F: FnOnce() -> M,
M: IntoMessage,
{
fn into_message(self) -> Message {
self().into_message()
}
}
pub struct Suggestion {
pub(crate) text: String,
}
impl Suggestion {
#[must_use]
pub fn new(text: impl Into<String>) -> Self {
Self { text: text.into() }
}
}
pub trait IntoSuggestion {
fn into_suggestion(self) -> Suggestion;
}
impl IntoSuggestion for &str {
fn into_suggestion(self) -> Suggestion {
Suggestion::new(self)
}
}
impl IntoSuggestion for String {
fn into_suggestion(self) -> Suggestion {
Suggestion::new(self)
}
}
impl<F, S> IntoSuggestion for F
where
F: FnOnce() -> S,
S: IntoSuggestion,
{
fn into_suggestion(self) -> Suggestion {
self().into_suggestion()
}
}