layer_conform_core/
matcher.rs1use std::path::Path;
4
5use crate::rule::Rule;
6
7pub fn matching_rules<'r>(path: &Path, rules: &'r [Rule]) -> Vec<&'r Rule> {
12 rules.iter().filter(|r| r.matches(path)).collect()
13}
14
15#[cfg(test)]
16mod tests {
17 use super::*;
18 use globset::{Glob, GlobSet, GlobSetBuilder};
19
20 fn glob_set(patterns: &[&str]) -> GlobSet {
21 let mut b = GlobSetBuilder::new();
22 for p in patterns {
23 b.add(Glob::new(p).expect("valid glob"));
24 }
25 b.build().expect("build glob set")
26 }
27
28 fn rule(id: &str, apply: &[&str], ignore: &[&str], disabled: bool) -> Rule {
29 Rule {
30 id: id.into(),
31 goldens: vec![],
32 apply_to: glob_set(apply),
33 ignore: glob_set(ignore),
34 threshold: None,
35 disabled,
36 }
37 }
38
39 #[test]
40 fn returns_rule_when_apply_to_matches() {
41 let rules = vec![rule("repos", &["src/repos/**/*.ts"], &[], false)];
42 let m = matching_rules(Path::new("src/repos/user.ts"), &rules);
43 assert_eq!(m.len(), 1);
44 assert_eq!(m[0].id, "repos");
45 }
46
47 #[test]
48 fn empty_when_no_apply_to_matches() {
49 let rules = vec![rule("repos", &["src/repos/**/*.ts"], &[], false)];
50 let m = matching_rules(Path::new("src/components/Button.tsx"), &rules);
51 assert!(m.is_empty());
52 }
53
54 #[test]
55 fn ignore_overrides_apply_to() {
56 let rules = vec![rule(
57 "repos",
58 &["src/repos/**/*.ts"],
59 &["src/repos/legacy/**"],
60 false,
61 )];
62 let m = matching_rules(Path::new("src/repos/legacy/old.ts"), &rules);
63 assert!(m.is_empty(), "ignore should suppress");
64 let m = matching_rules(Path::new("src/repos/user.ts"), &rules);
65 assert_eq!(m.len(), 1);
66 }
67
68 #[test]
69 fn multiple_rules_can_match_same_path() {
70 let rules = vec![
71 rule("ts", &["**/*.ts"], &[], false),
72 rule("repos", &["src/repos/**/*.ts"], &[], false),
73 ];
74 let m = matching_rules(Path::new("src/repos/user.ts"), &rules);
75 assert_eq!(m.len(), 2);
76 }
77
78 #[test]
79 fn disabled_rule_never_matches() {
80 let rules = vec![rule("repos", &["**/*.ts"], &[], true)];
81 let m = matching_rules(Path::new("src/foo.ts"), &rules);
82 assert!(m.is_empty());
83 }
84
85 #[test]
86 fn multiple_apply_to_patterns_are_or() {
87 let rules = vec![rule(
88 "many",
89 &["src/a/**/*.ts", "src/b/**/*.ts"],
90 &[],
91 false,
92 )];
93 assert_eq!(matching_rules(Path::new("src/a/x.ts"), &rules).len(), 1);
94 assert_eq!(matching_rules(Path::new("src/b/y.ts"), &rules).len(), 1);
95 assert!(matching_rules(Path::new("src/c/z.ts"), &rules).is_empty());
96 }
97}