1#![forbid(unsafe_code, future_incompatible, rust_2018_idioms)]
27#![deny(missing_debug_implementations, nonstandard_style)]
28#![recursion_limit = "512"]
29
30use proc_macro::TokenStream;
31use quote::{quote, quote_spanned};
32use syn::spanned::Spanned;
33
34#[cfg(not(test))] #[proc_macro_attribute]
46pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
47 let input = syn::parse_macro_input!(item as syn::ItemFn);
48
49 let ret = &input.sig.output;
50 let inputs = &input.sig.inputs;
51 let name = &input.sig.ident;
52 let body = &input.block;
53 let attrs = &input.attrs;
54 let vis = &input.vis;
55
56 if name != "main" {
57 return TokenStream::from(quote_spanned! { name.span() =>
58 compile_error!("only the main function can be tagged with #[async_std::main]"),
59 });
60 }
61
62 if input.sig.asyncness.is_none() {
63 return TokenStream::from(quote_spanned! { input.span() =>
64 compile_error!("the async keyword is missing from the function declaration"),
65 });
66 }
67
68 let result = quote! {
69 #vis fn main() #ret {
70 #(#attrs)*
71 async fn main(#inputs) #ret {
72 #body
73 }
74
75 async_std::task::block_on(async {
76 main().await
77 })
78 }
79
80 };
81
82 result.into()
83}
84
85#[proc_macro_attribute]
97pub fn test(_attr: TokenStream, item: TokenStream) -> TokenStream {
98 let input = syn::parse_macro_input!(item as syn::ItemFn);
99
100 let ret = &input.sig.output;
101 let name = &input.sig.ident;
102 let body = &input.block;
103 let attrs = &input.attrs;
104 let vis = &input.vis;
105
106 if input.sig.asyncness.is_none() {
107 return TokenStream::from(quote_spanned! { input.span() =>
108 compile_error!("the async keyword is missing from the function declaration"),
109 });
110 }
111
112 let result = quote! {
113 #[::core::prelude::v1::test]
114 #(#attrs)*
115 #vis fn #name() #ret {
116 async_std::task::block_on(async { #body })
117 }
118 };
119
120 result.into()
121}
122
123#[proc_macro_attribute]
139pub fn bench(_attr: TokenStream, item: TokenStream) -> TokenStream {
140 let input = syn::parse_macro_input!(item as syn::ItemFn);
141
142 let ret = &input.sig.output;
143 let args = &input.sig.inputs;
144 let name = &input.sig.ident;
145 let body = &input.block;
146 let attrs = &input.attrs;
147 let vis = &input.vis;
148
149 if input.sig.asyncness.is_none() {
150 return TokenStream::from(quote_spanned! { input.span() =>
151 compile_error!("the async keyword is missing from the function declaration"),
152 });
153 }
154
155 if !args.is_empty() {
156 return TokenStream::from(quote_spanned! { args.span() =>
157 compile_error!("async benchmarks don't take any arguments"),
158 });
159 }
160
161 let result = quote! {
162 #[::core::prelude::v1::bench]
163 #(#attrs)*
164 #vis fn #name(b: &mut test::Bencher) #ret {
165 task::block_on(task::spawn(async {
166 #body
167 }))
168 }
169 };
170
171 result.into()
172}