dei_core/
thresholds.rs

1//! Detection thresholds with strong typing and validation
2
3use serde::{Deserialize, Serialize};
4
5/// Newtype for lines of code to prevent mixing with other integers
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
7pub struct Lines(pub usize);
8
9/// Newtype for cyclomatic complexity
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
11pub struct Complexity(pub usize);
12
13/// Newtype for method count
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
15pub struct MethodCount(pub usize);
16
17/// Newtype for parameter count
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
19pub struct ParamCount(pub usize);
20
21/// Configurable detection thresholds with strong typing
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct Thresholds {
24    // Class-level
25    pub max_class_lines: Lines,
26    pub max_methods: MethodCount,
27    pub max_class_complexity: Complexity,
28    
29    // Method-level
30    pub max_method_lines: Lines,
31    pub max_method_complexity: Complexity,
32    pub max_parameters: ParamCount,
33    
34    // File-level
35    pub max_classes_per_file: usize,
36    pub max_file_lines: Lines,
37    
38    // Clustering
39    pub min_cluster_size: usize,
40    pub cluster_threshold: f64,
41}
42
43impl Default for Thresholds {
44    fn default() -> Self {
45        Self {
46            max_class_lines: Lines(300),
47            max_methods: MethodCount(20),
48            max_class_complexity: Complexity(50),
49            max_method_lines: Lines(50),
50            max_method_complexity: Complexity(10),
51            max_parameters: ParamCount(5),
52            max_classes_per_file: 3,
53            max_file_lines: Lines(500),
54            min_cluster_size: 3,
55            cluster_threshold: 0.7,
56        }
57    }
58}
59
60impl Thresholds {
61    /// Validate thresholds are sensible
62    pub fn validate(&self) -> Result<(), String> {
63        if self.max_class_lines.0 < self.max_method_lines.0 {
64            return Err("max_class_lines must be >= max_method_lines".into());
65        }
66        if self.cluster_threshold < 0.0 || self.cluster_threshold > 1.0 {
67            return Err("cluster_threshold must be between 0.0 and 1.0".into());
68        }
69        if self.min_cluster_size < 2 {
70            return Err("min_cluster_size must be >= 2".into());
71        }
72        Ok(())
73    }
74}
75