Skip to main content

fake_main/
lib.rs

1//! The cfg fake main macro.
2
3#![feature(proc_macro_expand)]
4
5extern crate proc_macro;
6use proc_macro::TokenStream;
7
8/// The macro that does what `cfg` does but also injects a fake `fn main` when
9/// the predicate is `false`.
10///
11/// # Usage
12///
13/// ```ignore
14/// # #[allow(clippy::needless_doctest_main)]
15/// #![feature(prelude_import)]
16/// #![feature(custom_inner_attributes)]
17/// #![::fake_main::cfg_(not(feature = "skip"))]
18///
19/// fn main() {
20///    println!("Real fn main");
21/// }
22/// ```
23#[proc_macro_attribute]
24pub fn cfg_(attr: TokenStream, item: TokenStream) -> TokenStream {
25    let attr = proc_macro2::TokenStream::from(attr);
26    let item = proc_macro2::TokenStream::from(item);
27
28    let attr_text = attr.to_string();
29
30    let to_expand: proc_macro2::TokenStream = quote::quote! {
31        ::core::cfg!( #attr )
32    };
33    let to_expand: TokenStream = to_expand.into();
34    let expanded = to_expand.expand_expr().unwrap();
35
36    let enabled = expanded.to_string() == "true";
37
38    if enabled {
39        quote::quote! {
40            #![feature(prelude_import)]
41            #![allow(internal_features)]
42            #![allow(unused_imports)]
43
44            #item
45        }
46        .into()
47    } else {
48        quote::quote! {
49            //! Fake main.
50
51            #![feature(prelude_import)]
52            #![allow(internal_features)]
53            #![allow(missing_docs)]
54
55            #[macro_use]
56            extern crate std;
57
58            #[prelude_import]
59            use std::prelude::v1::*;
60
61            /// Fake main.
62            fn main() {
63                unimplemented!(#attr_text);
64            }
65        }
66        .into()
67    }
68}