use std::collections::HashMap;
use std::path::Path;
use xuanji::{BoundaryKind, Polarity, Severity, Violation, ViolationId};
use crate::file_scope::{per_finding_file, seam_file};
use crate::finding::SemanticFact;
pub(crate) struct SingleModuleViolationContext<'a> {
pub(crate) src_dir: &'a Path,
pub(crate) root_file: &'a Path,
pub(crate) module: &'a str,
pub(crate) crate_package: &'a str,
pub(crate) rule: &'a str,
pub(crate) reason: &'a str,
pub(crate) severity: Severity,
pub(crate) anchor: Option<&'a str>,
}
pub(crate) fn push_single_module_violations(
violations: &mut Vec<Violation>,
context: SingleModuleViolationContext<'_>,
findings: Vec<SemanticFact>,
) -> Result<(), String> {
let module_file = seam_file(
&findings,
context.src_dir,
context.root_file,
context.module,
context.crate_package,
)?;
let anchor = context.anchor.map(str::to_string);
for finding in findings {
violations.push(
Violation::new(
BoundaryKind::Semantic,
ViolationId::new(context.module, context.rule, finding.into_finding()),
context.reason.to_string(),
context.severity,
)
.with_file(module_file.clone())
.with_anchor(anchor.clone())
.with_polarity(Polarity::DenyBreach),
);
}
Ok(())
}
pub(crate) struct MultiModuleViolationContext<'a> {
pub(crate) src_dir: &'a Path,
pub(crate) root_file: &'a Path,
pub(crate) target: &'a str,
pub(crate) crate_package: &'a str,
pub(crate) rule: &'a str,
pub(crate) reason: &'a str,
pub(crate) severity: Severity,
pub(crate) anchor: Option<&'a str>,
pub(crate) polarity: Polarity,
}
pub(crate) fn push_multi_module_violations(
violations: &mut Vec<Violation>,
context: MultiModuleViolationContext<'_>,
findings: Vec<(SemanticFact, String)>,
) {
let anchor = context.anchor.map(str::to_string);
let mut cache: HashMap<String, Option<String>> = HashMap::new();
for (finding, module) in findings {
let file = per_finding_file(
&module,
context.src_dir,
context.root_file,
context.crate_package,
&mut cache,
);
violations.push(
Violation::new(
BoundaryKind::Semantic,
ViolationId::new(context.target, context.rule, finding.into_finding()),
context.reason.to_string(),
context.severity,
)
.with_file(file)
.with_anchor(anchor.clone())
.with_polarity(context.polarity),
);
}
}