baobao_codegen/pipeline/
diagnostic.rs1use serde::Serialize;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
10pub enum Severity {
11 Error,
13 Warning,
15 Info,
17}
18
19impl Severity {
20 pub fn is_error(&self) -> bool {
22 matches!(self, Severity::Error)
23 }
24
25 pub fn is_warning(&self) -> bool {
27 matches!(self, Severity::Warning)
28 }
29}
30
31impl std::fmt::Display for Severity {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 match self {
34 Severity::Error => write!(f, "error"),
35 Severity::Warning => write!(f, "warning"),
36 Severity::Info => write!(f, "info"),
37 }
38 }
39}
40
41#[derive(Debug, Clone, Serialize)]
43pub struct Diagnostic {
44 pub severity: Severity,
46 pub phase: String,
48 pub message: String,
50 pub location: Option<String>,
52}
53
54impl Diagnostic {
55 pub fn error(phase: impl Into<String>, message: impl Into<String>) -> Self {
57 Self {
58 severity: Severity::Error,
59 phase: phase.into(),
60 message: message.into(),
61 location: None,
62 }
63 }
64
65 pub fn warning(phase: impl Into<String>, message: impl Into<String>) -> Self {
67 Self {
68 severity: Severity::Warning,
69 phase: phase.into(),
70 message: message.into(),
71 location: None,
72 }
73 }
74
75 pub fn info(phase: impl Into<String>, message: impl Into<String>) -> Self {
77 Self {
78 severity: Severity::Info,
79 phase: phase.into(),
80 message: message.into(),
81 location: None,
82 }
83 }
84
85 pub fn at(mut self, location: impl Into<String>) -> Self {
87 self.location = Some(location.into());
88 self
89 }
90}
91
92impl std::fmt::Display for Diagnostic {
93 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94 write!(f, "{}: {}", self.severity, self.message)?;
95 if let Some(loc) = &self.location {
96 write!(f, " (at {})", loc)?;
97 }
98 Ok(())
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn test_diagnostic_error() {
108 let diag = Diagnostic::error("validate", "invalid command name");
109 assert!(diag.severity.is_error());
110 assert_eq!(diag.phase, "validate");
111 }
112
113 #[test]
114 fn test_diagnostic_with_location() {
115 let diag = Diagnostic::warning("validate", "missing description").at("commands.deploy");
116 assert!(diag.location.is_some());
117 assert_eq!(diag.location.as_deref(), Some("commands.deploy"));
118 }
119
120 #[test]
121 fn test_severity_display() {
122 assert_eq!(Severity::Error.to_string(), "error");
123 assert_eq!(Severity::Warning.to_string(), "warning");
124 assert_eq!(Severity::Info.to_string(), "info");
125 }
126}