use std::fmt;
use serde::Serialize;
use crate::report::{Code, Severity, SourceInfo};
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(untagged)]
pub enum Target {
Path { path: String },
Commit { commit: String },
Range {},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct HistoryDiagnostic {
#[serde(flatten)]
pub target: Target,
pub code: Code,
pub line: Option<u32>,
pub rule: Option<String>,
pub severity: Severity,
pub message: String,
}
impl HistoryDiagnostic {
#[must_use]
pub fn new(target: Target, code: Code, message: impl Into<String>) -> Self {
Self {
target,
code,
line: None,
rule: None,
severity: code.severity(),
message: message.into(),
}
}
#[must_use]
pub fn at_line(mut self, line: Option<u32>) -> Self {
self.line = line;
self
}
#[must_use]
pub fn with_rule(mut self, rule: Option<String>) -> Self {
self.rule = rule;
self
}
}
impl fmt::Display for HistoryDiagnostic {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.target {
Target::Path { path } => f.write_str(path)?,
Target::Commit { commit } => write!(f, "commit {commit}")?,
Target::Range {} => f.write_str("range")?,
}
if let Some(line) = self.line {
write!(f, ":{line}")?;
}
write!(f, ":{}", self.code)?;
if let Some(rule) = &self.rule {
write!(f, "[{rule}]")?;
}
write!(f, ": {}", self.message)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Resolved {
pub revision: String,
pub id: String,
}
#[derive(Debug, Default, Serialize)]
pub struct HistoryReport {
pub ok: bool,
pub mode: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<SourceInfo>,
#[serde(skip_serializing_if = "Option::is_none")]
pub base: Option<Resolved>,
#[serde(skip_serializing_if = "Option::is_none")]
pub head: Option<Resolved>,
pub commits: usize,
pub diagnostics: Vec<HistoryDiagnostic>,
pub fatal: Option<String>,
}
impl HistoryReport {
#[must_use]
pub fn fatal(message: impl Into<String>) -> Self {
Self {
ok: false,
fatal: Some(message.into()),
..Self::default()
}
}
}