use std::collections::HashMap;
use crate::domain::model::check::{CheckViolationKind, Severity};
use crate::domain::model::record_ref::IssueRef;
use crate::domain::usecases::check::{CheckViolation, IssueCheckCtx, IssueFinding, IssueRule};
pub struct DuplicateIdRule;
pub const RULE_ID: &str = "issue/duplicate-id";
impl IssueRule for DuplicateIdRule {
fn id(&self) -> &'static str {
RULE_ID
}
fn find(&self, ctx: &IssueCheckCtx<'_>) -> anyhow::Result<Vec<IssueFinding>> {
let mut by_id: HashMap<IssueRef, Vec<std::path::PathBuf>> = HashMap::new();
for (path, issue) in ctx.issues {
by_id
.entry(issue.id.clone())
.or_default()
.push(path.clone());
}
let mut out = Vec::new();
for (id, paths) in by_id {
if paths.len() < 2 {
continue;
}
for path in &paths {
let also_at: Vec<_> = paths.iter().filter(|p| *p != path).cloned().collect();
let kind = CheckViolationKind::DuplicateId {
id: id.as_entity_ref().clone(),
also_at,
};
out.push(CheckViolation {
rule_id: RULE_ID,
path: path.clone(),
severity: Severity::Error,
kind,
});
}
}
Ok(out.into_iter().map(IssueFinding::report).collect())
}
}