ifc_validate/report/
finding.rs1use std::fmt;
17
18use super::path::Path;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub enum Severity {
23 Error,
25 Warning,
27 Unsupported,
29}
30
31impl fmt::Display for Severity {
32 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
33 let text = match self {
34 Self::Error => "error",
35 Self::Warning => "warning",
36 Self::Unsupported => "unsupported",
37 };
38 formatter.write_str(text)
39 }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
44pub struct Finding {
45 pub severity: Severity,
47 pub rule: String,
51 pub path: Path,
53 pub message: String,
55}
56
57impl Finding {
58 #[must_use]
60 pub fn error(rule: impl Into<String>, path: Path, message: impl Into<String>) -> Self {
61 Self {
62 severity: Severity::Error,
63 rule: rule.into(),
64 path,
65 message: message.into(),
66 }
67 }
68
69 #[must_use]
71 pub fn warning(rule: impl Into<String>, path: Path, message: impl Into<String>) -> Self {
72 Self {
73 severity: Severity::Warning,
74 rule: rule.into(),
75 path,
76 message: message.into(),
77 }
78 }
79
80 #[must_use]
82 pub fn unsupported(rule: impl Into<String>, path: Path, message: impl Into<String>) -> Self {
83 Self {
84 severity: Severity::Unsupported,
85 rule: rule.into(),
86 path,
87 message: message.into(),
88 }
89 }
90}
91
92impl fmt::Display for Finding {
93 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
94 write!(
95 formatter,
96 "{}: {} at {}: {}",
97 self.severity, self.rule, self.path, self.message
98 )
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105 use ifc_model::EntityId;
106
107 #[test]
109 fn errors_sort_before_warnings_before_unsupported() {
110 let mut severities = [Severity::Unsupported, Severity::Warning, Severity::Error];
111 severities.sort();
112 assert_eq!(
113 severities,
114 [Severity::Error, Severity::Warning, Severity::Unsupported]
115 );
116 }
117
118 #[test]
120 fn a_finding_names_where_it_applies() {
121 let finding = Finding::error(
122 "structure.dangling",
123 Path::Attribute {
124 entity: EntityId(12),
125 index: 3,
126 name: Some("Representation".into()),
127 },
128 "points at #99, which does not exist",
129 );
130 assert_eq!(finding.path.to_string(), "#12.Representation");
131 assert_eq!(finding.severity, Severity::Error);
132 }
133}