rt-local-macros 0.1.4

Thread local asynchronous runtime working with platform-specific event loops.
Documentation
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote};
use syn::{parse2, spanned::Spanned, ItemFn, Result};

pub fn build(
    _attr: TokenStream,
    item: TokenStream,
    backend: &str,
    is_test: bool,
) -> Result<TokenStream> {
    if let Ok(mut item_fn) = parse2::<ItemFn>(item) {
        if item_fn.sig.asyncness.is_none() {
            if is_test {
                return Ok(quote! {
                    #[::core::prelude::v1::test]
                    #item_fn
                });
            } else {
                bail!(
                    item_fn.sig.span(),
                    "the `async` keyword is missing from the function declaration"
                );
            }
        }
        item_fn.sig.asyncness = None;
        let attrs = &item_fn.attrs;
        let vis = &item_fn.vis;
        let sig = &item_fn.sig;
        let stmts = &item_fn.block.stmts;
        let test = if is_test {
            quote!(#[::core::prelude::v1::test])
        } else {
            quote!()
        };
        let backend = format_ident!("{}", backend);
        Ok(quote! {
            #test
            #(#attrs)*
            #vis #sig {
                ::rt_local::runtime::#backend::run(async {
                    #(#stmts)*
                })
            }
        })
    } else {
        let name = if is_test { "test" } else { "main" };
        bail!(
            Span::call_site(),
            "`#[{}]` can apply to only function",
            name
        );
    }
}