futures_await_test_macro/
lib.rs1#![warn(clippy::pedantic)]
2#![recursion_limit = "4096"]
3
4extern crate proc_macro;
5
6use proc_macro::TokenStream;
7use proc_macro2::Span;
8use quote::quote;
9use syn::{parse_macro_input, parse_quote, Ident, Item, Visibility};
10
11#[proc_macro_attribute]
12pub fn async_test(params: TokenStream, input: TokenStream) -> TokenStream {
13 assert!(
14 params.is_empty(),
15 "the #[async_test] attribute currently does not take parameters"
16 );
17
18 let mut inner = parse_macro_input!(input as Item);
19 let mut outer = inner.clone();
20 if let (&mut Item::Fn(ref mut inner_fn), &mut Item::Fn(ref mut outer_fn)) =
21 (&mut inner, &mut outer)
22 {
23 inner_fn.sig.ident = Ident::new(
24 &("_inner_".to_string() + &inner_fn.sig.ident.to_string()),
25 Span::call_site(),
26 );
27 let inner_ident = &inner_fn.sig.ident;
28 inner_fn.vis = Visibility::Inherited;
29 inner_fn.attrs.clear();
30 assert!(
31 outer_fn.sig.asyncness.take().is_some(),
32 "#[async_test] can only be applied to async functions"
33 );
34 outer_fn.attrs.push(parse_quote!(#[test]));
35 outer_fn.block = Box::new(parse_quote!({
36 ::futures_await_test::reexport::LocalPool::new().run_until(#inner_ident())
37 }));
38 } else {
39 panic!("#[async_test] can only be applied to async functions")
40 }
41 quote!(
42 #inner
43 #outer
44 )
45 .into()
46}