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}