swc_macros_common/
derive.rs

1use std::iter;
2
3use proc_macro2::TokenStream;
4use quote::ToTokens;
5use syn::{punctuated::Pair, *};
6
7use crate::def_site;
8
9mod generics;
10
11/// Generics of derived impl item.
12#[derive(Debug, Clone)]
13pub struct Derive<'a> {
14    input: &'a DeriveInput,
15    out: ItemImpl,
16}
17
18impl<'a> Derive<'a> {
19    pub fn new(input: &'a DeriveInput) -> Self {
20        let (generics, self_ty) = {
21            // Generics for impl cannot have default.
22            let params = input
23                .generics
24                .params
25                .clone()
26                .into_pairs()
27                .map(|mut pair| {
28                    if let GenericParam::Type(ref mut t) = *pair.value_mut() {
29                        t.eq_token = None;
30                        t.default = None;
31                    }
32
33                    pair
34                })
35                .collect();
36
37            let generics = Generics {
38                params,
39                gt_token: input.generics.gt_token,
40                lt_token: input.generics.lt_token,
41                where_clause: input.generics.where_clause.clone(),
42            };
43
44            // Handle generic declared on type.
45            let ty: Box<Type> = {
46                let (_, ty_generics, _) = input.generics.split_for_impl();
47                let mut t = TokenStream::new();
48                input.ident.to_tokens(&mut t);
49                ty_generics.to_tokens(&mut t);
50                Box::new(
51                    parse2(t.into_token_stream())
52                        .unwrap_or_else(|err| panic!("failed to parse type: {}", err)),
53                )
54            };
55
56            (generics, ty)
57        };
58
59        Derive {
60            input,
61            out: ItemImpl {
62                attrs: Vec::new(),
63                impl_token: Token!(impl)(def_site()),
64                brace_token: Default::default(),
65                defaultness: None,
66                unsafety: None,
67                generics,
68                trait_: None,
69                self_ty,
70                items: Default::default(),
71            },
72        }
73    }
74
75    /// Set `defaultness`
76    pub fn defaultness(&mut self, defaultness: Option<token::Default>) {
77        self.out.defaultness = defaultness;
78    }
79
80    /// Set `unsafety`
81    pub fn unsafety(&mut self, unsafety: Option<token::Unsafe>) {
82        self.out.unsafety = unsafety;
83    }
84
85    pub fn input(&self) -> &DeriveInput {
86        self.input
87    }
88
89    pub fn append_to(mut self, item: ItemImpl) -> ItemImpl {
90        assert_eq!(self.out.trait_, None);
91        if !self.out.generics.params.empty_or_trailing() {
92            self.out.generics.params.push_punct(Token![,](def_site()));
93        }
94
95        self.out
96            .generics
97            .params
98            .extend(item.generics.params.into_pairs());
99
100        self.out.trait_ = item.trait_;
101
102        self.out.attrs.extend(item.attrs);
103        self.out.items.extend(item.items);
104
105        self.out
106    }
107}