Skip to main content

traffic_light_macros/
lib.rs

1//! Macros for another single-threaded blocking asynchronous executor for Rust.
2//!
3//! # Examples
4//!
5//! ```
6//! use std::{
7//!     error,
8//!     result,
9//! };
10//!
11//! #[traffic_light::main]
12//! async fn main() -> result::Result<(), Box<dyn error::Error>> {
13//!     // ...
14//!     Ok(())
15//! }
16//! ```
17
18use proc_macro::TokenStream;
19use quote::quote;
20use syn::{ItemFn, parse_macro_input, parse_quote};
21
22/// Expands `async fn main() {}` into a call to [`Executor::block_on`]
23///
24/// # Examples
25///
26/// ```
27/// use std::{
28///     error,
29///     result,
30/// };
31///
32/// #[traffic_light::main]
33/// async fn main() -> result::Result<(), Box<dyn error::Error>> {
34///     // ...
35///     Ok(())
36/// }
37/// ```
38///
39/// # Expansion
40///
41/// ```
42/// fn main() {
43///     ::traffic_light::executor::Executor::block_on(async {
44///         // ...
45///     })
46/// }
47/// ```
48///
49/// [`Executor::block_on`]: ../traffic-light/executor/struct.Executor.html#method.block_on
50#[proc_macro_attribute]
51pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
52    let item = parse_macro_input!(item as ItemFn);
53
54    expand_async_fn(item)
55}
56
57#[proc_macro_attribute]
58pub fn test(_attr: TokenStream, item: TokenStream) -> TokenStream {
59    let mut item = parse_macro_input!(item as ItemFn);
60
61    item.attrs.push(parse_quote! { #[test] });
62
63    expand_async_fn(item)
64}
65
66fn expand_async_fn(item: ItemFn) -> TokenStream {
67    let ItemFn {
68        attrs,
69        mut sig,
70        block,
71        ..
72    } = item;
73
74    sig.asyncness = None;
75
76    let expanded = quote! {
77        #(#attrs)*
78        #sig {
79            ::traffic_light::executor::Executor::block_on(async #block)
80        }
81    };
82
83    TokenStream::from(expanded)
84}