use std::fmt;
use crate::offense::Offense;
use crate::source::SourceFile;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Category {
Layout,
Style,
Lint,
Naming,
Metrics,
}
impl fmt::Display for Category {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Category::Layout => write!(f, "Layout"),
Category::Style => write!(f, "Style"),
Category::Lint => write!(f, "Lint"),
Category::Naming => write!(f, "Naming"),
Category::Metrics => write!(f, "Metrics"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Severity {
Info,
Refactor,
Convention,
Warning,
Error,
Fatal,
}
impl Severity {
pub fn code(&self) -> char {
match self {
Severity::Info => 'I',
Severity::Refactor => 'R',
Severity::Convention => 'C',
Severity::Warning => 'W',
Severity::Error => 'E',
Severity::Fatal => 'F',
}
}
}
impl fmt::Display for Severity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.code())
}
}
pub trait Cop: Send + Sync {
fn name(&self) -> &str;
fn category(&self) -> Category;
fn severity(&self) -> Severity;
fn description(&self) -> &str;
fn check(&self, source: &SourceFile) -> Vec<Offense>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_severity_ordering() {
assert!(Severity::Info < Severity::Convention);
assert!(Severity::Convention < Severity::Warning);
assert!(Severity::Warning < Severity::Error);
assert!(Severity::Error < Severity::Fatal);
}
#[test]
fn test_severity_codes() {
assert_eq!(Severity::Convention.code(), 'C');
assert_eq!(Severity::Warning.code(), 'W');
assert_eq!(Severity::Error.code(), 'E');
}
#[test]
fn test_category_display() {
assert_eq!(Category::Layout.to_string(), "Layout");
assert_eq!(Category::Style.to_string(), "Style");
assert_eq!(Category::Lint.to_string(), "Lint");
assert_eq!(Category::Naming.to_string(), "Naming");
}
}