Skip to main content

sdecay_nolt/
lib.rs

1#![allow(missing_docs, reason = "That's an internal procmacro crate")]
2
3use proc_macro::TokenStream;
4use proc_macro2::Span;
5use quote::ToTokens;
6use syn::{
7    AngleBracketedGenericArguments, AssocConst, AssocType, BareFnArg, BoundLifetimes, ConstParam,
8    Constraint, GenericArgument, GenericParam, Ident, Lifetime, LifetimeParam,
9    ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf, ReturnType, TraitBound,
10    Type, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeParam, TypeParamBound, TypeParen,
11    TypePath, TypePtr, TypeReference, TypeSlice, TypeTraitObject, TypeTuple, parse_macro_input,
12    punctuated::Punctuated,
13};
14
15trait Nolt {
16    fn transform(&mut self);
17}
18
19impl<T: Nolt> Nolt for Box<T> {
20    fn transform(&mut self) {
21        T::transform(&mut **self);
22    }
23}
24
25impl<T: Nolt> Nolt for Option<T> {
26    fn transform(&mut self) {
27        if let Some(s) = self.as_mut() {
28            s.transform();
29        }
30    }
31}
32
33impl<T: Nolt> Nolt for Vec<T> {
34    fn transform(&mut self) {
35        self.iter_mut().for_each(T::transform);
36    }
37}
38
39impl<T: Nolt, S> Nolt for Punctuated<T, S> {
40    fn transform(&mut self) {
41        self.iter_mut().for_each(T::transform);
42    }
43}
44
45//
46
47impl Nolt for Lifetime {
48    fn transform(&mut self) {
49        self.ident = Ident::new("static", Span::call_site());
50    }
51}
52
53impl Nolt for GenericParam {
54    fn transform(&mut self) {
55        match self {
56            GenericParam::Lifetime(LifetimeParam {
57                lifetime, bounds, ..
58            }) => {
59                lifetime.transform();
60                bounds.transform();
61            }
62            GenericParam::Type(TypeParam {
63                bounds, default, ..
64            }) => {
65                bounds.transform();
66                default.transform();
67            }
68            GenericParam::Const(ConstParam { ty, .. }) => {
69                ty.transform();
70            }
71        }
72    }
73}
74
75impl Nolt for BoundLifetimes {
76    fn transform(&mut self) {
77        self.lifetimes.transform();
78    }
79}
80
81impl Nolt for BareFnArg {
82    fn transform(&mut self) {
83        self.ty.transform();
84    }
85}
86
87impl Nolt for ReturnType {
88    fn transform(&mut self) {
89        match self {
90            ReturnType::Default => {}
91            ReturnType::Type(_, ty) => ty.transform(),
92        }
93    }
94}
95
96impl Nolt for GenericArgument {
97    fn transform(&mut self) {
98        match self {
99            GenericArgument::Lifetime(lifetime) => lifetime.transform(),
100            GenericArgument::Type(tp) => tp.transform(),
101            GenericArgument::AssocType(AssocType { generics, ty, .. }) => {
102                generics.transform();
103                ty.transform();
104            }
105            GenericArgument::AssocConst(AssocConst { generics, .. }) => {
106                generics.transform();
107            }
108            GenericArgument::Constraint(Constraint {
109                generics, bounds, ..
110            }) => {
111                generics.transform();
112                bounds.transform();
113            }
114            _ => {}
115        }
116    }
117}
118
119impl Nolt for AngleBracketedGenericArguments {
120    fn transform(&mut self) {
121        let Self { args, .. } = self;
122        args.transform();
123    }
124}
125
126impl Nolt for ParenthesizedGenericArguments {
127    fn transform(&mut self) {
128        let Self { inputs, output, .. } = self;
129        inputs.transform();
130        output.transform();
131    }
132}
133
134impl Nolt for PathArguments {
135    fn transform(&mut self) {
136        match self {
137            PathArguments::None => {}
138            PathArguments::AngleBracketed(angle) => angle.transform(),
139            PathArguments::Parenthesized(paren) => paren.transform(),
140        }
141    }
142}
143
144impl Nolt for PathSegment {
145    fn transform(&mut self) {
146        self.arguments.transform();
147    }
148}
149
150impl Nolt for Path {
151    fn transform(&mut self) {
152        self.segments.transform();
153    }
154}
155
156impl Nolt for TypeParamBound {
157    fn transform(&mut self) {
158        match self {
159            syn::TypeParamBound::Trait(TraitBound {
160                lifetimes, path, ..
161            }) => {
162                lifetimes.transform();
163                path.transform();
164            }
165            syn::TypeParamBound::Lifetime(lifetime) => lifetime.transform(),
166            _ => {}
167        }
168    }
169}
170
171impl Nolt for QSelf {
172    fn transform(&mut self) {
173        let Self { ty, .. } = self;
174        ty.transform();
175    }
176}
177
178impl Nolt for Type {
179    fn transform(&mut self) {
180        match self {
181            Type::BareFn(TypeBareFn {
182                lifetimes,
183                inputs,
184                output,
185                ..
186            }) => {
187                lifetimes.transform();
188                inputs.transform();
189                output.transform();
190            }
191            Type::Group(TypeGroup { elem, .. })
192            | Type::Paren(TypeParen { elem, .. })
193            | Type::Ptr(TypePtr { elem, .. })
194            | Type::Slice(TypeSlice { elem, .. })
195            | Type::Array(TypeArray { elem, .. }) => {
196                elem.transform();
197            }
198            Type::ImplTrait(TypeImplTrait { bounds, .. })
199            | Type::TraitObject(TypeTraitObject { bounds, .. }) => bounds.transform(),
200            Type::Path(TypePath { qself, path }) => {
201                qself.transform();
202                path.transform();
203            }
204            Type::Reference(TypeReference { lifetime, elem, .. }) => {
205                lifetime.transform();
206                elem.transform();
207            }
208            Type::Tuple(TypeTuple { elems, .. }) => elems.transform(),
209            _ => {}
210        }
211    }
212}
213
214#[proc_macro]
215pub fn nolt(input: TokenStream) -> TokenStream {
216    let mut tp = parse_macro_input!(input as Type);
217    tp.transform();
218    tp.to_token_stream().into()
219}