11use itertools:: Itertools ;
22use proc_macro2:: { Ident , Span , TokenStream } ;
33use quote:: quote;
4- use syn:: { Expr , FieldsNamed , FieldsUnnamed , Result , Type } ;
4+ use std:: collections:: HashMap ;
5+ use syn:: punctuated:: Punctuated ;
6+ use syn:: visit_mut:: VisitMut ;
7+ use syn:: { Expr , FieldsNamed , FieldsUnnamed , Path , Result , Type } ;
58
69pub enum Field {
710 Default { name : Ident , ty : Type } ,
@@ -95,29 +98,48 @@ impl Field {
9598 }
9699 }
97100
98- pub fn generate_derived_expression ( & self ) -> Option < TokenStream > {
101+ pub fn generate_derived_expression ( & self , fields : & Fields ) -> Option < TokenStream > {
99102 match self {
100103 Field :: Default { .. } => None ,
101- Field :: Derived { name, expr, ty } => Some ( quote ! {
102- let #name: #ty = #expr;
103- } ) ,
104+ Field :: Derived { expr, ty, .. } => {
105+ let name = self . get_param_name ( ) ;
106+ let mut expr = expr. clone ( ) ;
107+ fields. rename_derive_expr ( & mut expr) ;
108+ Some ( quote ! {
109+ let #name: #ty = #expr;
110+ } )
111+ }
104112 }
105113 }
114+
115+ pub fn get_param_name ( & self ) -> Ident {
116+ Ident :: new ( & format ! ( "param_{}" , self . get_name( ) ) , Span :: call_site ( ) )
117+ }
106118}
107119
108120impl Fields {
109- pub fn get_all_names ( & self ) -> Vec < Ident > {
110- self . fields
111- . iter ( )
112- . map ( |field| field. get_name ( ) . clone ( ) )
113- . collect ( )
121+ pub fn get_creation_names ( & self ) -> Vec < TokenStream > {
122+ let transform = if self . is_named {
123+ |field : & Field | {
124+ let name = field. get_name ( ) ;
125+ let param_name = field. get_param_name ( ) ;
126+ quote ! { #name: #param_name }
127+ }
128+ } else {
129+ |field : & Field | {
130+ let name = field. get_param_name ( ) ;
131+ quote ! { #name }
132+ }
133+ } ;
134+
135+ self . fields . iter ( ) . map ( transform) . collect ( )
114136 }
115137
116138 pub fn get_expression_names ( & self ) -> Vec < Ident > {
117139 self . fields
118140 . iter ( )
119141 . filter ( |field| !matches ! ( field, Field :: Derived { .. } ) )
120- . map ( |field| field . get_name ( ) . clone ( ) )
142+ . map ( Field :: get_param_name )
121143 . collect ( )
122144 }
123145
@@ -132,31 +154,59 @@ impl Fields {
132154 pub fn get_derived_expressions ( & self ) -> Vec < TokenStream > {
133155 self . fields
134156 . iter ( )
135- . filter_map ( |field| field. generate_derived_expression ( ) )
157+ . filter_map ( |field| field. generate_derived_expression ( self ) )
136158 . collect ( )
137159 }
138160
139161 pub fn create_instance_expr ( & self , variant_name : Option < & Ident > ) -> TokenStream {
140- let all_names = self . get_all_names ( ) ;
162+ let creation_names = self . get_creation_names ( ) ;
141163
142- if all_names . is_empty ( ) {
143- if let Some ( name ) = variant_name {
144- quote ! { Self :: #name }
164+ if creation_names . is_empty ( ) {
165+ if let Some ( variant ) = variant_name {
166+ quote ! { Self :: #variant }
145167 } else {
146168 quote ! { Self }
147169 }
148- } else if let Some ( name ) = variant_name {
170+ } else if let Some ( variant ) = variant_name {
149171 if self . is_named {
150- quote ! { Self :: #name { #( #all_names ) , * } }
172+ quote ! { Self :: #variant { #( #creation_names ) , * } }
151173 } else {
152- quote ! { Self :: #name ( #( #all_names ) , * ) }
174+ quote ! { Self :: #variant ( #( #creation_names ) , * ) }
153175 }
154176 } else {
155177 if self . is_named {
156- quote ! { Self { #( #all_names ) , * } }
178+ quote ! { Self { #( #creation_names ) , * } }
157179 } else {
158- quote ! { Self ( #( #all_names) , * ) }
180+ quote ! { Self ( #( #creation_names) , * ) }
181+ }
182+ }
183+ }
184+
185+ fn rename_derive_expr ( & self , expr : & mut Expr ) {
186+ struct RenameDerived ( HashMap < Ident , Ident > ) ;
187+ impl VisitMut for RenameDerived {
188+ fn visit_path_mut ( & mut self , path : & mut Path ) {
189+ eprintln ! ( "visit_path_mut: {:#?}" , path) ;
190+
191+ for ( source, target) in & self . 0 {
192+ if path. is_ident ( source) {
193+ path. segments = Punctuated :: new ( ) ;
194+ path. segments . push ( syn:: PathSegment {
195+ ident : target. clone ( ) ,
196+ arguments : Default :: default ( ) ,
197+ } ) ;
198+ }
199+ }
159200 }
160201 }
202+
203+ let mapping = self
204+ . fields
205+ . iter ( )
206+ . filter ( |field| !matches ! ( field, Field :: Derived { .. } ) )
207+ . map ( |field| ( field. get_name ( ) . clone ( ) , field. get_param_name ( ) ) )
208+ . collect ( ) ;
209+
210+ RenameDerived ( mapping) . visit_expr_mut ( expr)
161211 }
162212}
0 commit comments