Skip to content

Commit 7d29504

Browse files
committed
generate: cleanup and test filtering
1 parent f5ed6ad commit 7d29504

File tree

1 file changed

+114
-50
lines changed

1 file changed

+114
-50
lines changed

xtask/src/generate.rs

Lines changed: 114 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -67,24 +67,69 @@ impl TemplateDiscovery {
6767
Ok(discovery)
6868
}
6969

70-
fn split_filter<'a>(&self, filters: impl Iterator<Item = &'a str>) -> Filters {
70+
fn split_filter<'a>(&self, filters: impl Iterator<Item = &'a str>) -> Filters<'a> {
7171
let mut out = Filters::default();
7272
for filter in filters {
7373
if self.templates.iter().any(|t| t.name == filter) {
74-
out.template_filters.insert(filter.to_string());
74+
out.template_filters.insert(filter);
7575
} else {
76-
out.placeholder_filters.push(filter.to_string());
76+
out.placeholder_filters.push(filter);
7777
}
7878
}
79+
debug!("Filters: {out:?}");
7980
out
8081
}
82+
83+
fn filter_variants<'a>(
84+
&'a self,
85+
filters: impl Iterator<Item = &'a str>,
86+
) -> anyhow::Result<Vec<(&'a Template, Vec<Define<'a>>)>> {
87+
let filters = self.split_filter(filters);
88+
89+
let mut has_unknown_filter = true;
90+
let mut unknown_filter = None;
91+
let variants = self
92+
.templates
93+
.iter()
94+
.filter(|template| {
95+
filters.template_filters.is_empty()
96+
|| filters.template_filters.contains(template.name.as_str())
97+
})
98+
.flat_map(|template| {
99+
let variants_result =
100+
template.variants(filters.placeholder_filters.iter().copied());
101+
let variants = match variants_result {
102+
Ok(e) => {
103+
has_unknown_filter = false;
104+
e
105+
}
106+
Err(e) => {
107+
unknown_filter = Some(e);
108+
Vec::new()
109+
}
110+
};
111+
variants.into_iter().map(move |v| (template, v))
112+
})
113+
.collect::<Vec<_>>();
114+
if has_unknown_filter {
115+
if let Some(filter) = unknown_filter {
116+
bail!("Unknown filter `{filter}`")
117+
} else {
118+
// Only reachable if no templates exist, Or if all templates have been filtered out, but you must filter
119+
// for at least one template for template filtering to even activate, so should be unreachable.
120+
bail!("No templates exist?")
121+
}
122+
}
123+
debug!("Variants: {variants:?}");
124+
Ok(variants)
125+
}
81126
}
82127

83-
#[derive(Clone, Debug, Default)]
84-
struct Filters {
85-
template_filters: HashSet<String>,
128+
#[derive(Clone, Debug, Default, Eq, PartialEq)]
129+
struct Filters<'a> {
130+
template_filters: HashSet<&'a str>,
86131
/// value whether it was used
87-
placeholder_filters: Vec<String>,
132+
placeholder_filters: Vec<&'a str>,
88133
}
89134

90135
#[derive(Clone, Debug)]
@@ -296,52 +341,13 @@ impl Generate {
296341
let out_base_dir = self.out_base_dir()?;
297342

298343
let discovery = TemplateDiscovery::discover()?;
299-
let filters = discovery.split_filter(self.filter.iter().map(|a| a.as_str()));
300-
301-
let mut has_unknown_filter = true;
302-
let mut unknown_filter = None;
303-
let results = discovery
304-
.templates
344+
let variants = discovery.filter_variants(self.filter.iter().map(|a| a.as_str()))?;
345+
let results = variants
305346
.iter()
306-
.filter(|template| {
307-
filters.template_filters.is_empty()
308-
|| filters.template_filters.contains(&template.name)
309-
})
310-
.map(|template| {
311-
let variants_result =
312-
template.variants(filters.placeholder_filters.iter().map(|f| f.as_str()));
313-
let variants = match variants_result {
314-
Ok(e) => {
315-
has_unknown_filter = false;
316-
e
317-
}
318-
Err(e) => {
319-
unknown_filter = Some(e);
320-
Vec::new()
321-
}
322-
};
323-
let out_template = out_base_dir.join(&template.name);
324-
let results = variants
325-
.iter()
326-
.map(|variant| self.generate(&out_template, template, variant))
327-
.collect::<anyhow::Result<Vec<_>>>()?;
328-
Ok((template, results))
347+
.map(|(template, variants)| {
348+
self.generate(&out_base_dir.join(&template.name), template, variants)
329349
})
330350
.collect::<anyhow::Result<Vec<_>>>()?;
331-
if has_unknown_filter {
332-
if let Some(filter) = unknown_filter {
333-
bail!("Unknown filter `{filter}`")
334-
} else {
335-
// Only reachable if no templates exist, Or if all templates have been filtered out, but you must filter
336-
// for at least one template for template filtering to even activate, so should be unreachable.
337-
bail!("No templates exist?")
338-
}
339-
}
340-
341-
let results = results
342-
.into_iter()
343-
.flat_map(|(_, a)| a.into_iter())
344-
.collect::<Vec<_>>();
345351
if results.is_empty() {
346352
// reachable with two templates with differing placeholders and filtering for both
347353
bail!("Nothing generated, all variants filtered out");
@@ -471,4 +477,62 @@ mod tests {
471477
}
472478
}
473479
}
480+
481+
#[test]
482+
pub fn template_filter_all_test() {
483+
let discovery = TemplateDiscovery {
484+
templates: Vec::from([test_template()]),
485+
};
486+
let filter = discovery.split_filter(std::iter::empty());
487+
assert_eq!(filter, Filters::default());
488+
let result = discovery.filter_variants(std::iter::empty()).unwrap();
489+
let templates = result
490+
.iter()
491+
.map(|(t, _)| t.name.as_str())
492+
.collect::<Vec<_>>();
493+
assert_eq!(templates, ["my-template"; 6])
494+
}
495+
496+
#[test]
497+
pub fn template_filter_one_test() {
498+
let discovery = TemplateDiscovery {
499+
templates: Vec::from([test_template()]),
500+
};
501+
let filter_args = ["my-template"];
502+
let filter = discovery.split_filter(filter_args.iter().copied());
503+
assert_eq!(
504+
filter,
505+
Filters {
506+
template_filters: HashSet::from(["my-template"]),
507+
placeholder_filters: Vec::new(),
508+
}
509+
);
510+
let result = discovery
511+
.filter_variants(filter_args.iter().copied())
512+
.unwrap();
513+
let templates = result
514+
.iter()
515+
.map(|(t, _)| t.name.as_str())
516+
.collect::<Vec<_>>();
517+
assert_eq!(templates, ["my-template"; 6])
518+
}
519+
520+
#[test]
521+
pub fn template_filter_none_test() {
522+
let discovery = TemplateDiscovery {
523+
templates: Vec::from([test_template()]),
524+
};
525+
let filter_args = ["unknown"];
526+
let filter = discovery.split_filter(filter_args.iter().copied());
527+
assert_eq!(
528+
filter,
529+
Filters {
530+
template_filters: HashSet::default(),
531+
placeholder_filters: Vec::from(["unknown"]),
532+
}
533+
);
534+
let result = discovery.filter_variants(filter_args.iter().copied());
535+
// Unknown filter
536+
assert!(result.is_err(), "Result: {result:#?}");
537+
}
474538
}

0 commit comments

Comments
 (0)