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