Skip to main content

alint_rules/
lib.rs

1//! Built-in rule implementations for alint.
2//!
3//! Rules are registered into an [`alint_core::RuleRegistry`] via
4//! [`register_builtin`]. Each kind has its own submodule.
5
6use alint_core::RuleRegistry;
7
8pub mod case;
9pub mod dir_absent;
10pub mod dir_contains;
11pub mod dir_exists;
12pub mod dir_only_contains;
13pub mod every_matching_has;
14pub mod executable_bit;
15pub mod executable_has_shebang;
16pub mod file_absent;
17pub mod file_content_forbidden;
18pub mod file_content_matches;
19pub mod file_ends_with;
20pub mod file_exists;
21pub mod file_hash;
22pub mod file_header;
23pub mod file_is_ascii;
24pub mod file_is_text;
25pub mod file_max_size;
26pub mod file_starts_with;
27pub mod filename_case;
28pub mod filename_regex;
29pub mod final_newline;
30pub mod fixers;
31pub mod for_each_dir;
32pub mod for_each_file;
33pub mod indent_style;
34pub mod io;
35pub mod line_endings;
36pub mod line_max_width;
37pub mod max_consecutive_blank_lines;
38pub mod max_directory_depth;
39pub mod max_files_per_directory;
40pub mod no_bidi_controls;
41pub mod no_bom;
42pub mod no_case_conflicts;
43pub mod no_empty_files;
44pub mod no_illegal_windows_names;
45pub mod no_merge_conflict_markers;
46pub mod no_submodules;
47pub mod no_symlinks;
48pub mod no_trailing_whitespace;
49pub mod no_zero_width_chars;
50pub mod pair;
51pub mod shebang_has_executable;
52pub mod unique_by;
53
54/// Register every built-in rule kind into the given registry.
55///
56/// Naming convention: rules that have a `dir_*` sibling keep
57/// their `file_*` prefix (`file_exists` vs `dir_exists`); rules
58/// with no such parallel also register a short alias without the
59/// prefix — `content_matches`, `content_forbidden`, `header`,
60/// `is_text`, `max_size`. Both forms resolve to the same
61/// builder; new rules land under short names only.
62pub fn register_builtin(registry: &mut RuleRegistry) {
63    registry.register("file_exists", file_exists::build);
64    registry.register("file_absent", file_absent::build);
65    registry.register("dir_exists", dir_exists::build);
66    registry.register("dir_absent", dir_absent::build);
67
68    registry.register("file_content_matches", file_content_matches::build);
69    registry.register("content_matches", file_content_matches::build);
70    registry.register("file_content_forbidden", file_content_forbidden::build);
71    registry.register("content_forbidden", file_content_forbidden::build);
72    registry.register("file_header", file_header::build);
73    registry.register("header", file_header::build);
74    registry.register("file_max_size", file_max_size::build);
75    registry.register("max_size", file_max_size::build);
76    registry.register("file_is_text", file_is_text::build);
77    registry.register("is_text", file_is_text::build);
78
79    registry.register("filename_case", filename_case::build);
80    registry.register("filename_regex", filename_regex::build);
81    registry.register("pair", pair::build);
82    registry.register("for_each_dir", for_each_dir::build);
83    registry.register("for_each_file", for_each_file::build);
84    registry.register("dir_only_contains", dir_only_contains::build);
85    registry.register("unique_by", unique_by::build);
86    registry.register("dir_contains", dir_contains::build);
87    registry.register("every_matching_has", every_matching_has::build);
88
89    // Text-hygiene family (short names — no `file_` prefix).
90    registry.register("no_trailing_whitespace", no_trailing_whitespace::build);
91    registry.register("final_newline", final_newline::build);
92    registry.register("line_endings", line_endings::build);
93    registry.register("line_max_width", line_max_width::build);
94
95    // Security / Unicode sanity.
96    registry.register(
97        "no_merge_conflict_markers",
98        no_merge_conflict_markers::build,
99    );
100    registry.register("no_bidi_controls", no_bidi_controls::build);
101    registry.register("no_zero_width_chars", no_zero_width_chars::build);
102
103    // Encoding + content fingerprint.
104    registry.register("file_is_ascii", file_is_ascii::build);
105    registry.register("no_bom", no_bom::build);
106    registry.register("file_hash", file_hash::build);
107
108    // Structure / layout.
109    registry.register("max_directory_depth", max_directory_depth::build);
110    registry.register("max_files_per_directory", max_files_per_directory::build);
111    registry.register("no_empty_files", no_empty_files::build);
112
113    // Cross-platform / portable metadata.
114    registry.register("no_case_conflicts", no_case_conflicts::build);
115    registry.register("no_illegal_windows_names", no_illegal_windows_names::build);
116
117    // Unix metadata + git.
118    registry.register("no_symlinks", no_symlinks::build);
119    registry.register("executable_bit", executable_bit::build);
120    registry.register("executable_has_shebang", executable_has_shebang::build);
121    registry.register("shebang_has_executable", shebang_has_executable::build);
122    registry.register("no_submodules", no_submodules::build);
123
124    // Hygiene + byte fingerprint.
125    registry.register("indent_style", indent_style::build);
126    registry.register(
127        "max_consecutive_blank_lines",
128        max_consecutive_blank_lines::build,
129    );
130    registry.register("file_starts_with", file_starts_with::build);
131    registry.register("file_ends_with", file_ends_with::build);
132}
133
134/// Convenience constructor that returns a fresh registry pre-populated with
135/// every built-in rule.
136pub fn builtin_registry() -> RuleRegistry {
137    let mut r = RuleRegistry::new();
138    register_builtin(&mut r);
139    r
140}
141
142#[cfg(test)]
143mod registry_tests {
144    use super::*;
145
146    #[test]
147    fn every_documented_kind_is_registered() {
148        let r = builtin_registry();
149        let known: Vec<&str> = r.known_kinds().collect();
150        for kind in [
151            // Prefixed kinds (parallel with dir_*).
152            "file_exists",
153            "file_absent",
154            "dir_exists",
155            "dir_absent",
156            // Prefixed + short alias pairs.
157            "file_content_matches",
158            "content_matches",
159            "file_content_forbidden",
160            "content_forbidden",
161            "file_header",
162            "header",
163            "file_max_size",
164            "max_size",
165            "file_is_text",
166            "is_text",
167            // Short-only.
168            "filename_case",
169            "filename_regex",
170            "pair",
171            "for_each_dir",
172            "for_each_file",
173            "dir_only_contains",
174            "unique_by",
175            "dir_contains",
176            "every_matching_has",
177            // Text-hygiene family.
178            "no_trailing_whitespace",
179            "final_newline",
180            "line_endings",
181            "line_max_width",
182            // Security / Unicode sanity.
183            "no_merge_conflict_markers",
184            "no_bidi_controls",
185            "no_zero_width_chars",
186            // Encoding + fingerprint.
187            "file_is_ascii",
188            "no_bom",
189            "file_hash",
190            // Structure / layout.
191            "max_directory_depth",
192            "max_files_per_directory",
193            "no_empty_files",
194            // Portable metadata.
195            "no_case_conflicts",
196            "no_illegal_windows_names",
197            // Unix metadata + git.
198            "no_symlinks",
199            "executable_bit",
200            "executable_has_shebang",
201            "shebang_has_executable",
202            "no_submodules",
203            // Hygiene + byte fingerprint.
204            "indent_style",
205            "max_consecutive_blank_lines",
206            "file_starts_with",
207            "file_ends_with",
208        ] {
209            assert!(
210                known.contains(&kind),
211                "{kind} missing from builtin registry"
212            );
213        }
214    }
215}