Skip to content

Commit 2815edc

Browse files
authored
RUST-2103 Update the rest of actions to document options (#1272)
1 parent 3358916 commit 2815edc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1046
-1045
lines changed

macros/src/action_impl.rs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
extern crate proc_macro;
2+
3+
use quote::quote;
4+
use syn::{
5+
braced,
6+
parenthesized,
7+
parse::{Parse, ParseStream},
8+
parse_macro_input,
9+
parse_quote_spanned,
10+
spanned::Spanned,
11+
Block,
12+
Generics,
13+
Ident,
14+
Lifetime,
15+
Token,
16+
Type,
17+
};
18+
19+
use crate::parse_name;
20+
21+
pub(crate) fn action_impl(
22+
attrs: proc_macro::TokenStream,
23+
input: proc_macro::TokenStream,
24+
) -> proc_macro::TokenStream {
25+
let ActionImplAttrs { sync_type } = parse_macro_input!(attrs as ActionImplAttrs);
26+
let ActionImpl {
27+
generics,
28+
lifetime,
29+
action,
30+
future_name,
31+
exec_self_mut,
32+
exec_output,
33+
exec_body,
34+
} = parse_macro_input!(input as ActionImpl);
35+
36+
let mut unbounded_generics = generics.clone();
37+
for lt in unbounded_generics.lifetimes_mut() {
38+
lt.bounds.clear();
39+
}
40+
for ty in unbounded_generics.type_params_mut() {
41+
ty.bounds.clear();
42+
}
43+
44+
let sync_run = if let Some(sync_type) = sync_type {
45+
quote! {
46+
/// Synchronously execute this action.
47+
pub fn run(self) -> Result<#sync_type> {
48+
crate::sync::TOKIO_RUNTIME.block_on(std::future::IntoFuture::into_future(self)).map(<#sync_type>::new)
49+
}
50+
}
51+
} else {
52+
quote! {
53+
/// Synchronously execute this action.
54+
pub fn run(self) -> #exec_output {
55+
crate::sync::TOKIO_RUNTIME.block_on(std::future::IntoFuture::into_future(self))
56+
}
57+
}
58+
};
59+
60+
quote! {
61+
impl #generics crate::action::private::Sealed for #action { }
62+
63+
impl #generics crate::action::Action for #action { }
64+
65+
impl #generics std::future::IntoFuture for #action {
66+
type Output = #exec_output;
67+
type IntoFuture = #future_name #unbounded_generics;
68+
69+
fn into_future(#exec_self_mut self) -> Self::IntoFuture {
70+
#future_name (Box::pin(async move {
71+
#exec_body
72+
}))
73+
}
74+
}
75+
76+
pub struct #future_name #generics (crate::BoxFuture<#lifetime, #exec_output>);
77+
78+
impl #generics std::future::Future for #future_name #unbounded_generics {
79+
type Output = #exec_output;
80+
81+
fn poll(mut self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output> {
82+
self.0.as_mut().poll(cx)
83+
}
84+
}
85+
86+
#[cfg(feature = "sync")]
87+
impl #generics #action {
88+
#sync_run
89+
}
90+
}.into()
91+
}
92+
93+
// impl<generics> Action for ActionType {
94+
// type Future = FutureName;
95+
// async fn execute([mut] self) -> OutType { <exec body> }
96+
// [SyncWrap]
97+
// }
98+
struct ActionImpl {
99+
generics: Generics,
100+
lifetime: Lifetime,
101+
action: Type,
102+
future_name: Ident,
103+
exec_self_mut: Option<Token![mut]>,
104+
exec_output: Type,
105+
exec_body: Block,
106+
}
107+
108+
impl Parse for ActionImpl {
109+
fn parse(input: ParseStream) -> syn::Result<Self> {
110+
// impl<generics> Action for ActionType
111+
input.parse::<Token![impl]>()?;
112+
let generics: Generics = input.parse()?;
113+
let mut lifetime = None;
114+
for lt in generics.lifetimes() {
115+
if lifetime.is_some() {
116+
return Err(input.error("only one lifetime argument permitted"));
117+
}
118+
lifetime = Some(lt);
119+
}
120+
let lifetime = match lifetime {
121+
Some(lt) => lt.lifetime.clone(),
122+
None => parse_quote_spanned! { generics.span() => 'static },
123+
};
124+
parse_name(input, "Action")?;
125+
input.parse::<Token![for]>()?;
126+
let action = input.parse()?;
127+
128+
let impl_body;
129+
braced!(impl_body in input);
130+
131+
// type Future = FutureName;
132+
impl_body.parse::<Token![type]>()?;
133+
parse_name(&impl_body, "Future")?;
134+
impl_body.parse::<Token![=]>()?;
135+
let future_name = impl_body.parse()?;
136+
impl_body.parse::<Token![;]>()?;
137+
138+
// async fn execute([mut] self) -> OutType { <exec body> }
139+
impl_body.parse::<Token![async]>()?;
140+
impl_body.parse::<Token![fn]>()?;
141+
parse_name(&impl_body, "execute")?;
142+
let exec_args;
143+
parenthesized!(exec_args in impl_body);
144+
let exec_self_mut = exec_args.parse()?;
145+
exec_args.parse::<Token![self]>()?;
146+
if !exec_args.is_empty() {
147+
return Err(exec_args.error("unexpected token"));
148+
}
149+
impl_body.parse::<Token![->]>()?;
150+
let exec_output = impl_body.parse()?;
151+
let exec_body = impl_body.parse()?;
152+
153+
if !impl_body.is_empty() {
154+
return Err(exec_args.error("unexpected token"));
155+
}
156+
157+
Ok(ActionImpl {
158+
generics,
159+
lifetime,
160+
action,
161+
future_name,
162+
exec_self_mut,
163+
exec_output,
164+
exec_body,
165+
})
166+
}
167+
}
168+
169+
struct ActionImplAttrs {
170+
sync_type: Option<Type>,
171+
}
172+
173+
impl Parse for ActionImplAttrs {
174+
fn parse(input: ParseStream) -> syn::Result<Self> {
175+
let mut out = Self { sync_type: None };
176+
if input.is_empty() {
177+
return Ok(out);
178+
}
179+
180+
parse_name(input, "sync")?;
181+
input.parse::<Token![=]>()?;
182+
out.sync_type = Some(input.parse()?);
183+
Ok(out)
184+
}
185+
}

0 commit comments

Comments
 (0)