use crate::reporting::offence::Offence;
use crate::rule::Rule;
use crate::rules::directory_file_count_rule::DirectoryFileCountRule;
use crate::rules::directory_subfolder_count_rule::DirectorySubfolderCountRule;
use crate::rules::header_rule::HeaderRule;
use crate::rules::imported_paths_rule::ImportedPathsRule;
use crate::rules::module_registry_rule::ModuleRegistryRule;
use crate::rules::readable_source_rule::ReadableSourceRule;
use crate::rules::registry_completeness_rule::RegistryCompletenessRule;
use crate::rules::single_implemented_type_rule::SingleImplementedTypeRule;
use crate::rules::test_file_structure_rule::TestFileStructureRule;
use crate::rules::test_free_source_rule::TestFreeSourceRule;
use crate::rules::tests_layout_rule::TestsLayoutRule;
use crate::settings::config::Config;
use crate::settings::rule_selection::RuleSelection;
use crate::source_file::SourceFile;
pub struct RuleRegistry {
rules: Vec<Box<dyn Rule>>,
}
impl RuleRegistry {
fn all(config: &Config) -> Vec<Box<dyn Rule>> {
vec![
Box::new(ReadableSourceRule::new()),
Box::new(DirectoryFileCountRule::new(
config
.max_files_per_directory
.unwrap_or(DirectoryFileCountRule::DEFAULT_LIMIT),
)),
Box::new(DirectorySubfolderCountRule::new(
config
.max_subfolders_per_directory
.unwrap_or(DirectorySubfolderCountRule::DEFAULT_LIMIT),
)),
Box::new(ImportedPathsRule::new()),
Box::new(ModuleRegistryRule::new()),
Box::new(RegistryCompletenessRule::new()),
Box::new(SingleImplementedTypeRule::new()),
Box::new(TestFileStructureRule::new()),
Box::new(TestFreeSourceRule::new()),
Box::new(TestsLayoutRule::new()),
Box::new(HeaderRule::new(config.expected_header.clone())),
]
}
pub fn from_config(config: &Config) -> Self {
let rules = Self::all(config)
.into_iter()
.filter(|rule| rule.is_configured() && config.selection.includes(rule.name()))
.collect();
Self { rules }
}
pub fn new(rules: Vec<Box<dyn Rule>>) -> Self {
Self { rules }
}
pub fn known_names() -> Vec<&'static str> {
Self::all(&Config::default())
.iter()
.map(|rule| rule.name())
.collect()
}
pub fn skipped_names(selection: &RuleSelection) -> Vec<&'static str> {
Self::known_names()
.into_iter()
.filter(|name| !selection.includes(name))
.collect()
}
pub fn unconfigured_names(&self, config: &Config) -> Vec<&'static str> {
let applied = self.names();
Self::known_names()
.into_iter()
.filter(|name| config.selection.includes(name) && !applied.contains(name))
.collect()
}
pub fn is_empty(&self) -> bool {
self.rules.is_empty()
}
pub fn names(&self) -> Vec<&'static str> {
self.rules.iter().map(|rule| rule.name()).collect()
}
pub fn check(&self, file: &SourceFile) -> Vec<Offence> {
self.rules
.iter()
.flat_map(|rule| rule.check(file))
.collect()
}
pub fn check_workspace(&self, files: &[SourceFile]) -> Vec<Offence> {
self.rules
.iter()
.flat_map(|rule| rule.check_workspace(files))
.collect()
}
}