@@ -127,6 +127,10 @@ impl Parse for Config {
127127 opts. additional_derive_ignore =
128128 list. into_iter ( ) . map ( |i| i. value ( ) ) . collect ( )
129129 }
130+ Opt :: AdditionalTypeAttributes ( list) => opts. additional_type_attributes = list,
131+ Opt :: AdditionalMemberAttributes ( list) => {
132+ opts. additional_member_attributes = list
133+ }
130134 Opt :: With ( with) => opts. with . extend ( with) ,
131135 Opt :: GenerateAll => {
132136 opts. generate_all = true ;
@@ -237,7 +241,7 @@ fn parse_source(
237241 }
238242 }
239243 }
240- pkgs. truncate ( 0 ) ;
244+ pkgs. clear ( ) ;
241245 pkgs. push ( resolve. push_str ( "macro-input" , s) ?) ;
242246 }
243247 Some ( Source :: Paths ( p) ) => parse ( p) ?,
@@ -312,6 +316,8 @@ mod kw {
312316 syn:: custom_keyword!( export_prefix) ;
313317 syn:: custom_keyword!( additional_derives) ;
314318 syn:: custom_keyword!( additional_derives_ignore) ;
319+ syn:: custom_keyword!( additional_type_attributes) ;
320+ syn:: custom_keyword!( additional_member_attributes) ;
315321 syn:: custom_keyword!( with) ;
316322 syn:: custom_keyword!( generate_all) ;
317323 syn:: custom_keyword!( type_section_suffix) ;
@@ -394,6 +400,8 @@ enum Opt {
394400 // Parse as paths so we can take the concrete types/macro names rather than raw strings
395401 AdditionalDerives ( Vec < syn:: Path > ) ,
396402 AdditionalDerivesIgnore ( Vec < syn:: LitStr > ) ,
403+ AdditionalTypeAttributes ( Vec < ( String , String ) > ) ,
404+ AdditionalMemberAttributes ( Vec < ( String , String ) > ) ,
397405 With ( HashMap < String , WithOption > ) ,
398406 GenerateAll ,
399407 TypeSectionSuffix ( syn:: LitStr ) ,
@@ -522,6 +530,26 @@ impl Parse for Opt {
522530 syn:: bracketed!( contents in input) ;
523531 let list = Punctuated :: < _ , Token ! [ , ] > :: parse_terminated ( & contents) ?;
524532 Ok ( Opt :: AdditionalDerivesIgnore ( list. iter ( ) . cloned ( ) . collect ( ) ) )
533+ } else if l. peek ( kw:: additional_type_attributes) {
534+ input. parse :: < kw:: additional_type_attributes > ( ) ?;
535+ input. parse :: < Token ! [ : ] > ( ) ?;
536+ let contents;
537+ braced ! ( contents in input) ;
538+ let fields: Punctuated < _ , Token ! [ , ] > =
539+ contents. parse_terminated ( attr_map_field_parse, Token ! [ , ] ) ?;
540+ Ok ( Opt :: AdditionalTypeAttributes (
541+ fields. into_iter ( ) . flatten ( ) . collect ( ) ,
542+ ) )
543+ } else if l. peek ( kw:: additional_member_attributes) {
544+ input. parse :: < kw:: additional_member_attributes > ( ) ?;
545+ input. parse :: < Token ! [ : ] > ( ) ?;
546+ let contents;
547+ braced ! ( contents in input) ;
548+ let fields: Punctuated < _ , Token ! [ , ] > =
549+ contents. parse_terminated ( attr_map_field_parse, Token ! [ , ] ) ?;
550+ Ok ( Opt :: AdditionalMemberAttributes (
551+ fields. into_iter ( ) . flatten ( ) . collect ( ) ,
552+ ) )
525553 } else if l. peek ( kw:: with) {
526554 input. parse :: < kw:: with > ( ) ?;
527555 input. parse :: < Token ! [ : ] > ( ) ?;
@@ -601,6 +629,29 @@ impl Parse for Opt {
601629 }
602630}
603631
632+ // Parse one `"selector": ["#[attr]", ...]` entry into a (selector, attribute) pair
633+ // per attribute.
634+ fn attr_map_field_parse ( input : ParseStream < ' _ > ) -> Result < Vec < ( String , String ) > > {
635+ let selector = input. parse :: < syn:: LitStr > ( ) ?;
636+ input. parse :: < Token ! [ : ] > ( ) ?;
637+ let contents;
638+ let bracket = syn:: bracketed!( contents in input) ;
639+ let attrs = Punctuated :: < syn:: LitStr , Token ! [ , ] > :: parse_terminated ( & contents) ?;
640+ // An empty list would otherwise flatten away silently and escape the
641+ // unused-selector check in the generator.
642+ if attrs. is_empty ( ) {
643+ return Err ( Error :: new (
644+ bracket. span . join ( ) ,
645+ "attribute list must not be empty" ,
646+ ) ) ;
647+ }
648+ let selector = selector. value ( ) ;
649+ Ok ( attrs
650+ . into_iter ( )
651+ . map ( |a| ( selector. clone ( ) , a. value ( ) ) )
652+ . collect ( ) )
653+ }
654+
604655fn with_field_parse ( input : ParseStream < ' _ > ) -> Result < ( String , WithOption ) > {
605656 let interface = input. parse :: < syn:: LitStr > ( ) ?. value ( ) ;
606657 input. parse :: < Token ! [ : ] > ( ) ?;
0 commit comments