@@ -3,8 +3,8 @@ use quote::ToTokens;
33use rustc_hash:: FxHashMap ;
44use syn:: {
55 punctuated:: Punctuated , token:: Comma , AttrStyle , Attribute , Expr , ExprLit , Field , Fields ,
6- GenericArgument , Generics , Ident , ItemEnum , ItemStruct , Lit , Meta , PathArguments , PathSegment ,
7- Type , TypePath , TypeReference , Variant , Visibility as SynVisibility ,
6+ GenericArgument , Generics , Ident , ItemEnum , ItemStruct , Lit , Meta , MetaList , PathArguments ,
7+ PathSegment , Type , TypePath , TypeReference , Variant , Visibility as SynVisibility ,
88} ;
99
1010use crate :: {
@@ -17,7 +17,7 @@ use crate::{
1717} ;
1818
1919use super :: {
20- attr:: { AttrLocation , AttrPart , AttrPositions , AttrProcessor } ,
20+ attr:: { AttrLocation , AttrPart , AttrPartListElement , AttrPositions , AttrProcessor } ,
2121 ident_name,
2222 skeleton:: { EnumSkeleton , Skeleton , StructSkeleton } ,
2323 Derives , FxIndexMap , FxIndexSet ,
@@ -707,23 +707,24 @@ fn process_attr(
707707 AttrPart :: Tag ( & part_name) ,
708708 ) ?;
709709 }
710- Meta :: List ( meta_list) => {
711- let part_name = meta_list. path . get_ident ( ) . ok_or ( ( ) ) ?. to_string ( ) ;
710+ Meta :: NameValue ( name_value) => {
711+ let part_name = name_value. path . get_ident ( ) . ok_or ( ( ) ) ?. to_string ( ) ;
712+ let str = convert_expr_to_string ( & name_value. value ) ;
712713 process_attr_part (
713714 processor,
714715 attr_name,
715716 location. unpack ( ) ,
716- AttrPart :: List ( & part_name, meta_list ) ,
717+ AttrPart :: String ( & part_name, str ) ,
717718 ) ?;
718719 }
719- Meta :: NameValue ( name_value ) => {
720- let part_name = name_value . path . get_ident ( ) . ok_or ( ( ) ) ?. to_string ( ) ;
721- let str = convert_expr_to_string ( & name_value . value ) ;
720+ Meta :: List ( meta_list ) => {
721+ let part_name = meta_list . path . get_ident ( ) . ok_or ( ( ) ) ?. to_string ( ) ;
722+ let list = parse_attr_part_list ( meta_list ) ? ;
722723 process_attr_part (
723724 processor,
724725 attr_name,
725726 location. unpack ( ) ,
726- AttrPart :: String ( & part_name, str ) ,
727+ AttrPart :: List ( & part_name, list ) ,
727728 ) ?;
728729 }
729730 } ;
@@ -734,12 +735,34 @@ fn process_attr(
734735 }
735736}
736737
738+ fn parse_attr_part_list ( meta_list : & MetaList ) -> Result < Vec < AttrPartListElement > > {
739+ let metas =
740+ meta_list. parse_args_with ( Punctuated :: < Meta , Comma > :: parse_terminated) . map_err ( |_| ( ) ) ?;
741+ metas
742+ . into_iter ( )
743+ . map ( |meta| match meta {
744+ Meta :: Path ( path) => {
745+ let part_name = path. get_ident ( ) . ok_or ( ( ) ) ?. to_string ( ) ;
746+ Ok ( AttrPartListElement :: Tag ( part_name) )
747+ }
748+ Meta :: NameValue ( name_value) => {
749+ let part_name = name_value. path . get_ident ( ) . ok_or ( ( ) ) ?. to_string ( ) ;
750+ let str = convert_expr_to_string ( & name_value. value ) ;
751+ Ok ( AttrPartListElement :: String ( part_name, str) )
752+ }
753+ Meta :: List ( meta_list) => {
754+ let part_name = meta_list. path . get_ident ( ) . ok_or ( ( ) ) ?. to_string ( ) ;
755+ let list = parse_attr_part_list ( & meta_list) ?;
756+ Ok ( AttrPartListElement :: List ( part_name, list) )
757+ }
758+ } )
759+ . collect ( )
760+ }
761+
737762/// Convert an [`Expr`] to a string.
738763///
739764/// If the `Expr` is a string literal, get the value of the string.
740765/// Otherwise print the `Expr` as a string.
741- ///
742- /// This function is also used in `Visit` generator.
743766pub fn convert_expr_to_string ( expr : & Expr ) -> String {
744767 if let Expr :: Lit ( ExprLit { lit : Lit :: Str ( s) , .. } ) = expr {
745768 s. value ( )
0 commit comments