Skip to main content

rscheck_cli/rules/
mod.rs

1mod absolute_filesystem_paths;
2mod absolute_module_paths;
3mod banned_dependencies;
4mod duplicate_logic;
5mod duplicate_types_alias;
6mod file_complexity;
7mod layer_direction;
8mod public_api_errors;
9mod srp_heuristic;
10mod use_tree_path;
11
12use crate::analysis::Workspace;
13use crate::config::{Level, Policy, RuleSettings};
14use crate::emit::Emitter;
15use crate::report::RuleCatalogEntry;
16
17pub use absolute_filesystem_paths::AbsoluteFilesystemPathsRule;
18pub use absolute_module_paths::AbsoluteModulePathsRule;
19pub use banned_dependencies::BannedDependenciesRule;
20pub use duplicate_logic::DuplicateLogicRule;
21pub use duplicate_types_alias::DuplicateTypesAliasCandidateRule;
22pub use file_complexity::FileComplexityRule;
23pub use layer_direction::LayerDirectionRule;
24pub use public_api_errors::PublicApiErrorsRule;
25pub use srp_heuristic::SrpHeuristicRule;
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
28#[serde(rename_all = "snake_case")]
29pub enum RuleFamily {
30    Architecture,
31    Design,
32    Shape,
33    Portability,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
37#[serde(rename_all = "snake_case")]
38pub enum RuleBackend {
39    Syntax,
40    Semantic,
41    Adapter,
42}
43
44#[derive(Debug, Clone, Copy)]
45pub struct RuleInfo {
46    pub id: &'static str,
47    pub family: RuleFamily,
48    pub backend: RuleBackend,
49    pub summary: &'static str,
50    pub default_level: Level,
51    pub schema: &'static str,
52    pub config_example: &'static str,
53    pub fixable: bool,
54}
55
56pub struct RuleContext<'a> {
57    pub policy: &'a Policy,
58}
59
60pub trait Rule {
61    fn info(&self) -> RuleInfo;
62    fn run(&self, ws: &Workspace, ctx: &RuleContext<'_>, out: &mut dyn Emitter);
63}
64
65fn all_rules() -> Vec<Box<dyn Rule>> {
66    vec![
67        Box::new(AbsoluteModulePathsRule),
68        Box::new(AbsoluteFilesystemPathsRule),
69        Box::new(FileComplexityRule),
70        Box::new(DuplicateLogicRule),
71        Box::new(DuplicateTypesAliasCandidateRule),
72        Box::new(SrpHeuristicRule),
73        Box::new(BannedDependenciesRule),
74        Box::new(PublicApiErrorsRule),
75        Box::new(LayerDirectionRule),
76    ]
77}
78
79pub fn rule_catalog() -> Vec<RuleInfo> {
80    all_rules().into_iter().map(|rule| rule.info()).collect()
81}
82
83pub fn rule_catalog_entries() -> Vec<RuleCatalogEntry> {
84    rule_catalog()
85        .into_iter()
86        .map(|info| RuleCatalogEntry {
87            id: info.id.to_string(),
88            family: info.family,
89            backend: info.backend,
90            default_level: info.default_level,
91            summary: info.summary.to_string(),
92            fixable: info.fixable,
93        })
94        .collect()
95}
96
97pub fn enabled_rules(policy: &Policy) -> Vec<Box<dyn Rule>> {
98    all_rules()
99        .into_iter()
100        .filter(|rule| {
101            let info = rule.info();
102            policy.rule_enabled_anywhere(info.id, info.default_level)
103        })
104        .collect()
105}
106
107pub fn default_rule_settings() -> Vec<(String, RuleSettings)> {
108    rule_catalog()
109        .into_iter()
110        .map(|info| {
111            (
112                info.id.to_string(),
113                RuleSettings {
114                    level: Some(info.default_level),
115                    options: toml::Table::new(),
116                },
117            )
118        })
119        .collect()
120}