use std::fmt;
use super::path::Path;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Severity {
Error,
Warning,
Unsupported,
}
impl fmt::Display for Severity {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let text = match self {
Self::Error => "error",
Self::Warning => "warning",
Self::Unsupported => "unsupported",
};
formatter.write_str(text)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Finding {
pub severity: Severity,
pub rule: String,
pub path: Path,
pub message: String,
}
impl Finding {
#[must_use]
pub fn error(rule: impl Into<String>, path: Path, message: impl Into<String>) -> Self {
Self {
severity: Severity::Error,
rule: rule.into(),
path,
message: message.into(),
}
}
#[must_use]
pub fn warning(rule: impl Into<String>, path: Path, message: impl Into<String>) -> Self {
Self {
severity: Severity::Warning,
rule: rule.into(),
path,
message: message.into(),
}
}
#[must_use]
pub fn unsupported(rule: impl Into<String>, path: Path, message: impl Into<String>) -> Self {
Self {
severity: Severity::Unsupported,
rule: rule.into(),
path,
message: message.into(),
}
}
}
impl fmt::Display for Finding {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
formatter,
"{}: {} at {}: {}",
self.severity, self.rule, self.path, self.message
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use ifc_model::EntityId;
#[test]
fn errors_sort_before_warnings_before_unsupported() {
let mut severities = [Severity::Unsupported, Severity::Warning, Severity::Error];
severities.sort();
assert_eq!(
severities,
[Severity::Error, Severity::Warning, Severity::Unsupported]
);
}
#[test]
fn a_finding_names_where_it_applies() {
let finding = Finding::error(
"structure.dangling",
Path::Attribute {
entity: EntityId(12),
index: 3,
name: Some("Representation".into()),
},
"points at #99, which does not exist",
);
assert_eq!(finding.path.to_string(), "#12.Representation");
assert_eq!(finding.severity, Severity::Error);
}
}