119625d8cSopenharmony_ci// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
219625d8cSopenharmony_ci// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
319625d8cSopenharmony_ci// Ana Hobden (@hoverbear) <operator@hoverbear.org>
419625d8cSopenharmony_ci//
519625d8cSopenharmony_ci// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
619625d8cSopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
719625d8cSopenharmony_ci// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
819625d8cSopenharmony_ci// option. This file may not be copied, modified, or distributed
919625d8cSopenharmony_ci// except according to those terms.
1019625d8cSopenharmony_ci//
1119625d8cSopenharmony_ci// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
1219625d8cSopenharmony_ci// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
1319625d8cSopenharmony_ci// MIT/Apache 2.0 license.
1419625d8cSopenharmony_ci
1519625d8cSopenharmony_ci#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
1619625d8cSopenharmony_ci#![doc = include_str!("../README.md")]
1719625d8cSopenharmony_ci#![forbid(unsafe_code)]
1819625d8cSopenharmony_ci
1919625d8cSopenharmony_ciextern crate proc_macro;
2019625d8cSopenharmony_ci
2119625d8cSopenharmony_ciuse proc_macro::TokenStream;
2219625d8cSopenharmony_ciuse syn::{parse_macro_input, DeriveInput};
2319625d8cSopenharmony_ciuse syn::{Data, DataStruct, Fields};
2419625d8cSopenharmony_ci
2519625d8cSopenharmony_ci#[macro_use]
2619625d8cSopenharmony_cimod macros;
2719625d8cSopenharmony_ci
2819625d8cSopenharmony_cimod attr;
2919625d8cSopenharmony_cimod derives;
3019625d8cSopenharmony_cimod dummies;
3119625d8cSopenharmony_cimod item;
3219625d8cSopenharmony_cimod utils;
3319625d8cSopenharmony_ci
3419625d8cSopenharmony_ci/// Generates the `ValueEnum` impl.
3519625d8cSopenharmony_ci#[proc_macro_derive(ValueEnum, attributes(clap, value))]
3619625d8cSopenharmony_cipub fn value_enum(input: TokenStream) -> TokenStream {
3719625d8cSopenharmony_ci    let input: DeriveInput = parse_macro_input!(input);
3819625d8cSopenharmony_ci    derives::derive_value_enum(&input)
3919625d8cSopenharmony_ci        .unwrap_or_else(|err| {
4019625d8cSopenharmony_ci            let dummy = dummies::value_enum(&input.ident);
4119625d8cSopenharmony_ci            to_compile_error(err, dummy)
4219625d8cSopenharmony_ci        })
4319625d8cSopenharmony_ci        .into()
4419625d8cSopenharmony_ci}
4519625d8cSopenharmony_ci
4619625d8cSopenharmony_ci/// Generates the `Parser` implementation.
4719625d8cSopenharmony_ci///
4819625d8cSopenharmony_ci/// This is far less verbose than defining the `clap::Command` struct manually,
4919625d8cSopenharmony_ci/// receiving an instance of `clap::ArgMatches` from conducting parsing, and then
5019625d8cSopenharmony_ci/// implementing a conversion code to instantiate an instance of the user
5119625d8cSopenharmony_ci/// context struct.
5219625d8cSopenharmony_ci#[proc_macro_derive(Parser, attributes(clap, structopt, command, arg, group))]
5319625d8cSopenharmony_cipub fn parser(input: TokenStream) -> TokenStream {
5419625d8cSopenharmony_ci    let input: DeriveInput = parse_macro_input!(input);
5519625d8cSopenharmony_ci    derives::derive_parser(&input)
5619625d8cSopenharmony_ci        .unwrap_or_else(|err| {
5719625d8cSopenharmony_ci            let specific_dummy = match input.data {
5819625d8cSopenharmony_ci                Data::Struct(DataStruct {
5919625d8cSopenharmony_ci                    fields: Fields::Named(ref _fields),
6019625d8cSopenharmony_ci                    ..
6119625d8cSopenharmony_ci                }) => Some(dummies::args(&input.ident)),
6219625d8cSopenharmony_ci                Data::Struct(DataStruct {
6319625d8cSopenharmony_ci                    fields: Fields::Unit,
6419625d8cSopenharmony_ci                    ..
6519625d8cSopenharmony_ci                }) => Some(dummies::args(&input.ident)),
6619625d8cSopenharmony_ci                Data::Enum(_) => Some(dummies::subcommand(&input.ident)),
6719625d8cSopenharmony_ci                _ => None,
6819625d8cSopenharmony_ci            };
6919625d8cSopenharmony_ci            let dummy = specific_dummy
7019625d8cSopenharmony_ci                .map(|specific_dummy| {
7119625d8cSopenharmony_ci                    let parser_dummy = dummies::parser(&input.ident);
7219625d8cSopenharmony_ci                    quote::quote! {
7319625d8cSopenharmony_ci                        #parser_dummy
7419625d8cSopenharmony_ci                        #specific_dummy
7519625d8cSopenharmony_ci                    }
7619625d8cSopenharmony_ci                })
7719625d8cSopenharmony_ci                .unwrap_or_else(|| quote::quote!());
7819625d8cSopenharmony_ci            to_compile_error(err, dummy)
7919625d8cSopenharmony_ci        })
8019625d8cSopenharmony_ci        .into()
8119625d8cSopenharmony_ci}
8219625d8cSopenharmony_ci
8319625d8cSopenharmony_ci/// Generates the `Subcommand` impl.
8419625d8cSopenharmony_ci#[proc_macro_derive(Subcommand, attributes(clap, command, arg, group))]
8519625d8cSopenharmony_cipub fn subcommand(input: TokenStream) -> TokenStream {
8619625d8cSopenharmony_ci    let input: DeriveInput = parse_macro_input!(input);
8719625d8cSopenharmony_ci    derives::derive_subcommand(&input)
8819625d8cSopenharmony_ci        .unwrap_or_else(|err| {
8919625d8cSopenharmony_ci            let dummy = dummies::subcommand(&input.ident);
9019625d8cSopenharmony_ci            to_compile_error(err, dummy)
9119625d8cSopenharmony_ci        })
9219625d8cSopenharmony_ci        .into()
9319625d8cSopenharmony_ci}
9419625d8cSopenharmony_ci
9519625d8cSopenharmony_ci/// Generates the `Args` impl.
9619625d8cSopenharmony_ci#[proc_macro_derive(Args, attributes(clap, command, arg, group))]
9719625d8cSopenharmony_cipub fn args(input: TokenStream) -> TokenStream {
9819625d8cSopenharmony_ci    let input: DeriveInput = parse_macro_input!(input);
9919625d8cSopenharmony_ci    derives::derive_args(&input)
10019625d8cSopenharmony_ci        .unwrap_or_else(|err| {
10119625d8cSopenharmony_ci            let dummy = dummies::args(&input.ident);
10219625d8cSopenharmony_ci            to_compile_error(err, dummy)
10319625d8cSopenharmony_ci        })
10419625d8cSopenharmony_ci        .into()
10519625d8cSopenharmony_ci}
10619625d8cSopenharmony_ci
10719625d8cSopenharmony_cifn to_compile_error(
10819625d8cSopenharmony_ci    error: syn::Error,
10919625d8cSopenharmony_ci    dummy: proc_macro2::TokenStream,
11019625d8cSopenharmony_ci) -> proc_macro2::TokenStream {
11119625d8cSopenharmony_ci    let compile_errors = error.to_compile_error();
11219625d8cSopenharmony_ci    quote::quote!(
11319625d8cSopenharmony_ci        #dummy
11419625d8cSopenharmony_ci        #compile_errors
11519625d8cSopenharmony_ci    )
11619625d8cSopenharmony_ci}
117