use super::action::RefactoringAction;
use super::issue_type::IssueType;
use super::severity::Severity;
#[derive(Debug, Clone)]
pub struct CouplingIssue {
pub issue_type: IssueType,
pub severity: Severity,
pub source: String,
pub target: String,
pub description: String,
pub refactoring: RefactoringAction,
pub balance_score: f64,
}
impl CouplingIssue {
pub fn stable_key(&self) -> IssueKey {
IssueKey {
issue_type: self.issue_type,
source: match self.issue_type {
IssueType::HighAfferentCoupling if is_count_target(&self.source, "dependents") => {
"<dependent-count>".to_string()
}
_ => self.source.clone(),
},
target: match self.issue_type {
IssueType::HighEfferentCoupling
if is_count_target(&self.target, "dependencies") =>
{
"<dependency-count>".to_string()
}
_ => self.target.clone(),
},
}
}
pub fn meets(&self, floor: Severity) -> bool {
self.severity >= floor
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct IssueKey {
pub issue_type: IssueType,
pub source: String,
pub target: String,
}
impl From<&CouplingIssue> for IssueKey {
fn from(issue: &CouplingIssue) -> Self {
issue.stable_key()
}
}
fn is_count_target(value: &str, unit: &str) -> bool {
let Some((count, suffix)) = value.split_once(' ') else {
return false;
};
count.chars().all(|c| c.is_ascii_digit()) && suffix == unit
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_count_target_requires_digits_and_exact_unit() {
assert!(is_count_target("3 dependencies", "dependencies"));
assert!(is_count_target("12 dependents", "dependents"));
assert!(!is_count_target("3 widgets", "dependencies"));
assert!(!is_count_target("many dependencies", "dependencies"));
assert!(!is_count_target("dependencies", "dependencies"));
}
#[test]
fn meets_compares_severity_floor() {
let issue = CouplingIssue {
issue_type: IssueType::GodModule,
severity: Severity::Medium,
source: String::new(),
target: String::new(),
description: String::new(),
refactoring: RefactoringAction::General {
action: String::new(),
},
balance_score: 0.5,
};
assert!(issue.meets(Severity::Low));
assert!(issue.meets(Severity::Medium));
assert!(!issue.meets(Severity::High));
}
}