stern4rust/rules/layout/
module_registry_rule.rs1use crate::finding::model::registry_policy::RegistryPolicy;
6use crate::finding::parsing::registry_parser::RegistryParser;
7use crate::reporting::offence::Offence;
8use crate::rule::Rule;
9use crate::source_file::SourceFile;
10
11pub struct ModuleRegistryRule;
29
30impl ModuleRegistryRule {
31 pub const TESTS_ROOT: &'static str = "tests/";
32
33 pub fn new() -> Self {
34 Self
35 }
36
37 fn applies_to(file: &SourceFile) -> bool {
38 !file.relative_path().starts_with(Self::TESTS_ROOT) && Self::is_registry(file)
39 }
40
41 fn is_registry(file: &SourceFile) -> bool {
42 matches!(
43 file.relative_path().rsplit('/').next(),
44 Some("lib.rs") | Some("mod.rs")
45 )
46 }
47}
48
49impl Default for ModuleRegistryRule {
50 fn default() -> Self {
51 Self::new()
52 }
53}
54
55impl Rule for ModuleRegistryRule {
56 fn name(&self) -> &'static str {
57 "module-registry"
58 }
59
60 fn check(&self, file: &SourceFile) -> Vec<Offence> {
61 if !Self::applies_to(file) {
62 return Vec::new();
63 }
64 RegistryParser::strays(file, RegistryPolicy::source())
65 .unwrap_or_default()
66 .into_iter()
67 .map(|stray| {
68 Offence::new(
69 file.relative_path(),
70 stray.line,
71 self.name(),
72 format!(
73 "{} does not belong in a module registry, which holds the \
74 header, inner attributes, `extern crate alloc;` and pub mod \
75 declarations only",
76 stray.label
77 ),
78 format!("move {} into a module of its own", stray.label),
79 )
80 .with_subject(&stray.label)
81 })
82 .collect()
83 }
84
85 fn check_workspace(&self, _files: &[SourceFile]) -> Vec<Offence> {
86 Vec::new()
87 }
88
89 fn requirement(&self) -> Option<&'static str> {
90 None
91 }
92
93 fn is_configured(&self) -> bool {
94 true
95 }
96}