@@ -4,13 +4,14 @@ extern crate syn;
4
4
5
5
use proc_macro2:: TokenStream ;
6
6
use synstructure:: Structure ;
7
- use syn:: { Fields , Meta , NestedMeta , Lit , Path , parse_str} ;
7
+ use syn:: { Fields , Meta , NestedMeta , Lit , Path , Ident , parse_str} ;
8
8
9
9
decl_derive ! ( [ CustomDebug , attributes( debug) ] => custom_debug_derive) ;
10
10
11
11
fn custom_debug_derive ( s : Structure ) -> TokenStream {
12
12
let name = s. ast ( ) . ident . to_string ( ) ;
13
- let debug_attr = parse_str ( "debug" ) . unwrap ( ) ;
13
+ let debug_attr = parse_str :: < Path > ( "debug" ) . unwrap ( ) ;
14
+ let skip_ident = parse_str :: < Ident > ( "skip" ) . unwrap ( ) ;
14
15
15
16
let variants = s. each_variant ( |variant| {
16
17
let debug_helper = match variant. ast ( ) . fields {
@@ -22,48 +23,52 @@ fn custom_debug_derive(s: Structure) -> TokenStream {
22
23
let variant_body = variant. bindings ( ) . iter ( ) . map ( |b| {
23
24
let mut format = None ;
24
25
25
- b. ast ( ) . attrs . iter ( )
26
+ let metas = b. ast ( ) . attrs . iter ( )
26
27
. filter ( |attr| attr. path == debug_attr)
27
28
. flat_map ( |attr| attr. interpret_meta ( ) )
28
29
. flat_map ( |meta| match meta {
29
30
Meta :: List ( list) => list. nested ,
30
31
_ => panic ! ( "Invalid debug attribute" ) ,
31
- } )
32
- . for_each ( |meta| match meta {
33
- NestedMeta :: Meta ( Meta :: NameValue ( nv) ) => {
34
- let value = nv. lit ;
35
- format = Some ( match & * nv. ident . to_string ( ) {
36
- "format" => quote ! { & format_args!( #value, #b) } ,
37
- "with" => match value {
38
- Lit :: Str ( fun) => {
39
- let fun = fun. parse :: < Path > ( ) . unwrap ( ) ;
40
- quote ! {
41
- & {
42
- struct DebugWith <' a, T : ' a> {
43
- data: & ' a T ,
44
- fmt: fn ( & T , & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result ,
45
- }
32
+ } ) ;
46
33
47
- impl <' a, T : ' a> :: std:: fmt:: Debug for DebugWith <' a, T > {
48
- fn fmt( & self , f: & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result {
49
- ( self . fmt) ( self . data, f)
34
+ for meta in metas {
35
+ match meta {
36
+ NestedMeta :: Meta ( Meta :: Word ( ref ident) ) if ident == & skip_ident => return quote ! { } ,
37
+ NestedMeta :: Meta ( Meta :: NameValue ( nv) ) => {
38
+ let value = nv. lit ;
39
+ format = Some ( match & * nv. ident . to_string ( ) {
40
+ "format" => quote ! { & format_args!( #value, #b) } ,
41
+ "with" => match value {
42
+ Lit :: Str ( fun) => {
43
+ let fun = fun. parse :: < Path > ( ) . unwrap ( ) ;
44
+ quote ! {
45
+ & {
46
+ struct DebugWith <' a, T : ' a> {
47
+ data: & ' a T ,
48
+ fmt: fn ( & T , & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result ,
49
+ }
50
+
51
+ impl <' a, T : ' a> :: std:: fmt:: Debug for DebugWith <' a, T > {
52
+ fn fmt( & self , f: & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result {
53
+ ( self . fmt) ( self . data, f)
54
+ }
50
55
}
51
- }
52
56
53
- DebugWith {
54
- data: #b,
55
- fmt: #fun,
57
+ DebugWith {
58
+ data: #b,
59
+ fmt: #fun,
60
+ }
56
61
}
57
62
}
58
- }
63
+ } ,
64
+ _ => panic ! ( "Invalid 'with' value" ) ,
59
65
} ,
60
- _ => panic ! ( "Invalid 'with' value" ) ,
61
- } ,
62
- name => panic ! ( "Unknown key '{}'" , name) ,
63
- } )
64
- } ,
65
- _ => panic ! ( "Invalid debug attribute" ) ,
66
- } ) ;
66
+ name => panic ! ( "Unknown key '{}'" , name) ,
67
+ } )
68
+ } ,
69
+ _ => panic ! ( "Invalid debug attribute" ) ,
70
+ }
71
+ }
67
72
68
73
let format = format. unwrap_or_else ( || quote ! { #b } ) ;
69
74
@@ -208,6 +213,39 @@ fn test_with() {
208
213
}
209
214
}
210
215
216
+ #[ test]
217
+ fn test_skip ( ) {
218
+ test_derive ! {
219
+ custom_debug_derive {
220
+ struct Point {
221
+ x: f32 ,
222
+ #[ debug( skip) ]
223
+ y: f32 ,
224
+ z: f32 ,
225
+ }
226
+ }
227
+
228
+ expands to {
229
+ #[ allow( non_upper_case_globals) ]
230
+ const _DERIVE_std_fmt_Debug_FOR_Point: ( ) = {
231
+ impl :: std:: fmt:: Debug for Point {
232
+ fn fmt( & self , f: & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result {
233
+ match self {
234
+ Point { x: ref __binding_0, y: ref __binding_1, z: ref __binding_2, } => {
235
+ let mut s = f. debug_struct( "Point" ) ;
236
+ s. field( "x" , __binding_0) ;
237
+ s. field( "z" , __binding_2) ;
238
+ s. finish( )
239
+ }
240
+ }
241
+ }
242
+ }
243
+ } ;
244
+ }
245
+
246
+ no_build
247
+ }
248
+ }
211
249
212
250
#[ test]
213
251
fn test_enum ( ) {
0 commit comments