use std::collections::HashMap;
use std::path::Path;
use crate::rule::Rule;
use crate::spec::Spec;
use crate::support::fs::relative_to;
use super::super::finding::{Finding, Location};
use super::conformance_error;
#[cfg(test)]
#[path = "duplicate_ids_test.rs"]
mod duplicate_ids_test;
pub(super) const DUPLICATE_ID_CHECK: &str = "no-duplicate-ids";
pub(super) fn validate_no_duplicate_ids(
spex_dir: &Path,
specs: &[Spec],
rules: &[Rule],
) -> Vec<Finding> {
let mut findings = Vec::new();
let mut seen: HashMap<&str, &Path> = HashMap::new();
let definitions = specs
.iter()
.map(|spec| (spec.id.as_str(), spec.path.as_path()))
.chain(
rules
.iter()
.map(|rule| (rule.id.as_str(), rule.path.as_path())),
);
for (id, path) in definitions {
if let Some(first_seen) = seen.get(id) {
findings.push(conformance_error(
DUPLICATE_ID_CHECK,
Some(Location::in_file(path)),
format!(
"duplicate id `{id}`: already defined in `{}`",
relative_to(first_seen, spex_dir).display()
),
));
} else {
seen.insert(id, path);
}
}
findings
}