use xuanji::{RuleKey, Severity};
use crate::rules::{VISIBILITY_MODULE_RULE, VISIBILITY_RULE, VISIBILITY_SUPER_RULE};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VisibilityCeiling {
Crate,
Super,
Module,
}
impl VisibilityCeiling {
fn key_label(self) -> &'static str {
match self {
VisibilityCeiling::Crate => "crate",
VisibilityCeiling::Super => "super",
VisibilityCeiling::Module => "module",
}
}
pub(crate) fn rank(self) -> u8 {
match self {
VisibilityCeiling::Crate => 2,
VisibilityCeiling::Super => 1,
VisibilityCeiling::Module => 0,
}
}
pub fn rule(self) -> &'static str {
match self {
VisibilityCeiling::Crate => VISIBILITY_RULE,
VisibilityCeiling::Super => VISIBILITY_SUPER_RULE,
VisibilityCeiling::Module => VISIBILITY_MODULE_RULE,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VisibilityBoundary {
pub(crate) crate_package: String,
pub(crate) module: String,
pub(crate) reason: String,
pub(crate) anchor: Option<String>,
pub(crate) severity: Severity,
pub(crate) ceiling: VisibilityCeiling,
}
impl VisibilityBoundary {
pub fn rule_key(&self) -> RuleKey {
RuleKey::of(
"tianheng.rule/hunyi/visibility-ceiling",
[("ceiling", self.ceiling.key_label())],
)
}
pub fn in_crate(package: &str) -> VisibilityCrateDraft {
VisibilityCrateDraft {
crate_package: package.to_string(),
}
}
pub fn module(&self) -> &str {
&self.module
}
pub fn reason(&self) -> &str {
&self.reason
}
pub fn ceiling(&self) -> VisibilityCeiling {
self.ceiling
}
}
crate::dsl::boundary_common!(VisibilityBoundary, VisibilityBoundaryDraft);
#[doc(hidden)]
pub struct VisibilityCrateDraft {
crate_package: String,
}
impl VisibilityCrateDraft {
pub fn module(self, module: &str) -> VisibilityModuleDraft {
VisibilityModuleDraft {
crate_package: self.crate_package,
module: module.to_string(),
}
}
}
#[doc(hidden)]
pub struct VisibilityModuleDraft {
crate_package: String,
module: String,
}
impl VisibilityModuleDraft {
pub fn must_not_declare_pub(self) -> VisibilityBoundaryDraft {
self.max_visibility(VisibilityCeiling::Crate)
}
pub fn max_visibility(self, ceiling: VisibilityCeiling) -> VisibilityBoundaryDraft {
VisibilityBoundaryDraft {
crate_package: self.crate_package,
module: self.module,
severity: Severity::Enforce,
ceiling,
}
}
}
#[doc(hidden)]
pub struct VisibilityBoundaryDraft {
crate_package: String,
module: String,
severity: Severity,
ceiling: VisibilityCeiling,
}
impl VisibilityBoundaryDraft {
pub fn because(self, reason: &str) -> VisibilityBoundary {
VisibilityBoundary {
crate_package: self.crate_package,
module: self.module,
reason: reason.to_string(),
anchor: None,
severity: self.severity,
ceiling: self.ceiling,
}
}
}