| 1 | use crate::add_helpers::{struct_exprs, tuple_exprs}; |
| 2 | use crate::utils::{add_extra_ty_param_bound_op, named_to_vec, unnamed_to_vec}; |
| 3 | use proc_macro2::TokenStream; |
| 4 | use quote::{format_ident, quote}; |
| 5 | use syn::{Data, DeriveInput, Fields}; |
| 6 | |
| 7 | pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { |
| 8 | let trait_ident = format_ident!(" {trait_name}" ); |
| 9 | let method_name = trait_name.trim_end_matches("Assign" ).to_lowercase(); |
| 10 | let method_ident = format_ident!(" {method_name}_assign" ); |
| 11 | let input_type = &input.ident; |
| 12 | |
| 13 | let generics = add_extra_ty_param_bound_op(&input.generics, &trait_ident); |
| 14 | let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); |
| 15 | |
| 16 | let exprs = match input.data { |
| 17 | Data::Struct(ref data_struct) => match data_struct.fields { |
| 18 | Fields::Unnamed(ref fields) => { |
| 19 | tuple_exprs(&unnamed_to_vec(fields), &method_ident) |
| 20 | } |
| 21 | Fields::Named(ref fields) => { |
| 22 | struct_exprs(&named_to_vec(fields), &method_ident) |
| 23 | } |
| 24 | _ => panic!("Unit structs cannot use derive( {trait_name})" ), |
| 25 | }, |
| 26 | |
| 27 | _ => panic!("Only structs can use derive( {trait_name})" ), |
| 28 | }; |
| 29 | |
| 30 | quote! { |
| 31 | #[automatically_derived] |
| 32 | impl #impl_generics derive_more::core::ops::#trait_ident |
| 33 | for #input_type #ty_generics #where_clause { |
| 34 | #[inline] |
| 35 | #[track_caller] |
| 36 | fn #method_ident(&mut self, rhs: #input_type #ty_generics) { |
| 37 | #( #exprs; )* |
| 38 | } |
| 39 | } |
| 40 | } |
| 41 | } |
| 42 | |