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
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
use crate::def_site;
use pmutil::ToTokensExt;
use proc_macro2::TokenStream;
use quote::ToTokens;
use std::iter;
use syn::{punctuated::Pair, *};

mod generics;

/// Generics of derived impl item.
#[derive(Debug, Clone)]
pub struct Derive<'a> {
    input: &'a DeriveInput,
    out: ItemImpl,
}

impl<'a> Derive<'a> {
    pub fn new(input: &'a DeriveInput) -> Self {
        let (generics, self_ty) = {
            // Generics for impl cannot have default.
            let params = input
                .generics
                .params
                .clone()
                .into_pairs()
                .map(|mut pair| {
                    if let GenericParam::Type(ref mut t) = *pair.value_mut() {
                        t.eq_token = None;
                        t.default = None;
                    }

                    pair
                })
                .collect();

            let generics = Generics {
                params,
                gt_token: input.generics.gt_token,
                lt_token: input.generics.lt_token,
                where_clause: input.generics.where_clause.clone(),
            };

            // Handle generic delcared on type.
            let ty: Box<Type> = {
                let (_, ty_generics, _) = input.generics.split_for_impl();
                let mut t = TokenStream::new();
                input.ident.to_tokens(&mut t);
                ty_generics.to_tokens(&mut t);
                Box::new(parse(t.dump().into()).unwrap_or_else(|err| {
                    panic!("failed to parse type: {}\nType: {}", err, t.dump())
                }))
            };

            (generics, ty)
        };

        Derive {
            input,
            out: ItemImpl {
                attrs: vec![],
                impl_token: def_site(),
                brace_token: def_site(),
                defaultness: None,
                unsafety: None,
                generics,
                trait_: None,
                self_ty,
                items: Default::default(),
            },
        }
    }

    /// Set `defaultness`
    pub fn defaultness(&mut self, defaultness: Option<token::Default>) {
        self.out.defaultness = defaultness;
    }

    /// Set `unsafety`
    pub fn unsafety(&mut self, unsafety: Option<token::Unsafe>) {
        self.out.unsafety = unsafety;
    }
    pub fn input(&self) -> &DeriveInput {
        self.input
    }

    pub fn append_to(mut self, item: ItemImpl) -> ItemImpl {
        assert_eq!(self.out.trait_, None);
        if !self.out.generics.params.empty_or_trailing() {
            self.out.generics.params.push_punct(def_site());
        }

        self.out
            .generics
            .params
            .extend(item.generics.params.into_pairs());

        self.out.trait_ = item.trait_;

        self.out.attrs.extend(item.attrs);
        self.out.items.extend(item.items);

        self.out
    }
}