isoloom_spec/syntax/
warning.rs1use std::fmt;
11
12use serde::Serialize;
13
14use super::problem::{FieldPath, Span, lines};
15
16#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
18pub struct Warning {
19 pub path: FieldPath,
21 #[serde(flatten, skip_serializing_if = "Option::is_none")]
23 pub span: Option<Span>,
24 pub reason: String,
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub fix: Option<String>,
29}
30
31impl Warning {
32 #[must_use]
34 pub fn new(path: FieldPath, reason: impl Into<String>) -> Warning {
35 Warning {
36 path,
37 span: None,
38 reason: reason.into(),
39 fix: None,
40 }
41 }
42
43 #[must_use]
45 pub fn fix(mut self, fix: impl Into<String>) -> Warning {
46 self.fix = Some(fix.into());
47 self
48 }
49
50 #[must_use]
52 pub fn render(&self, file: &str) -> String {
53 lines(&format!("warning: {}", self.path), self.span, file, &self.reason, self.fix.as_deref())
54 }
55}
56
57impl fmt::Display for Warning {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 f.write_str(&self.render("isoloom.yml"))
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn a_warning_reads_as_three_lines() {
69 let mut w = Warning::new(FieldPath::new("machines.web.app.steps[1]"), "`nginx` starts on Debian VMs only").fix("`service: nginx`");
70 w.span = Some(Span { line: 9, column: 11 });
71 assert_eq!(
72 w.render("isoloom.yml"),
73 "warning: machines.web.app.steps[1] (isoloom.yml:9:11)\n `nginx` starts on Debian VMs only\n fix: `service: nginx`"
74 );
75 let json = serde_json::to_value(&w).unwrap();
76 assert_eq!((json["path"].as_str(), json["line"].as_u64()), (Some("machines.web.app.steps[1]"), Some(9)));
77 }
78}