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
45impl 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}