use crate::reporting::offence::Offence;
use crate::reporting::rule_explanation::RuleExplanation;
use crate::rule::Rule;
use crate::rules::layout::directory_file_count_rule::DirectoryFileCountRule;
use crate::rules::layout::directory_subfolder_count_rule::DirectorySubfolderCountRule;
use crate::rules::layout::module_registry_rule::ModuleRegistryRule;
use crate::rules::layout::paired_test_file_rule::PairedTestFileRule;
use crate::rules::layout::registry_completeness_rule::RegistryCompletenessRule;
use crate::rules::layout::test_file_name_postfix_rule::TestFileNamePostfixRule;
use crate::rules::layout::tests_layout_rule::TestsLayoutRule;
use crate::rules::manifest::spdx_matches_manifest_rule::SpdxMatchesManifestRule;
use crate::rules::manifest::workspace_dependencies_rule::WorkspaceDependenciesRule;
use crate::rules::source::declared_by_name_rule::DeclaredByNameRule;
use crate::rules::source::header_rule::HeaderRule;
use crate::rules::source::imported_paths_rule::ImportedPathsRule;
use crate::rules::source::ordered_imports_rule::OrderedImportsRule;
use crate::rules::source::pure_traits_rule::PureTraitsRule;
use crate::rules::source::readable_source_rule::ReadableSourceRule;
use crate::rules::source::single_implemented_type_rule::SingleImplementedTypeRule;
use crate::rules::source::test_free_source_rule::TestFreeSourceRule;
use crate::rules::testing::arrange_act_assert_rule::ArrangeActAssertRule;
use crate::rules::testing::test_file_structure_rule::TestFileStructureRule;
use crate::rules::testing::test_naming_rule::TestNamingRule;
use crate::rules::testing::tested_public_api_rule::TestedPublicApiRule;
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(ArrangeActAssertRule::new()),
Box::new(DeclaredByNameRule::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(OrderedImportsRule::new()),
Box::new(PairedTestFileRule::new()),
Box::new(PureTraitsRule::new()),
Box::new(RegistryCompletenessRule::new()),
Box::new(SingleImplementedTypeRule::new()),
Box::new(SpdxMatchesManifestRule::new(
config.manifest_license.clone(),
)),
Box::new(TestFileNamePostfixRule::new()),
Box::new(TestFileStructureRule::new()),
Box::new(TestFreeSourceRule::new()),
Box::new(TestNamingRule::new()),
Box::new(TestedPublicApiRule::new()),
Box::new(TestsLayoutRule::new()),
Box::new(WorkspaceDependenciesRule::new(
config.workspace_dependencies.clone(),
)),
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> {
self.unconfigured(config)
.into_iter()
.map(|(name, _)| name)
.collect()
}
pub fn unconfigured(&self, config: &Config) -> Vec<(&'static str, &'static str)> {
let applied = self.names();
Self::all(config)
.iter()
.filter(|rule| {
config.selection.includes(rule.name()) && !applied.contains(&rule.name())
})
.map(|rule| (rule.name(), rule.requirement().unwrap_or("not configured")))
.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 explanations(&self) -> Vec<RuleExplanation> {
self.rules.iter().map(|rule| rule.explanation()).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()
}
}