derive_more_impl/
constructor.rs1use crate::utils::{
2 field_idents, get_field_types, named_to_vec, numbered_vars, unnamed_to_vec,
3};
4use proc_macro2::TokenStream;
5use quote::quote;
6use syn::{Data, DeriveInput, Field, Fields, Ident};
7
8pub fn expand(input: &DeriveInput, _: &str) -> TokenStream {
10 let input_type = &input.ident;
11 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
12 let ((body, vars), fields) = match input.data {
13 Data::Struct(ref data_struct) => match data_struct.fields {
14 Fields::Unnamed(ref fields) => {
15 let field_vec = unnamed_to_vec(fields);
16 (tuple_body(input_type, &field_vec), field_vec)
17 }
18 Fields::Named(ref fields) => {
19 let field_vec = named_to_vec(fields);
20 (struct_body(input_type, &field_vec), field_vec)
21 }
22 Fields::Unit => (struct_body(input_type, &[]), vec![]),
23 },
24 _ => panic!("Only structs can derive a constructor"),
25 };
26 let original_types = &get_field_types(&fields);
27 quote! {
28 #[allow(missing_docs)]
29 #[allow(unreachable_code)] #[automatically_derived]
31 impl #impl_generics #input_type #ty_generics #where_clause {
32 #[inline]
33 pub const fn new(#(#vars: #original_types),*) -> #input_type #ty_generics {
34 #body
35 }
36 }
37 }
38}
39
40fn tuple_body(return_type: &Ident, fields: &[&Field]) -> (TokenStream, Vec<Ident>) {
41 let vars = &numbered_vars(fields.len(), "");
42 (quote! { #return_type(#(#vars),*) }, vars.clone())
43}
44
45fn struct_body(return_type: &Ident, fields: &[&Field]) -> (TokenStream, Vec<Ident>) {
46 let field_names: &Vec<Ident> =
47 &field_idents(fields).iter().map(|f| (**f).clone()).collect();
48 let vars = field_names;
49 let ret_vars = field_names.clone();
50 (quote! { #return_type{#(#field_names: #vars),*} }, ret_vars)
51}