Skip to main content

garbage_code_hunter/common/
severity.rs

1//! Shared severity level used by all analysis modules.
2
3use serde::{Deserialize, Serialize};
4
5/// Severity level for any detected issue.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
7pub enum Severity {
8    Critical,
9    High,
10    Medium,
11    Low,
12    Info,
13}
14
15impl Severity {
16    /// Returns the emoji representation for terminal output.
17    pub fn emoji(&self) -> &'static str {
18        match self {
19            Severity::Critical => "\u{1f480}",
20            Severity::High => "\u{1f621}",
21            Severity::Medium => "\u{26a0}\u{fe0f}",
22            Severity::Low => "\u{1f4a7}",
23            Severity::Info => "\u{2139}\u{fe0f}",
24        }
25    }
26
27    /// Returns the numeric penalty weight for scoring.
28    pub fn penalty(&self) -> f64 {
29        match self {
30            Severity::Critical => 10.0,
31            Severity::High => 5.0,
32            Severity::Medium => 2.0,
33            Severity::Low => 0.5,
34            Severity::Info => 0.0,
35        }
36    }
37
38    /// Alias for penalty() — used by commit_roaster which calls it weight().
39    pub fn weight(&self) -> f64 {
40        self.penalty()
41    }
42
43    /// Returns a human-readable label.
44    pub fn label(&self) -> &'static str {
45        match self {
46            Severity::Critical => "Critical",
47            Severity::High => "High",
48            Severity::Medium => "Medium",
49            Severity::Low => "Low",
50            Severity::Info => "Info",
51        }
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn test_severity_ordering() {
61        // Derived PartialOrd orders by declaration order
62        assert!(Severity::Critical < Severity::High);
63        assert!(Severity::High < Severity::Medium);
64        assert!(Severity::Medium < Severity::Low);
65        assert!(Severity::Low < Severity::Info);
66    }
67
68    #[test]
69    fn test_emoji_non_empty() {
70        for sev in [
71            Severity::Critical,
72            Severity::High,
73            Severity::Medium,
74            Severity::Low,
75            Severity::Info,
76        ] {
77            assert!(!sev.emoji().is_empty());
78        }
79    }
80
81    #[test]
82    fn test_penalty_values() {
83        assert_eq!(Severity::Critical.penalty(), 10.0);
84        assert_eq!(Severity::High.penalty(), 5.0);
85        assert_eq!(Severity::Medium.penalty(), 2.0);
86        assert_eq!(Severity::Low.penalty(), 0.5);
87        assert_eq!(Severity::Info.penalty(), 0.0);
88    }
89
90    #[test]
91    fn test_weight_is_alias_for_penalty() {
92        for sev in [
93            Severity::Critical,
94            Severity::High,
95            Severity::Medium,
96            Severity::Low,
97            Severity::Info,
98        ] {
99            assert_eq!(sev.weight(), sev.penalty());
100        }
101    }
102
103    #[test]
104    fn test_label() {
105        assert_eq!(Severity::Critical.label(), "Critical");
106        assert_eq!(Severity::Info.label(), "Info");
107    }
108}