Skip to content

Commit 7506d57

Browse files
committed
Move transformer into module
1 parent 6a08cb1 commit 7506d57

File tree

2 files changed

+121
-102
lines changed

2 files changed

+121
-102
lines changed

trait_transformer/src/lib.rs

Lines changed: 2 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -6,112 +6,12 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9-
use proc_macro2::{Span, TokenStream};
10-
use quote::quote;
11-
use syn::{
12-
parse::{Parse, ParseStream},
13-
parse_macro_input, parse_quote,
14-
punctuated::Punctuated,
15-
token::Comma,
16-
Ident, ItemTrait, Path, PredicateType, Result, ReturnType, Token, TraitBound,
17-
TraitBoundModifier, TraitItem, Type, WherePredicate,
18-
};
19-
20-
struct Attrs {
21-
traits: Punctuated<Transform, Comma>,
22-
}
23-
24-
impl Parse for Attrs {
25-
fn parse(input: ParseStream) -> Result<Self> {
26-
Ok(Self {
27-
traits: input.parse_terminated(Transform::parse, Token![,])?,
28-
})
29-
}
30-
}
31-
32-
struct Transform {
33-
subtrait_name: Ident,
34-
#[allow(dead_code)]
35-
colon: Token![:],
36-
subtrait: Path,
37-
}
38-
39-
impl Parse for Transform {
40-
fn parse(input: ParseStream) -> Result<Self> {
41-
Ok(Self {
42-
subtrait_name: input.parse()?,
43-
colon: input.parse()?,
44-
subtrait: input.parse()?,
45-
})
46-
}
47-
}
9+
mod transformer;
4810

4911
#[proc_macro_attribute]
5012
pub fn trait_transformer(
5113
attr: proc_macro::TokenStream,
5214
item: proc_macro::TokenStream,
5315
) -> proc_macro::TokenStream {
54-
let attrs = parse_macro_input!(attr as Attrs);
55-
let item = parse_macro_input!(item as ItemTrait);
56-
57-
let transformed_trait = transform_trait(&attrs, &item);
58-
let output = quote! {
59-
#item
60-
#transformed_trait
61-
};
62-
63-
output.into()
64-
}
65-
66-
fn transform_trait(attrs: &Attrs, tr: &ItemTrait) -> TokenStream {
67-
let traits = attrs
68-
.traits
69-
.iter()
70-
.map(|attr| {
71-
let subtrait = &attr.subtrait;
72-
let fn_bounds = tr.items.iter().filter_map(|item| {
73-
match item {
74-
TraitItem::Fn(item_fn) => {
75-
let is_async = item_fn.sig.asyncness.is_some();
76-
let returns_impl_trait =
77-
if let ReturnType::Type(_, ty) = &item_fn.sig.output {
78-
matches!(**ty, Type::ImplTrait(_))
79-
} else {
80-
false
81-
};
82-
83-
if is_async || returns_impl_trait {
84-
let name = &item_fn.sig.ident;
85-
return Some(quote! { #name(): #subtrait });
86-
}
87-
}
88-
_ => (),
89-
}
90-
None
91-
});
92-
93-
let tr_ident = &tr.ident;
94-
let supertrait = syn::TypeParamBound::Verbatim(quote! {
95-
#tr_ident<#(#fn_bounds),*>
96-
});
97-
98-
ItemTrait {
99-
attrs: Vec::new(),
100-
ident: attr.subtrait_name.clone(),
101-
items: Vec::new(),
102-
supertraits: Punctuated::from_iter(vec![
103-
supertrait,
104-
syn::TypeParamBound::Trait(TraitBound {
105-
paren_token: None,
106-
modifier: TraitBoundModifier::None,
107-
lifetimes: None,
108-
path: attr.subtrait.clone(),
109-
}),
110-
].into_iter()),
111-
..tr.clone()
112-
}
113-
})
114-
.collect::<Vec<_>>();
115-
116-
quote! { #(#traits)* }
16+
transformer::trait_transformer(attr, item)
11717
}

trait_transformer/src/transformer.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright (c) 2023 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
use proc_macro2::{Span, TokenStream};
10+
use quote::quote;
11+
use syn::{
12+
parse::{Parse, ParseStream},
13+
parse_macro_input, parse_quote,
14+
punctuated::Punctuated,
15+
token::Comma,
16+
Ident, ItemTrait, Path, PredicateType, Result, ReturnType, Token, TraitBound,
17+
TraitBoundModifier, TraitItem, Type, WherePredicate,
18+
};
19+
20+
struct Attrs {
21+
traits: Punctuated<Transform, Comma>,
22+
}
23+
24+
impl Parse for Attrs {
25+
fn parse(input: ParseStream) -> Result<Self> {
26+
Ok(Self {
27+
traits: input.parse_terminated(Transform::parse, Token![,])?,
28+
})
29+
}
30+
}
31+
32+
struct Transform {
33+
subtrait_name: Ident,
34+
#[allow(dead_code)]
35+
colon: Token![:],
36+
subtrait: Path,
37+
}
38+
39+
impl Parse for Transform {
40+
fn parse(input: ParseStream) -> Result<Self> {
41+
Ok(Self {
42+
subtrait_name: input.parse()?,
43+
colon: input.parse()?,
44+
subtrait: input.parse()?,
45+
})
46+
}
47+
}
48+
49+
pub fn trait_transformer(
50+
attr: proc_macro::TokenStream,
51+
item: proc_macro::TokenStream,
52+
) -> proc_macro::TokenStream {
53+
let attrs = parse_macro_input!(attr as Attrs);
54+
let item = parse_macro_input!(item as ItemTrait);
55+
56+
let transformed_trait = transform_trait(&attrs, &item);
57+
let output = quote! {
58+
#item
59+
#transformed_trait
60+
};
61+
62+
output.into()
63+
}
64+
65+
fn transform_trait(attrs: &Attrs, tr: &ItemTrait) -> TokenStream {
66+
let traits = attrs
67+
.traits
68+
.iter()
69+
.map(|attr| {
70+
let subtrait = &attr.subtrait;
71+
let fn_bounds = tr.items.iter().filter_map(|item| {
72+
match item {
73+
TraitItem::Fn(item_fn) => {
74+
let is_async = item_fn.sig.asyncness.is_some();
75+
let returns_impl_trait =
76+
if let ReturnType::Type(_, ty) = &item_fn.sig.output {
77+
matches!(**ty, Type::ImplTrait(_))
78+
} else {
79+
false
80+
};
81+
82+
if is_async || returns_impl_trait {
83+
let name = &item_fn.sig.ident;
84+
return Some(quote! { #name(): #subtrait });
85+
}
86+
}
87+
_ => (),
88+
}
89+
None
90+
});
91+
92+
let tr_ident = &tr.ident;
93+
let supertrait = syn::TypeParamBound::Verbatim(quote! {
94+
#tr_ident<#(#fn_bounds),*>
95+
});
96+
97+
ItemTrait {
98+
attrs: Vec::new(),
99+
ident: attr.subtrait_name.clone(),
100+
items: Vec::new(),
101+
supertraits: Punctuated::from_iter(
102+
vec![
103+
supertrait,
104+
syn::TypeParamBound::Trait(TraitBound {
105+
paren_token: None,
106+
modifier: TraitBoundModifier::None,
107+
lifetimes: None,
108+
path: attr.subtrait.clone(),
109+
}),
110+
]
111+
.into_iter(),
112+
),
113+
..tr.clone()
114+
}
115+
})
116+
.collect::<Vec<_>>();
117+
118+
quote! { #(#traits)* }
119+
}

0 commit comments

Comments
 (0)