use std::fmt;
use serde::Serialize;
use super::problem::{FieldPath, Span, lines};
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Warning {
pub path: FieldPath,
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub span: Option<Span>,
pub reason: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub fix: Option<String>,
}
impl Warning {
#[must_use]
pub fn new(path: FieldPath, reason: impl Into<String>) -> Warning {
Warning {
path,
span: None,
reason: reason.into(),
fix: None,
}
}
#[must_use]
pub fn fix(mut self, fix: impl Into<String>) -> Warning {
self.fix = Some(fix.into());
self
}
#[must_use]
pub fn render(&self, file: &str) -> String {
lines(&format!("warning: {}", self.path), self.span, file, &self.reason, self.fix.as_deref())
}
}
impl fmt::Display for Warning {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.render("isoloom.yml"))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_warning_reads_as_three_lines() {
let mut w = Warning::new(FieldPath::new("machines.web.app.steps[1]"), "`nginx` starts on Debian VMs only").fix("`service: nginx`");
w.span = Some(Span { line: 9, column: 11 });
assert_eq!(
w.render("isoloom.yml"),
"warning: machines.web.app.steps[1] (isoloom.yml:9:11)\n `nginx` starts on Debian VMs only\n fix: `service: nginx`"
);
let json = serde_json::to_value(&w).unwrap();
assert_eq!((json["path"].as_str(), json["line"].as_u64()), (Some("machines.web.app.steps[1]"), Some(9)));
}
}