archunit/files/fluentapi/
match_pattern_file_condition.rsuse crate::checkable::execute_logged_check;
use crate::{
checkable::{CheckResult, Checkable},
common::{
ArchUnitError, CheckOptions, Filter, PatternError, ProjectLocator, UserError,
extract_graph_with_options, locate_project_from,
},
files::{MatchPatternFileConditionBuilder, gather_matching_file_violations},
};
use super::file_rule_support::{empty_selection_violation, selected_nodes};
#[derive(Debug, Clone)]
#[must_use = "an architecture rule has no effect until it is checked"]
pub struct MatchPatternFileCondition {
condition: MatchPatternFileConditionBuilder,
check_filter: Result<Filter, PatternError>,
}
impl MatchPatternFileCondition {
pub(super) const fn new(
condition: MatchPatternFileConditionBuilder,
check_filter: Result<Filter, PatternError>,
) -> Self {
Self {
condition,
check_filter,
}
}
pub const fn condition(&self) -> &MatchPatternFileConditionBuilder {
&self.condition
}
#[must_use]
pub fn check_filter(&self) -> Option<&Filter> {
self.check_filter.as_ref().ok()
}
#[must_use]
pub const fn project_locator(&self) -> &ProjectLocator {
self.condition.project_locator()
}
#[must_use]
pub fn filters(&self) -> &[Filter] {
self.condition.filters()
}
#[must_use]
pub const fn is_negated(&self) -> bool {
self.condition.is_negated()
}
#[must_use]
pub fn selector_error(&self) -> Option<&PatternError> {
self.condition
.selector_error()
.or_else(|| self.check_filter.as_ref().err())
}
}
impl Checkable for MatchPatternFileCondition {
fn check_with(&self, options: &CheckOptions) -> CheckResult {
execute_logged_check("files.pattern", options, |logger| {
if let Some(error) = self.condition.selector_error() {
return Err(ArchUnitError::from(UserError::with_source(
"the file scope contains an invalid selector",
error.clone(),
)));
}
let check_filter = self.check_filter.as_ref().map_err(|error| {
ArchUnitError::from(UserError::with_source(
"the file predicate contains an invalid pattern",
error.clone(),
))
})?;
logger.log_progress("extracting project graph")?;
let project = locate_project_from(self.project_locator())?;
let extraction = extract_graph_with_options(&project, options)?;
let selected = selected_nodes(extraction.graph(), self.filters());
logger.log_progress(format!("selected files={}", selected.len()))?;
if let Some(violation) =
empty_selection_violation(&selected, self.filters(), self.is_negated(), options)
{
return Ok(vec![violation]);
}
Ok(gather_matching_file_violations(
&selected,
check_filter,
self.is_negated(),
))
})
}
}