@@ -48,16 +48,53 @@ fn is_same_file<P: AsRef<Path>>(file1: P, file2: P) -> Result<bool, std::io::Err
48
48
Ok ( b1 == b2)
49
49
}
50
50
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
+
51
61
#[ derive( Debug ) ]
52
62
enum ActionMeta {
53
63
Struct ,
54
- Enum ( Vec < ( String , String ) > ) ,
64
+ Enum ( Vec < EnumElement > ) ,
55
65
}
56
66
57
67
impl ActionMeta {
58
68
pub fn is_struct ( & self ) -> bool {
59
69
matches ! ( self , Self :: Struct )
60
70
}
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
+ }
61
98
}
62
99
63
100
fn main ( ) -> Result < ( ) , Box < dyn Error > > {
@@ -77,8 +114,10 @@ fn main() -> Result<(), Box<dyn Error>> {
77
114
} ;
78
115
79
116
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 =
81
118
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 ( ) ;
82
121
83
122
let mut use_statements: BTreeMap < Vec < String > , Vec < String > > = Default :: default ( ) ;
84
123
use_statements. insert ( vec ! [ ] , vec ! [ "ActionKindGet" . to_owned( ) ] ) ;
@@ -116,20 +155,45 @@ fn main() -> Result<(), Box<dyn Error>> {
116
155
"enum" => {
117
156
if let Some ( action_name) = matches. get ( 2 ) {
118
157
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 ( ) ;
119
160
let mut variant_lines = vec ! [ ] ;
120
161
loop {
121
162
let Some ( line) = lines. next ( ) else { break } ;
122
163
let line = line. unwrap ( ) ;
123
- if line. contains ( '}' ) {
164
+ if line. ends_with ( '}' ) {
124
165
break ;
125
166
}
126
167
variant_lines. push ( line) ;
127
168
}
128
- let variants_str = variant_lines. join ( "" ) ;
169
+ let variants_str = variant_lines. join ( "\n " ) ;
129
170
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
131
178
. 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 ( )
133
197
. collect ( ) ;
134
198
actions. insert ( action_name. clone ( ) , ActionMeta :: Enum ( variants) ) ;
135
199
action_defs. push ( action_name) ;
@@ -198,9 +262,15 @@ fn main() -> Result<(), Box<dyn Error>> {
198
262
199
263
let action_kinds_iter = actions
200
264
. 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
+ } ) ;
204
274
let action_kinds = std:: iter:: once ( "None" . to_owned ( ) )
205
275
. chain ( action_kinds_iter)
206
276
. collect :: < Vec < _ > > ( ) ;
@@ -237,13 +307,33 @@ fn main() -> Result<(), Box<dyn Error>> {
237
307
format ! ( "ActionKind::{action_kind}" )
238
308
}
239
309
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
+ }
242
314
}
243
315
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
+ } ) ;
247
337
std:: iter:: once ( "match self {" . to_owned ( ) )
248
338
. chain ( variants_iter)
249
339
. chain ( std:: iter:: once ( " }" . to_owned ( ) ) )
0 commit comments