syn_builder/
generics.rs

1use crate::{attrs_builder, macros::AttrsPropsBuilder, IntoExpr, IntoIdent, IntoPath, IntoType};
2use proc_macro2::TokenStream;
3use syn::{
4    BoundLifetimes, ConstParam, GenericParam, Generics, Lifetime, LifetimeParam, PredicateLifetime,
5    PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause,
6    WherePredicate,
7};
8
9pub fn generics<P: IntoGenericParam>(params: impl IntoIterator<Item = P>) -> Generics {
10    Generics {
11        lt_token: Some(Default::default()),
12        params: FromIterator::from_iter(
13            params.into_iter().map(IntoGenericParam::into_generic_param),
14        ),
15        gt_token: Some(Default::default()),
16        ..Default::default()
17    }
18}
19
20pub trait GenericsBuilder {
21    fn new<P: IntoGenericParam>(params: impl IntoIterator<Item = P>) -> Self;
22    fn where_clause(self, where_clause: impl Into<WhereClause>) -> Self;
23}
24
25impl GenericsBuilder for Generics {
26    fn new<P: IntoGenericParam>(params: impl IntoIterator<Item = P>) -> Self {
27        generics(params)
28    }
29    fn where_clause(self, where_clause: impl Into<WhereClause>) -> Self {
30        Self {
31            where_clause: Some(where_clause.into()),
32            ..self
33        }
34    }
35}
36
37pub trait IntoGenericParam {
38    fn into_generic_param(self) -> GenericParam;
39}
40
41impl IntoGenericParam for GenericParam {
42    fn into_generic_param(self) -> GenericParam {
43        self
44    }
45}
46
47pub fn lifetime_param(lifetime: impl Into<Lifetime>) -> LifetimeParam {
48    LifetimeParam {
49        attrs: Default::default(),
50        lifetime: lifetime.into(),
51        colon_token: None,
52        bounds: Default::default(),
53    }
54}
55
56attrs_builder!(LifetimeParam);
57
58impl IntoGenericParam for LifetimeParam {
59    fn into_generic_param(self) -> GenericParam {
60        GenericParam::Lifetime(self)
61    }
62}
63
64pub trait LifetimeParamBuilder: AttrsPropsBuilder {
65    fn new(lifetime: impl Into<Lifetime>) -> Self;
66    fn bounds<B: Into<Lifetime>>(self, bounds: impl IntoIterator<Item = B>) -> Self;
67}
68
69impl LifetimeParamBuilder for LifetimeParam {
70    fn new(lifetime: impl Into<Lifetime>) -> Self {
71        lifetime_param(lifetime)
72    }
73
74    fn bounds<B: Into<Lifetime>>(self, bounds: impl IntoIterator<Item = B>) -> Self {
75        Self {
76            colon_token: Some(Default::default()),
77            bounds: bounds.into_iter().map(Into::into).collect(),
78            ..self
79        }
80    }
81}
82
83pub fn type_param(ident: impl IntoIdent) -> TypeParam {
84    TypeParam {
85        attrs: Default::default(),
86        ident: ident.into_ident(),
87        colon_token: None,
88        bounds: Default::default(),
89        eq_token: None,
90        default: None,
91    }
92}
93
94attrs_builder!(TypeParam);
95
96impl IntoGenericParam for TypeParam {
97    fn into_generic_param(self) -> GenericParam {
98        GenericParam::Type(self)
99    }
100}
101
102pub trait TypeParamBuilder: AttrsPropsBuilder {
103    fn new(ident: impl IntoIdent) -> Self;
104    fn bounds<B: IntoTypeParamBound>(self, bounds: impl IntoIterator<Item = B>) -> Self;
105    fn default(self, default: impl IntoType) -> Self;
106}
107
108impl TypeParamBuilder for TypeParam {
109    fn new(ident: impl IntoIdent) -> Self {
110        type_param(ident)
111    }
112
113    fn bounds<B: IntoTypeParamBound>(self, bounds: impl IntoIterator<Item = B>) -> Self {
114        Self {
115            colon_token: Some(Default::default()),
116            bounds: FromIterator::from_iter(
117                bounds
118                    .into_iter()
119                    .map(IntoTypeParamBound::into_type_param_bound),
120            ),
121            ..self
122        }
123    }
124
125    fn default(self, default: impl IntoType) -> Self {
126        Self {
127            eq_token: Some(Default::default()),
128            default: Some(default.into_type()),
129            ..self
130        }
131    }
132}
133
134pub fn const_param(ident: impl IntoIdent, ty: impl IntoType) -> ConstParam {
135    ConstParam {
136        attrs: Default::default(),
137        const_token: Default::default(),
138        ident: ident.into_ident(),
139        colon_token: Default::default(),
140        ty: ty.into_type(),
141        eq_token: None,
142        default: None,
143    }
144}
145
146attrs_builder!(ConstParam);
147
148impl IntoGenericParam for ConstParam {
149    fn into_generic_param(self) -> GenericParam {
150        GenericParam::Const(self)
151    }
152}
153
154pub trait ConstParamBuilder: AttrsPropsBuilder {
155    fn new(ident: impl IntoIdent, ty: impl IntoType) -> Self;
156    fn default(self, default: impl IntoExpr) -> Self;
157}
158
159impl ConstParamBuilder for ConstParam {
160    fn new(ident: impl IntoIdent, ty: impl IntoType) -> Self {
161        const_param(ident, ty)
162    }
163
164    fn default(self, default: impl IntoExpr) -> Self {
165        Self {
166            eq_token: Some(Default::default()),
167            default: Some(default.into_expr()),
168            ..self
169        }
170    }
171}
172
173pub fn bound_lifetimes<L: IntoGenericParam>(
174    lifetimes: impl IntoIterator<Item = L>,
175) -> BoundLifetimes {
176    BoundLifetimes {
177        lifetimes: FromIterator::from_iter(
178            lifetimes
179                .into_iter()
180                .map(IntoGenericParam::into_generic_param),
181        ),
182        ..Default::default()
183    }
184}
185
186pub trait BoundLifetimesBuilder {
187    fn new<L: IntoGenericParam>(lifetimes: impl IntoIterator<Item = L>) -> Self;
188}
189
190impl BoundLifetimesBuilder for BoundLifetimes {
191    fn new<L: IntoGenericParam>(lifetimes: impl IntoIterator<Item = L>) -> Self {
192        bound_lifetimes(lifetimes)
193    }
194}
195
196pub trait IntoTypeParamBound {
197    fn into_type_param_bound(self) -> TypeParamBound;
198}
199
200impl IntoTypeParamBound for TypeParamBound {
201    fn into_type_param_bound(self) -> TypeParamBound {
202        self
203    }
204}
205
206impl IntoTypeParamBound for Lifetime {
207    fn into_type_param_bound(self) -> TypeParamBound {
208        TypeParamBound::Lifetime(self)
209    }
210}
211
212impl IntoTypeParamBound for TokenStream {
213    fn into_type_param_bound(self) -> TypeParamBound {
214        TypeParamBound::Verbatim(self)
215    }
216}
217
218pub fn trait_bound(path: impl IntoPath) -> TraitBound {
219    TraitBound {
220        paren_token: None,
221        modifier: TraitBoundModifier::None,
222        lifetimes: None,
223        path: path.into_path(),
224    }
225}
226
227impl IntoTypeParamBound for TraitBound {
228    fn into_type_param_bound(self) -> TypeParamBound {
229        TypeParamBound::Trait(self)
230    }
231}
232
233pub trait TraitBoundBuilder {
234    fn new(path: impl IntoPath) -> Self;
235    fn lifetimes(self, lifetimes: impl Into<BoundLifetimes>) -> Self;
236    fn modifier(self, maybe: bool) -> Self;
237}
238
239impl TraitBoundBuilder for TraitBound {
240    fn new(path: impl IntoPath) -> Self {
241        trait_bound(path)
242    }
243
244    fn lifetimes(self, lifetimes: impl Into<BoundLifetimes>) -> Self {
245        Self {
246            lifetimes: Some(lifetimes.into()),
247            ..self
248        }
249    }
250
251    fn modifier(self, maybe: bool) -> Self {
252        Self {
253            modifier: if maybe {
254                TraitBoundModifier::Maybe(Default::default())
255            } else {
256                TraitBoundModifier::None
257            },
258            ..self
259        }
260    }
261}
262
263pub fn where_clause<P: IntoWherePredicate>(predicates: impl IntoIterator<Item = P>) -> WhereClause {
264    WhereClause {
265        where_token: Default::default(),
266        predicates: FromIterator::from_iter(
267            predicates
268                .into_iter()
269                .map(IntoWherePredicate::into_where_predicate),
270        ),
271    }
272}
273
274pub trait IntoWherePredicate {
275    fn into_where_predicate(self) -> WherePredicate;
276}
277
278impl IntoWherePredicate for WherePredicate {
279    fn into_where_predicate(self) -> WherePredicate {
280        self
281    }
282}
283
284pub trait WhereClauseBuilder {
285    fn new<P: IntoWherePredicate>(predicates: impl IntoIterator<Item = P>) -> Self;
286}
287
288impl WhereClauseBuilder for WhereClause {
289    fn new<P: IntoWherePredicate>(predicates: impl IntoIterator<Item = P>) -> Self {
290        where_clause(predicates)
291    }
292}
293
294pub fn predicate_lifetime<B: Into<Lifetime>>(
295    lifetime: impl Into<Lifetime>,
296    bounds: impl IntoIterator<Item = B>,
297) -> PredicateLifetime {
298    PredicateLifetime {
299        lifetime: lifetime.into(),
300        colon_token: Default::default(),
301        bounds: FromIterator::from_iter(bounds.into_iter().map(Into::into)),
302    }
303}
304
305impl IntoWherePredicate for PredicateLifetime {
306    fn into_where_predicate(self) -> WherePredicate {
307        WherePredicate::Lifetime(self)
308    }
309}
310
311pub trait PredicateLifetimeBuilder {
312    fn new<B: Into<Lifetime>>(
313        lifetime: impl Into<Lifetime>,
314        bounds: impl IntoIterator<Item = B>,
315    ) -> Self;
316}
317
318impl PredicateLifetimeBuilder for PredicateLifetime {
319    fn new<B: Into<Lifetime>>(
320        lifetime: impl Into<Lifetime>,
321        bounds: impl IntoIterator<Item = B>,
322    ) -> Self {
323        predicate_lifetime(lifetime, bounds)
324    }
325}
326
327pub fn predicate_type<B: IntoTypeParamBound>(
328    bounded_ty: impl IntoType,
329    bounds: impl IntoIterator<Item = B>,
330) -> PredicateType {
331    PredicateType {
332        lifetimes: None,
333        bounded_ty: bounded_ty.into_type(),
334        colon_token: Default::default(),
335        bounds: FromIterator::from_iter(
336            bounds
337                .into_iter()
338                .map(IntoTypeParamBound::into_type_param_bound),
339        ),
340    }
341}
342
343impl IntoWherePredicate for PredicateType {
344    fn into_where_predicate(self) -> WherePredicate {
345        WherePredicate::Type(self)
346    }
347}
348
349pub trait PredicateTypeBuilder {
350    fn new<B: IntoTypeParamBound>(
351        bounded_ty: impl IntoType,
352        bounds: impl IntoIterator<Item = B>,
353    ) -> Self;
354    fn lifetimes(self, lifetimes: impl Into<BoundLifetimes>) -> Self;
355}
356
357impl PredicateTypeBuilder for PredicateType {
358    fn new<B: IntoTypeParamBound>(
359        bounded_ty: impl IntoType,
360        bounds: impl IntoIterator<Item = B>,
361    ) -> Self {
362        predicate_type(bounded_ty, bounds)
363    }
364
365    fn lifetimes(self, lifetimes: impl Into<BoundLifetimes>) -> Self {
366        Self {
367            lifetimes: Some(lifetimes.into()),
368            ..self
369        }
370    }
371}