swc_config_macro/
merge.rs1use proc_macro2::TokenStream;
2use quote::{quote, ToTokens};
3use swc_macros_common::{access_field, join_stmts};
4use syn::{parse_quote, DeriveInput, Expr, Field, Fields, Stmt, Token};
5
6pub fn expand(input: DeriveInput) -> TokenStream {
7 match &input.data {
8 syn::Data::Struct(s) => {
9 let body = call_merge_for_fields("e!(self), &s.fields);
10 let body = join_stmts(&body);
11
12 let ident = &input.ident;
13 parse_quote!(
14 #[automatically_derived]
15 impl swc_config::merge::Merge for #ident {
16 fn merge(&mut self, _other: Self) {
17 #body
18 }
19 }
20 )
21 }
22 syn::Data::Enum(_) => unimplemented!("derive(Merge) does not support an enum"),
23 syn::Data::Union(_) => unimplemented!("derive(Merge) does not support a union"),
24 }
25}
26
27fn call_merge_for_fields(obj: &dyn ToTokens, fields: &Fields) -> Vec<Stmt> {
28 fn call_merge(obj: &dyn ToTokens, idx: usize, f: &Field) -> Expr {
29 let r = quote!(_other);
30
31 let l = access_field(obj, idx, f);
32 let r = access_field(&r, idx, f);
33 parse_quote!(swc_config::merge::Merge::merge(&mut #l, #r))
34 }
35
36 match fields {
37 Fields::Named(fs) => fs
38 .named
39 .iter()
40 .enumerate()
41 .map(|(idx, f)| call_merge(obj, idx, f))
42 .map(|expr| Stmt::Expr(expr, Some(Token))))
43 .collect(),
44 Fields::Unnamed(fs) => fs
45 .unnamed
46 .iter()
47 .enumerate()
48 .map(|(idx, f)| call_merge(obj, idx, f))
49 .map(|expr| Stmt::Expr(expr, Some(Token))))
50 .collect(),
51 Fields::Unit => unimplemented!("derive(Merge) does not support a unit struct"),
52 }
53}