@@ -67,7 +67,7 @@ void main(List<String> arguments) {
67
67
printUsage (argParser);
68
68
return ;
69
69
}
70
-
70
+
71
71
// check if file exists
72
72
String rfwPath = results.arguments[0 ];
73
73
File rfwFile = File (rfwPath);
@@ -81,11 +81,123 @@ void main(List<String> arguments) {
81
81
}
82
82
File outputFile = File (outputPath);
83
83
outputFile.writeAsStringSync (
84
- decodeLibraryBlob (rfwFile.readAsBytesSync ()).toString ( ));
84
+ decodeLibraryBlob (rfwFile.readAsBytesSync ()).visit ( ParseTxtVisitor () ));
85
85
} on FormatException catch (e) {
86
86
// Print usage information if an invalid argument was provided.
87
87
print (e.message);
88
88
print ('' );
89
89
printUsage (argParser);
90
90
}
91
91
}
92
+
93
+ extension on RemoteWidgetLibrary {
94
+ String visit (ParseTxtVisitor visitor) => visitor.visit (this );
95
+ }
96
+
97
+ class ParseTxtVisitor {
98
+ String visit (RemoteWidgetLibrary library) {
99
+ StringBuffer buffer = StringBuffer ();
100
+ // write imports
101
+ buffer.writeln (library.imports.map (_visitImport).join ('\n ' ));
102
+
103
+ buffer.writeln ();
104
+ // write widget declarations
105
+ for (var element in library.widgets) {
106
+ buffer.writeln (_visitWidgetDeclaration (element));
107
+ }
108
+ return buffer.toString ();
109
+ }
110
+
111
+ // visit import
112
+ String _visitImport (Import import) => 'import ${import .name };' ;
113
+
114
+ // visit widget declaration
115
+ String _visitWidgetDeclaration (WidgetDeclaration widget) {
116
+ StringBuffer buffer = StringBuffer ();
117
+ buffer.write ('widget ${widget .name }' );
118
+
119
+ if (widget.initialState != null ) {
120
+ buffer.write (_visitDynamicMap (widget.initialState! ));
121
+ }
122
+
123
+ buffer.write (' = ' );
124
+ buffer.write (_visitObject (widget.root));
125
+ buffer.write (';' );
126
+ return buffer.toString ();
127
+ }
128
+
129
+ // visit DynamicMap
130
+ String _visitDynamicMap (DynamicMap map, {bool withoutCurlyBraces = false }) {
131
+ StringBuffer buffer = StringBuffer ();
132
+
133
+ DynamicMap newMap = map.map ((key, value) {
134
+ if (value is int && key == 'color' ) {
135
+ return MapEntry (key, int2Color (value));
136
+ }
137
+ return MapEntry (key, _visitObject (value, dynamicMapKey: key));
138
+ });
139
+
140
+ if (withoutCurlyBraces) {
141
+ buffer
142
+ .write (newMap.entries.map ((e) => '${e .key }: ${e .value }' ).join (', ' ));
143
+ } else {
144
+ buffer.write (newMap);
145
+ }
146
+ return buffer.toString ();
147
+ }
148
+
149
+ // visit DynamicList
150
+ String _visitDynamicList (DynamicList list) =>
151
+ list.map ((e) => _visitObject (e)).toList ().toString ();
152
+
153
+ // visit BlobNode
154
+ String _visitBlobNode (BlobNode node) {
155
+ StringBuffer buffer = StringBuffer ();
156
+ if (node is ConstructorCall ) {
157
+ // ConstructorCall ignore arguments' curly braces
158
+ buffer.write ('${node .name }(' );
159
+ buffer.write (_visitDynamicMap (node.arguments, withoutCurlyBraces: true ));
160
+ buffer.write (')' );
161
+ } else if (node is Switch ) {
162
+ buffer.write ('switch ' );
163
+ buffer.write (_visitObject (node.input));
164
+ buffer.write (' ' );
165
+ node.outputs.forEach ((key, value) {});
166
+ // TODO: Can key be another type?
167
+ buffer.write (node.outputs.map ((key, value) => MapEntry (
168
+ key == null ? 'default' : '$key ' ,
169
+ _visitObject (value, dynamicMapKey: '$key ' ))));
170
+ } else if (node is EventHandler ) {
171
+ buffer.write ('event "${node .eventName }" ' );
172
+ buffer.write (_visitDynamicMap (node.eventArguments));
173
+ } else {
174
+ buffer.write (node.toString ());
175
+ }
176
+ return buffer.toString ();
177
+ }
178
+
179
+ // BlobNode, DynamicMap, DynamicList, int, double, bool, String, null
180
+ String _visitObject (Object ? object, {String ? dynamicMapKey}) {
181
+ if (object is BlobNode ) {
182
+ return _visitBlobNode (object);
183
+ } else if (object is DynamicMap ) {
184
+ return _visitDynamicMap (object);
185
+ } else if (object is DynamicList ) {
186
+ if (object.every ((element) => element is int ) &&
187
+ dynamicMapKey == 'colors' ) {
188
+ return object.map ((e) => int2Color (e as int )).toList ().toString ();
189
+ }
190
+ return _visitDynamicList (object);
191
+ }
192
+ if (object is String ) {
193
+ return '"$object "' ;
194
+ } else {
195
+ //int, double, bool, null
196
+ return '$object ' ;
197
+ }
198
+ }
199
+
200
+ String int2Color (int value) {
201
+ return '0x${value .toRadixString (16 ).toUpperCase ().toUpperCase ()}' ;
202
+ }
203
+ }
0 commit comments