1use syn::fold::{self, Fold};
2use syn::punctuated::Punctuated;
3use syn::{
4 FnArg, ImplItemFn, ItemImpl, ItemTrait, PatType, Path, Receiver, Signature, Token, TraitItemFn,
5};
6
7use crate::parser::SylviaAttribute;
8
9pub struct StripInput;
11
12fn remove_input_attr(inputs: Punctuated<FnArg, Token![,]>) -> Punctuated<FnArg, Token![,]> {
13 inputs
14 .into_iter()
15 .map(|input| match input {
16 syn::FnArg::Receiver(rec) if !rec.attrs.is_empty() => {
17 let rec = Receiver {
18 attrs: vec![],
19 ..rec
20 };
21 syn::FnArg::Receiver(rec)
22 }
23 syn::FnArg::Typed(ty) if !ty.attrs.is_empty() => {
24 let ty = PatType {
25 attrs: vec![],
26 ..ty
27 };
28 syn::FnArg::Typed(ty)
29 }
30 _ => input,
31 })
32 .collect()
33}
34
35impl Fold for StripInput {
36 fn fold_trait_item_fn(&mut self, i: TraitItemFn) -> TraitItemFn {
37 let attrs = i
38 .attrs
39 .into_iter()
40 .filter(|attr| SylviaAttribute::new(attr).is_none())
41 .collect();
42
43 let inputs = remove_input_attr(i.sig.inputs);
44 let sig = Signature { inputs, ..i.sig };
45 fold::fold_trait_item_fn(self, TraitItemFn { attrs, sig, ..i })
46 }
47
48 fn fold_impl_item_fn(&mut self, i: ImplItemFn) -> ImplItemFn {
49 let attrs = i
50 .attrs
51 .into_iter()
52 .filter(|attr| SylviaAttribute::new(attr).is_none())
53 .collect();
54
55 let inputs = remove_input_attr(i.sig.inputs);
56 let sig = Signature { inputs, ..i.sig };
57 fold::fold_impl_item_fn(self, ImplItemFn { attrs, sig, ..i })
58 }
59
60 fn fold_item_trait(&mut self, i: ItemTrait) -> ItemTrait {
61 let attrs = i
62 .attrs
63 .into_iter()
64 .filter(|attr| SylviaAttribute::new(attr).is_none())
65 .collect();
66
67 fold::fold_item_trait(self, ItemTrait { attrs, ..i })
68 }
69
70 fn fold_item_impl(&mut self, i: ItemImpl) -> ItemImpl {
71 let attrs = i
72 .attrs
73 .into_iter()
74 .filter(|attr| SylviaAttribute::new(attr).is_none())
75 .collect();
76
77 fold::fold_item_impl(self, ItemImpl { attrs, ..i })
78 }
79}
80
81pub struct StripGenerics;
83
84impl Fold for StripGenerics {
85 fn fold_path_arguments(&mut self, _: syn::PathArguments) -> syn::PathArguments {
86 syn::PathArguments::None
87 }
88}
89
90pub struct StripSelfPath;
92
93impl Fold for StripSelfPath {
94 fn fold_path(&mut self, path: Path) -> Path {
95 let segments = path
96 .segments
97 .into_iter()
98 .filter(|segment| segment.ident != "Self")
99 .collect();
100 syn::fold::fold_path(self, Path { segments, ..path })
101 }
102}