winit_main_proc/
lib.rs

1//! Procedural macros for `winit-main`.
2//!
3//! Re-exported by `winit-main` if `winit-main` is compiled with the `proc`
4/// feature.
5
6use proc_macro::TokenStream;
7use syn::{
8    parse_macro_input,
9    parse_quote,
10};
11use quote::quote;
12
13
14/// Proc-macro around a "simulated main thread" function, which hijacks itself
15/// with `winit_main::run` and spawns the function body in a new thread with
16/// callbacks to communcate with the main thread. 
17///
18/// Input:
19/// ```rust,compile_fail
20/// #[winit_main::main]
21/// fn main(event_loop: EventLoopHandle, events: EventReceiver) {
22///     // stuff goes here
23/// }
24/// ```
25///
26/// Output:
27/// ```rust,compile_fail
28/// fn main() -> ! {
29///     fn _inner(event_loop: EventLoopHandle, events: EventReceiver) {
30///         // stuff goes here
31///     }
32///     ::winit_main::run(_inner)
33/// }
34/// ```
35#[proc_macro_attribute]
36pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
37    let item = parse_macro_input!(item as syn::ItemFn);
38
39    let mut inner_fn = item.clone();
40    inner_fn.sig.ident = parse_quote! { _inner };
41
42    let outer_fn = syn::ItemFn {
43        attrs: item.attrs.clone(),
44        vis: item.vis.clone(),
45        sig: syn::Signature {
46            unsafety: item.sig.unsafety.clone(),
47            ident: item.sig.ident.clone(),
48            generics: item.sig.generics.clone(),
49
50            constness: None,
51            asyncness: None,
52            abi: None,
53            variadic: None,
54            output: parse_quote! { -> ! },
55
56            fn_token: Default::default(),
57            paren_token: Default::default(),
58            inputs: Default::default(),
59        },
60        block: Box::new(parse_quote! {
61            {
62                #inner_fn
63                ::winit_main::run(_inner)
64            }
65        }),
66    };
67
68    (quote! { #outer_fn }).into()
69}