swc_macros_common/
derive.rs1use std::iter;
2
3use proc_macro2::TokenStream;
4use quote::ToTokens;
5use syn::{punctuated::Pair, *};
6
7use crate::def_site;
8
9mod generics;
10
11#[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 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 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 pub fn defaultness(&mut self, defaultness: Option<token::Default>) {
77 self.out.defaultness = defaultness;
78 }
79
80 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));
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}