aboutsummaryrefslogtreecommitdiff
path: root/derive-macro/src/derives.rs
blob: 3db585860204cbac0c1c9a8bca6afdd28d98d76d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// SPDX-License-Identifier: MIT
// Copyright (c) 2023 Robin Jarry

use proc_macro2::TokenStream;
use proc_macro_error::abort_call_site;
use quote::quote;
use syn::{self, Data, DataStruct, DeriveInput, Field, Fields, Generics, Ident};

use crate::dummies;
use crate::item::Item;

pub fn derive_ini_parse(input: &DeriveInput) -> TokenStream {
    let ident = &input.ident;

    match input.data {
        Data::Struct(DataStruct {
            fields: Fields::Named(ref fields),
            ..
        }) => {
            dummies::ini_parse(ident);

            let item = Item::from_args_struct(input);
            let fields = fields
                .named
                .iter()
                .map(|field| {
                    let item = Item::from_args_field(field);
                    (field, item)
                })
                .collect::<Vec<_>>();
            gen_for_struct(&item, ident, &input.generics, &fields)
        }
        _ => abort_call_site!("`#[derive(IniParse)]` only supports non-tuple structs"),
    }
}

pub fn derive_ini_dump(input: &DeriveInput) -> TokenStream {
    abort_call_site!("`#[derive(IniDump)]` is not implemented")
}

fn gen_for_struct(
    item: &Item,
    name: &Ident,
    generics: &Generics,
    fields: &[(&Field, Item)],
) -> TokenStream {
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

    let into_app = into_app::gen_for_struct(item, name, generics);
    let args = args::gen_for_struct(item, name, generics, fields);

    quote! {
        impl #impl_generics clap::Parser for #name #ty_generics #where_clause {}

        #into_app
        #args
    }
}