use nonempty::NonEmpty;
use crate::concern::lint::Level;
use crate::concern::lint::TagSet;
use crate::concern::lint::Warning;
use crate::concern::Code;
use crate::file::Location;
#[derive(Debug)]
pub enum MissingError {
Code,
Level,
Tags,
Location,
Subject,
Body,
}
impl std::fmt::Display for MissingError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MissingError::Code => write!(f, "code"),
MissingError::Level => write!(f, "level"),
MissingError::Tags => write!(f, "tags"),
MissingError::Location => write!(f, "location"),
MissingError::Subject => write!(f, "subject"),
MissingError::Body => write!(f, "body"),
}
}
}
impl std::error::Error for MissingError {}
#[derive(Debug)]
pub enum Error {
Missing(MissingError),
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::Missing(err) => write!(f, "missing value for field: {err}"),
}
}
}
impl std::error::Error for Error {}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Default)]
pub struct Builder {
code: Option<Code>,
level: Option<Level>,
tags: Option<TagSet>,
locations: Option<NonEmpty<Location>>,
subject: Option<String>,
body: Option<String>,
fix: Option<String>,
}
impl Builder {
pub fn code(mut self, code: Code) -> Self {
self.code = Some(code);
self
}
pub fn level(mut self, level: Level) -> Self {
self.level = Some(level);
self
}
pub fn tags(mut self, tags: TagSet) -> Self {
self.tags = Some(tags);
self
}
pub fn push_location(mut self, location: Location) -> Self {
let locations = match self.locations {
Some(mut locations) => {
locations.push(location);
locations
}
None => NonEmpty::new(location),
};
self.locations = Some(locations);
self
}
pub fn subject(mut self, subject: impl Into<String>) -> Self {
let subject = subject.into();
self.subject = Some(subject);
self
}
pub fn body(mut self, body: impl Into<String>) -> Self {
let body = body.into();
self.body = Some(body);
self
}
pub fn fix(mut self, fix: impl Into<String>) -> Self {
let fix = fix.into();
self.fix = Some(fix);
self
}
pub fn try_build(self) -> Result<Warning> {
let code = self
.code
.map(Ok)
.unwrap_or(Err(Error::Missing(MissingError::Code)))?;
let level = self
.level
.map(Ok)
.unwrap_or(Err(Error::Missing(MissingError::Level)))?;
let tags = self
.tags
.map(Ok)
.unwrap_or(Err(Error::Missing(MissingError::Tags)))?;
let locations = self
.locations
.map(Ok)
.unwrap_or(Err(Error::Missing(MissingError::Location)))?;
let subject = self
.subject
.map(Ok)
.unwrap_or(Err(Error::Missing(MissingError::Subject)))?;
let body = self
.body
.map(Ok)
.unwrap_or(Err(Error::Missing(MissingError::Body)))?;
Ok(Warning {
code,
level,
tags,
locations,
subject,
body,
fix: self.fix,
})
}
}