fluvio_future_derive/
lib.rs1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use proc_macro2::Span;
5use quote::{quote, quote_spanned};
6use syn::{Ident, ItemFn};
7use syn::spanned::Spanned;
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 use syn::AttributeArgs;
55
56 let attribute_args = syn::parse_macro_input!(args as AttributeArgs);
57 let input = syn::parse_macro_input!(item as ItemFn);
58 let name = &input.sig.ident;
59 let sync_name = format!("{}_sync", name);
60 let out_fn_iden = Ident::new(&sync_name, Span::call_site());
61
62 let test_attributes = generate::generate_test_attributes(&attribute_args);
63
64 let expression = quote! {
65
66 #[test]
67 #test_attributes
68 fn #out_fn_iden() {
69
70 ::fluvio_future::subscriber::init_logger();
71
72 #input
73
74 let ft = async {
75 #name().await
76 };
77
78 #[cfg(not(target_arch = "wasm32"))]
79 if let Err(err) = ::fluvio_future::task::run_block_on(ft) {
80 assert!(false,"error: {:?}",err);
81 }
82 #[cfg(target_arch = "wasm32")]
83 ::fluvio_future::task::run_block_on(ft);
84
85 }
86 };
87
88 expression.into()
89}
90
91#[proc_macro_attribute]
92pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
93 use syn::AttributeArgs;
94
95 let attribute_args = syn::parse_macro_input!(args as AttributeArgs);
96 let input = syn::parse_macro_input!(item as ItemFn);
97 let name = &input.sig.ident;
98 let sync_name = format!("{}_sync", name);
99 let out_fn_iden = Ident::new(&sync_name, Span::call_site());
100
101 let test_attributes = generate::generate_test_attributes(&attribute_args);
102
103 let expression = quote! {
104
105 #[test]
106 #test_attributes
107 fn #out_fn_iden() {
108
109 ::fluvio_future::subscriber::init_logger();
110
111 #input
112
113 let ft = async {
114 #name().await;
115 };
116
117
118 ::fluvio_future::task::run_block_on(ft);
119
120 }
121 };
122
123 expression.into()
124}
125
126mod generate {
127
128 use proc_macro2::TokenStream;
129 use quote::quote;
130 use syn::NestedMeta;
131
132 pub fn generate_test_attributes(attributes: &Vec<NestedMeta>) -> TokenStream {
133 let args = attributes.iter().map(|meta| {
134 quote! {
135 #[#meta]
136 }
137 });
138
139 quote! {
140
141 #(#args)*
142
143 }
144 }
145}