use std::fmt::Debug;
use lib_package::LibPackage;
use package_hierarchy::PackageHierarchy;
use crate::{
manifest::PackageManifest,
package::PackageType,
validation::{
data::*,
violation::{self, *},
},
};
mod ident_casing;
mod lib_package;
mod package_hierarchy;
mod package_name;
pub use self::{ident_casing::*, package_name::*};
pub type RuleSet = Vec<Box<dyn Rule>>;
pub trait Rule: Debug {
fn rule_name(&self) -> &'static str {
std::any::type_name::<Self>().split("::").last().unwrap()
}
fn rule_info(&self) -> &'static str;
fn rule_level(&self) -> Level {
Level::Error
}
fn to_violation(&self, message: violation::Message) -> Violation {
Violation {
rule: self.rule_name().into(),
level: self.rule_level(),
message,
location: Default::default(),
info: self.rule_info().into(),
}
}
fn check_packages(&mut self, _packages: &Packages) -> Violations {
Default::default()
}
fn check_package(&mut self, _package: &Package) -> Violations {
Default::default()
}
fn check_entity(&mut self, _name: &str, _entity: &Entity) -> Violations {
Default::default()
}
}
impl Rule for RuleSet {
fn rule_name(&self) -> &'static str {
"RuleSet"
}
fn rule_info(&self) -> &'static str {
"RuleSet"
}
fn check_packages(&mut self, packages: &Packages) -> Violations {
self.iter_mut()
.flat_map(|rule| rule.check_packages(packages))
.collect()
}
fn check_package(&mut self, package: &Package) -> Violations {
self.iter_mut()
.flat_map(|rule| rule.check_package(package))
.collect()
}
fn check_entity(&mut self, name: &str, entity: &Entity) -> Violations {
self.iter_mut()
.flat_map(|rule| rule.check_entity(name, entity))
.collect()
}
}
pub fn all(manifest: &PackageManifest) -> RuleSet {
let mut ret: Vec<Box<dyn Rule>> = vec![
Box::new(PackageName::new(manifest.name.clone())),
Box::new(IdentCasing),
Box::new(PackageHierarchy),
];
if manifest.kind == PackageType::Lib {
ret.push(Box::new(LibPackage));
}
ret
}
#[cfg(test)]
mod tests {
use super::*;
use crate::package::PackageType;
use semver::Version;
#[test]
fn all_should_contain_these_rules_for_api_packages() -> Result<(), Box<dyn std::error::Error>> {
let manifest = PackageManifest {
kind: PackageType::Api,
name: crate::package::PackageName::new("package")?,
version: Version::new(0, 1, 0),
description: Default::default(),
};
let all = all(&manifest)
.iter()
.map(|r| r.rule_name())
.collect::<Vec<_>>();
assert_eq!(
all,
&[
PackageName::new(manifest.name.clone()).rule_name(),
IdentCasing.rule_name(),
PackageHierarchy.rule_name(),
],
);
Ok(())
}
#[test]
fn all_should_contain_these_rules_for_lib_packages() -> Result<(), Box<dyn std::error::Error>> {
let manifest = PackageManifest {
kind: PackageType::Lib,
name: crate::package::PackageName::new("package")?,
version: Version::new(0, 1, 0),
description: Default::default(),
};
let all = all(&manifest)
.iter()
.map(|r| r.rule_name())
.collect::<Vec<_>>();
assert_eq!(
all,
&[
PackageName::new(manifest.name.clone()).rule_name(),
IdentCasing.rule_name(),
PackageHierarchy.rule_name(),
LibPackage.rule_name(),
],
);
Ok(())
}
}