debate_derive/
lib.rs

1mod common;
2mod from_args;
3mod generics;
4mod main_func;
5mod usage;
6mod value;
7
8use proc_macro::TokenStream;
9use proc_macro2::TokenStream as TokenStream2;
10
11macro_rules! proc_macro_definition {
12    (
13        derive($Trait:ident) attributes($($attrs:tt)*)
14        pub fn $local_fn_name:ident => $implementation:path;
15    ) => {
16        #[proc_macro_derive($Trait, attributes($($attrs)*))]
17        pub fn $local_fn_name(item: TokenStream) -> TokenStream {
18            let item: TokenStream2 = item.into();
19            let result: syn::Result<TokenStream2> = $implementation(item);
20            match result {
21                Ok(tokens) => tokens.into(),
22                Err(err) => err.to_compile_error().into(),
23            }
24        }
25    }
26}
27
28// TODO: separate `BuildFromArgs` and `Usage` derive, with `FromArgs` covering
29// both
30
31proc_macro_definition! {
32    derive(FromArgs) attributes(debate)
33    pub fn derive_args => from_args::derive_args_result;
34}
35
36proc_macro_definition! {
37    derive(Value) attributes(debate)
38    pub fn derive_value => value::derive_value_result;
39}
40
41proc_macro_definition! {
42    derive(Usage) attributes(debate, doc)
43    pub fn derive_usage => usage::derive_usage_result;
44}
45
46proc_macro_definition! {
47    derive(ParameterUsage) attributes()
48    pub fn derive_parameter_usage => usage::value::derive_parameter_usage_result;
49}
50
51/*
52    fn main(args: Args) -> Foo {
53        $BODY
54    }
55
56    becomes
57
58    fn main() {
59        let args = LoadedArguments::from_env();
60        let args: Args = args.parse();
61
62        $BODY
63    }
64*/
65
66// TODO: reuse the macro from above, it's close enough.
67/// Decorate an `fn main` to inject the command line arguments as a type.
68#[proc_macro_attribute]
69pub fn main(attrs: TokenStream, item: TokenStream) -> TokenStream {
70    match main_func::decorate_fn_main(attrs.into(), item.into()) {
71        Ok(tokens) => tokens,
72        Err(err) => err.to_compile_error(),
73    }
74    .into()
75}