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}