fallow_core/plugins/
used_export_names.rs1use std::collections::BTreeSet;
4
5use super::{AggregatedPluginResult, CompiledPathRule};
6
7#[derive(Debug, Clone)]
13pub struct UsedExportNames {
14 rules: Vec<(CompiledPathRule, Vec<String>)>,
15}
16
17impl UsedExportNames {
18 #[must_use]
22 pub fn names_for(&self, rel_path: &str) -> BTreeSet<&str> {
23 self.rules
24 .iter()
25 .filter(|(path, _)| path.matches(rel_path))
26 .flat_map(|(_, exports)| exports.iter().map(String::as_str))
27 .collect()
28 }
29}
30
31impl AggregatedPluginResult {
32 #[must_use]
35 pub fn used_export_names(&self) -> UsedExportNames {
36 UsedExportNames {
37 rules: self
38 .used_exports
39 .iter()
40 .filter_map(|rule| {
41 let path = CompiledPathRule::for_used_export_rule(
42 &rule.rule.path,
43 "used_exports pattern",
44 )?;
45 Some((path, rule.rule.exports.clone()))
46 })
47 .collect(),
48 }
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::super::{PluginUsedExportRule, UsedExportRule};
55 use super::*;
56
57 fn result(rules: Vec<PluginUsedExportRule>) -> AggregatedPluginResult {
58 AggregatedPluginResult {
59 used_exports: rules,
60 ..AggregatedPluginResult::default()
61 }
62 }
63
64 #[test]
65 fn names_for_a_path_join_each_matching_rule() {
66 let names = result(vec![
67 PluginUsedExportRule::new(
68 "nextjs",
69 UsedExportRule::new("app/**/page.{ts,tsx}", ["default", "revalidate"]),
70 ),
71 PluginUsedExportRule::new("nextjs", UsedExportRule::new("app/**/*.tsx", ["dynamic"])),
72 PluginUsedExportRule::new(
73 "tanstack-router",
74 UsedExportRule::new("src/routes/**/*.tsx", ["Route"]),
75 ),
76 ])
77 .used_export_names();
78
79 assert_eq!(
80 names.names_for("app/blog/page.tsx"),
81 BTreeSet::from(["default", "dynamic", "revalidate"])
82 );
83 assert_eq!(
84 names.names_for("src/routes/index.tsx"),
85 BTreeSet::from(["Route"])
86 );
87 assert!(names.names_for("src/lib/math.ts").is_empty());
88 }
89
90 #[test]
91 fn an_excluded_glob_and_an_invalid_glob_match_no_file() {
92 let names = result(vec![
93 PluginUsedExportRule::new(
94 "tanstack-router",
95 UsedExportRule::new("src/routes/**/*.tsx", ["Route"])
96 .with_excluded_globs(["src/routes/**/-*.tsx"]),
97 ),
98 PluginUsedExportRule::new("broken", UsedExportRule::new("src/[", ["config"])),
99 ])
100 .used_export_names();
101
102 assert_eq!(
103 names.names_for("src/routes/posts.tsx"),
104 BTreeSet::from(["Route"])
105 );
106 assert!(names.names_for("src/routes/-helper.tsx").is_empty());
107 assert!(names.names_for("src/[").is_empty());
108 }
109}