@@ -48,16 +48,53 @@ fn is_same_file<P: AsRef<Path>>(file1: P, file2: P) -> Result<bool, std::io::Err
4848 Ok ( b1 == b2)
4949}
5050
51+ #[ derive( Debug , Clone ) ]
52+ enum EnumElement {
53+ InlineFields {
54+ tag : String ,
55+ action_kind : String ,
56+ has_fields : bool ,
57+ } ,
58+ Nested ( ( String , String ) ) ,
59+ }
60+
5161#[ derive( Debug ) ]
5262enum ActionMeta {
5363 Struct ,
54- Enum ( Vec < ( String , String ) > ) ,
64+ Enum ( Vec < EnumElement > ) ,
5565}
5666
5767impl ActionMeta {
5868 pub fn is_struct ( & self ) -> bool {
5969 matches ! ( self , Self :: Struct )
6070 }
71+
72+ pub fn is_inlined ( & self ) -> bool {
73+ if let Self :: Enum ( fields) = self {
74+ fields
75+ . iter ( )
76+ . any ( |field| matches ! ( field, EnumElement :: InlineFields { .. } ) )
77+ } else {
78+ false
79+ }
80+ }
81+
82+ pub fn action_kinds ( & self ) -> Vec < String > {
83+ match self {
84+ Self :: Struct => vec ! [ ] ,
85+ Self :: Enum ( elts) => {
86+ let mut action_kinds = elts
87+ . iter ( )
88+ . filter_map ( |elt| match elt {
89+ EnumElement :: Nested ( _) => None ,
90+ EnumElement :: InlineFields { action_kind, .. } => Some ( action_kind. clone ( ) ) ,
91+ } )
92+ . collect :: < Vec < _ > > ( ) ;
93+ action_kinds. sort ( ) ;
94+ action_kinds
95+ }
96+ }
97+ }
6198}
6299
63100fn main ( ) -> Result < ( ) , Box < dyn Error > > {
@@ -77,8 +114,10 @@ fn main() -> Result<(), Box<dyn Error>> {
77114 } ;
78115
79116 let action_def_re = Regex :: new ( r"^pub (struct|enum) ([a-zA-Z0-9]*Action)( |\n)\{" ) . unwrap ( ) ;
80- let action_enum_variant_re =
117+ let action_enum_variant_nested_re =
81118 Regex :: new ( r"([a-zA-Z0-9]*)\(\n? *([a-zA-Z0-9]*Action),?\n? *\)" ) . unwrap ( ) ;
119+ let action_enum_variant_inline_re =
120+ Regex :: new ( r"(?m)^\s*([A-Z][a-zA-Z0-9]+)(\s*\{[^}]*\})?," ) . unwrap ( ) ;
82121
83122 let mut use_statements: BTreeMap < Vec < String > , Vec < String > > = Default :: default ( ) ;
84123 use_statements. insert ( vec ! [ ] , vec ! [ "ActionKindGet" . to_owned( ) ] ) ;
@@ -116,20 +155,45 @@ fn main() -> Result<(), Box<dyn Error>> {
116155 "enum" => {
117156 if let Some ( action_name) = matches. get ( 2 ) {
118157 let action_name = action_name. as_str ( ) . to_owned ( ) ;
158+ // Without 'Action' suffix
159+ let action_name_base = action_name[ ..( action_name. len ( ) - 6 ) ] . to_string ( ) ;
119160 let mut variant_lines = vec ! [ ] ;
120161 loop {
121162 let Some ( line) = lines. next ( ) else { break } ;
122163 let line = line. unwrap ( ) ;
123- if line. contains ( '}' ) {
164+ if line. ends_with ( '}' ) {
124165 break ;
125166 }
126167 variant_lines. push ( line) ;
127168 }
128- let variants_str = variant_lines. join ( "" ) ;
169+ let variants_str = variant_lines. join ( "\n " ) ;
129170
130- let variants = action_enum_variant_re
171+ let variants_nested = action_enum_variant_nested_re
172+ . captures_iter ( & variants_str)
173+ . map ( |matches| {
174+ EnumElement :: Nested ( ( matches[ 1 ] . to_owned ( ) , matches[ 2 ] . to_owned ( ) ) )
175+ } )
176+ . collect :: < Vec < _ > > ( ) ;
177+ let variants_inlined = action_enum_variant_inline_re
131178 . captures_iter ( & variants_str)
132- . map ( |matches| ( matches[ 1 ] . to_owned ( ) , matches[ 2 ] . to_owned ( ) ) )
179+ . filter_map ( |matches| {
180+ let tag = matches[ 1 ] . to_owned ( ) ;
181+ if tag. ends_with ( "Action" ) {
182+ None
183+ } else {
184+ let action_kind = format ! ( "{action_name_base}{tag}" ) ;
185+ Some ( EnumElement :: InlineFields {
186+ tag,
187+ action_kind,
188+ has_fields : matches. get ( 2 ) . is_some ( ) ,
189+ } )
190+ }
191+ } )
192+ . collect :: < Vec < _ > > ( ) ;
193+ let variants = variants_nested
194+ . iter ( )
195+ . chain ( variants_inlined. iter ( ) )
196+ . cloned ( )
133197 . collect ( ) ;
134198 actions. insert ( action_name. clone ( ) , ActionMeta :: Enum ( variants) ) ;
135199 action_defs. push ( action_name) ;
@@ -198,9 +262,15 @@ fn main() -> Result<(), Box<dyn Error>> {
198262
199263 let action_kinds_iter = actions
200264 . iter ( )
201- . filter ( |( _, meta) | meta. is_struct ( ) )
202- // Remove suffix `Action` from action name.
203- . map ( |( name, _) | name[ ..( name. len ( ) - 6 ) ] . to_string ( ) ) ;
265+ . filter ( |( _, meta) | meta. is_struct ( ) || meta. is_inlined ( ) )
266+ . flat_map ( |( name, meta) | {
267+ if meta. is_inlined ( ) {
268+ meta. action_kinds ( )
269+ } else {
270+ // Remove suffix `Action` from action name.
271+ vec ! [ name[ ..( name. len( ) - 6 ) ] . to_string( ) ]
272+ }
273+ } ) ;
204274 let action_kinds = std:: iter:: once ( "None" . to_owned ( ) )
205275 . chain ( action_kinds_iter)
206276 . collect :: < Vec < _ > > ( ) ;
@@ -237,13 +307,33 @@ fn main() -> Result<(), Box<dyn Error>> {
237307 format ! ( "ActionKind::{action_kind}" )
238308 }
239309 ActionMeta :: Enum ( variants) => {
240- for ( _, a) in variants {
241- queue. push_back ( a. clone ( ) ) ;
310+ for elt in variants {
311+ if let EnumElement :: Nested ( ( _, a) ) = elt {
312+ queue. push_back ( a. clone ( ) ) ;
313+ }
242314 }
243315
244- let variants_iter = variants
245- . iter ( )
246- . map ( |( v, _) | format ! ( " Self::{v}(a) => a.kind()," ) ) ;
316+ let variants_iter = variants. iter ( ) . map ( |elt| match elt {
317+ EnumElement :: Nested ( ( v, _) ) => {
318+ format ! ( " Self::{v}(a) => a.kind()," )
319+ }
320+ EnumElement :: InlineFields {
321+ tag,
322+ action_kind,
323+ has_fields : true ,
324+ } => {
325+ format ! (
326+ " Self::{tag} {{ .. }} => ActionKind::{action_kind},"
327+ )
328+ }
329+ EnumElement :: InlineFields {
330+ tag,
331+ action_kind,
332+ has_fields : false ,
333+ } => {
334+ format ! ( " Self::{tag} => ActionKind::{action_kind}," )
335+ }
336+ } ) ;
247337 std:: iter:: once ( "match self {" . to_owned ( ) )
248338 . chain ( variants_iter)
249339 . chain ( std:: iter:: once ( " }" . to_owned ( ) ) )
0 commit comments