bon_macros/normalization/cfg/
visit.rs
1use crate::util::prelude::*;
2
3pub(crate) fn visit_attrs(
4 item: &mut syn::Item,
5 visit: impl FnMut(&mut Vec<syn::Attribute>) -> Result<bool>,
6) -> Result {
7 VisitAttrs { visit }.visit_item(item)
8}
9
10struct VisitAttrs<T> {
11 visit: T,
12}
13
14impl<T> VisitAttrs<T>
15where
16 T: FnMut(&mut Vec<syn::Attribute>) -> Result<bool>,
17{
18 fn visit(&mut self, attrs: &mut Vec<syn::Attribute>) -> Result<bool> {
19 (self.visit)(attrs)
20 }
21
22 fn visit_item(&mut self, item: &mut syn::Item) -> Result {
23 match item {
24 syn::Item::Fn(fn_item) => self.visit_item_fn(fn_item),
25 syn::Item::Impl(impl_item) => self.visit_item_impl(impl_item),
26 _ => Ok(()),
27 }
28 }
29
30 fn visit_item_fn(&mut self, fn_item: &mut syn::ItemFn) -> Result {
31 if !self.visit(&mut fn_item.attrs)? {
32 bail!(
33 fn_item,
34 "This code should never be executed if there is a `#[cfg(...)]` attribute \
35 on the function itself, because if that cfg evaluates to `false`, \
36 no other proc macro on the item should be called."
37 )
38 }
39
40 self.visit_signature(&mut fn_item.sig)
41 }
42
43 fn visit_impl_item_fn(&mut self, fn_item: &mut syn::ImplItemFn) -> Result<bool> {
44 if !self.visit(&mut fn_item.attrs)? {
45 return Ok(false);
46 }
47
48 self.visit_signature(&mut fn_item.sig)?;
49
50 Ok(true)
51 }
52
53 fn visit_signature(&mut self, sig: &mut syn::Signature) -> Result {
54 sig.inputs.try_retain_mut(|arg| match arg {
55 syn::FnArg::Typed(arg) => self.visit(&mut arg.attrs),
56 syn::FnArg::Receiver(arg) => self.visit(&mut arg.attrs),
57 })?;
58
59 self.visit_generics(&mut sig.generics)?;
60
61 if let Some(variadic) = &mut sig.variadic {
62 if !self.visit(&mut variadic.attrs)? {
63 sig.variadic = None;
64 }
65 }
66
67 Ok(())
72 }
73
74 fn visit_generics(&mut self, generics: &mut syn::Generics) -> Result {
75 generics.params.try_retain_mut(|param| match param {
76 syn::GenericParam::Type(param) => self.visit(&mut param.attrs),
77 syn::GenericParam::Lifetime(param) => self.visit(&mut param.attrs),
78 syn::GenericParam::Const(param) => self.visit(&mut param.attrs),
79 })
80 }
81
82 fn visit_item_impl(&mut self, impl_item: &mut syn::ItemImpl) -> Result {
83 if !self.visit(&mut impl_item.attrs)? {
84 bail!(
85 impl_item,
86 "This code should never be executed if there is a `#[cfg(...)]` attribute \
87 on the impl itself, because if that cfg evaluates to `false`, \
88 no other proc macro on the item should be called."
89 )
90 }
91
92 self.visit_generics(&mut impl_item.generics)?;
93
94 impl_item.items.try_retain_mut(|item| match item {
95 syn::ImplItem::Fn(fn_item) => self.visit_impl_item_fn(fn_item),
96 _ => Ok(true),
97 })
98 }
99}