fluvio_future_derive/
lib.rs1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use proc_macro2::Span;
5use quote::{quote, quote_spanned};
6use syn::spanned::Spanned;
7use syn::{Ident, ItemFn};
8
9#[proc_macro_attribute]
10pub fn main_async(_attr: TokenStream, item: TokenStream) -> TokenStream {
11 let input = syn::parse_macro_input!(item as syn::ItemFn);
12
13 let ret = &input.sig.output;
14 let inputs = &input.sig.inputs;
15 let name = &input.sig.ident;
16 let body = &input.block;
17 let attrs = &input.attrs;
18 let vis = &input.vis;
19
20 if name != "main" {
21 return TokenStream::from(quote_spanned! { name.span() =>
22 compile_error!("only the main function can be tagged with #[fluvio_future::main_async]"),
23 });
24 }
25
26 if input.sig.asyncness.is_none() {
27 return TokenStream::from(quote_spanned! { input.span() =>
28 compile_error!("the async keyword is missing from the function declaration"),
29 });
30 }
31
32 let result = quote! {
33 #vis fn main() #ret {
34
35 ::fluvio_future::subscriber::init_logger();
36
37 #(#attrs)*
38 async fn main(#inputs) #ret {
39 #body
40 }
41
42 ::fluvio_future::task::run_block_on(async {
43 main().await
44 })
45 }
46
47 };
48
49 result.into()
50}
51
52#[proc_macro_attribute]
53pub fn test_async(args: TokenStream, item: TokenStream) -> TokenStream {
54
55 let attribute_args = syn::parse_macro_input!(args with syn::punctuated::Punctuated::<syn::Meta, syn::Token![,]>::parse_terminated);
56 let input = syn::parse_macro_input!(item as ItemFn);
57 let name = &input.sig.ident;
58 let sync_name = format!("{}_sync", name);
59 let out_fn_iden = Ident::new(&sync_name, Span::call_site());
60
61 let test_attributes = generate::generate_test_attributes(&attribute_args);
62
63 let expression = quote! {
64
65 #[test]
66 #test_attributes
67 fn #out_fn_iden() {
68
69 ::fluvio_future::subscriber::init_logger();
70
71 #input
72
73 let ft = async {
74 #name().await
75 };
76
77 #[cfg(not(target_arch = "wasm32"))]
78 if let Err(err) = ::fluvio_future::task::run_block_on(ft) {
79 assert!(false,"error: {:?}",err);
80 }
81 }
82 };
83
84 expression.into()
85}
86
87#[proc_macro_attribute]
88pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
89
90 let attribute_args = syn::parse_macro_input!(args with syn::punctuated::Punctuated::<syn::Meta, syn::Token![,]>::parse_terminated);
91 let input = syn::parse_macro_input!(item as ItemFn);
92 let name = &input.sig.ident;
93 let sync_name = format!("{}_sync", name);
94 let out_fn_iden = Ident::new(&sync_name, Span::call_site());
95
96 let test_attributes = generate::generate_test_attributes(&attribute_args);
97
98 let expression = quote! {
99
100 #[test]
101 #test_attributes
102 fn #out_fn_iden() {
103
104 ::fluvio_future::subscriber::init_logger();
105
106 #input
107
108 let ft = async {
109 #name().await;
110 };
111
112
113 ::fluvio_future::task::run_block_on(ft);
114 }
115 };
116
117 expression.into()
118}
119
120mod generate {
121
122 use proc_macro2::TokenStream;
123 use quote::quote;
124
125 pub fn generate_test_attributes(attributes: &syn::punctuated::Punctuated<syn::Meta, syn::Token![,]>) -> TokenStream {
126 let args = attributes.iter().map(|meta| {
127 quote! {
128 #[#meta]
129 }
130 });
131
132 quote! {
133
134 #(#args)*
135
136 }
137 }
138}