@@ -21,10 +21,10 @@ class JsonConverterHelper extends TypeHelper<TypeHelperContextWithConfig> {
21
21
22
22
@override
23
23
Object ? serialize (
24
- DartType targetType,
25
- String expression,
26
- TypeHelperContextWithConfig context,
27
- ) {
24
+ DartType targetType,
25
+ String expression,
26
+ TypeHelperContextWithConfig context,
27
+ ) {
28
28
final converter = _typeConverter (targetType, context);
29
29
30
30
if (converter == null ) {
@@ -54,11 +54,11 @@ Json? $converterToJsonName<Json, Value>(
54
54
55
55
@override
56
56
Object ? deserialize (
57
- DartType targetType,
58
- String expression,
59
- TypeHelperContextWithConfig context,
60
- bool defaultProvided,
61
- ) {
57
+ DartType targetType,
58
+ String expression,
59
+ TypeHelperContextWithConfig context,
60
+ bool defaultProvided,
61
+ ) {
62
62
final converter = _typeConverter (targetType, context);
63
63
if (converter == null ) {
64
64
return null ;
@@ -91,16 +91,14 @@ Value? $converterFromJsonName<Json, Value>(
91
91
}
92
92
93
93
String _nullableJsonConverterLambdaResult (
94
- _JsonConvertData converter, {
95
- required String name,
96
- required DartType targetType,
97
- required String expression,
98
- required String callback,
99
- }) {
94
+ _JsonConvertData converter, {
95
+ required String name,
96
+ required DartType targetType,
97
+ required String expression,
98
+ required String callback,
99
+ }) {
100
100
final jsonDisplayString = typeToCode (converter.jsonType);
101
- final fieldTypeDisplayString = converter.isGeneric
102
- ? typeToCode (targetType)
103
- : typeToCode (converter.fieldType);
101
+ final fieldTypeDisplayString = converter.isGeneric ? typeToCode (targetType) : typeToCode (converter.fieldType);
104
102
105
103
return '$name <$jsonDisplayString , $fieldTypeDisplayString >('
106
104
'$expression , $callback )' ;
@@ -113,31 +111,31 @@ class _JsonConvertData {
113
111
final bool isGeneric;
114
112
115
113
_JsonConvertData .className (
116
- String className,
117
- String accessor,
118
- this .jsonType,
119
- this .fieldType,
120
- ) : accessString = 'const $className ${_withAccessor (accessor )}()' ,
114
+ String className,
115
+ String ? arguments,
116
+ String accessor,
117
+ this .jsonType,
118
+ this .fieldType,
119
+ ) : accessString = 'const $className ${_withAccessor (accessor )}(${arguments ?? '' })' ,
121
120
isGeneric = false ;
122
121
123
122
_JsonConvertData .genericClass (
124
- String className,
125
- String genericTypeArg ,
126
- String accessor ,
127
- this .jsonType ,
128
- this .fieldType ,
129
- ) : accessString =
130
- '$className <$genericTypeArg >${_withAccessor (accessor )}()' ,
123
+ String className,
124
+ String ? arguments ,
125
+ String genericTypeArg ,
126
+ String accessor ,
127
+ this .jsonType ,
128
+ this .fieldType,
129
+ ) : accessString = '$className <$genericTypeArg >${_withAccessor (accessor )}(${ arguments ?? '' } )' ,
131
130
isGeneric = true ;
132
131
133
132
_JsonConvertData .propertyAccess (
134
- this .accessString,
135
- this .jsonType,
136
- this .fieldType,
137
- ) : isGeneric = false ;
133
+ this .accessString,
134
+ this .jsonType,
135
+ this .fieldType,
136
+ ) : isGeneric = false ;
138
137
139
- static String _withAccessor (String accessor) =>
140
- accessor.isEmpty ? '' : '.$accessor ' ;
138
+ static String _withAccessor (String accessor) => accessor.isEmpty ? '' : '.$accessor ' ;
141
139
}
142
140
143
141
/// If there is no converter for the params, return `null` .
@@ -146,9 +144,9 @@ class _JsonConvertData {
146
144
///
147
145
/// Used to make sure we create a smart encoding function.
148
146
bool ? hasConverterNullEncode (
149
- DartType targetType,
150
- TypeHelperContextWithConfig ctx,
151
- ) {
147
+ DartType targetType,
148
+ TypeHelperContextWithConfig ctx,
149
+ ) {
152
150
final data = _typeConverter (targetType, ctx);
153
151
154
152
if (data == null ) {
@@ -159,34 +157,30 @@ bool? hasConverterNullEncode(
159
157
}
160
158
161
159
_JsonConvertData ? _typeConverter (
162
- DartType targetType,
163
- TypeHelperContextWithConfig ctx,
164
- ) {
160
+ DartType targetType,
161
+ TypeHelperContextWithConfig ctx,
162
+ ) {
165
163
List <_ConverterMatch > converterMatches (List <ElementAnnotation > items) => items
166
164
.map (
167
165
(annotation) => _compatibleMatch (
168
- targetType,
169
- annotation,
170
- annotation.computeConstantValue ()! ,
171
- ),
172
- )
166
+ targetType,
167
+ annotation,
168
+ annotation.computeConstantValue ()! ,
169
+ ),
170
+ )
173
171
.whereType <_ConverterMatch >()
174
172
.toList ();
175
173
176
174
var matchingAnnotations = converterMatches (ctx.fieldElement.metadata);
177
175
178
176
if (matchingAnnotations.isEmpty) {
179
- matchingAnnotations =
180
- converterMatches (ctx.fieldElement.getter? .metadata ?? []);
177
+ matchingAnnotations = converterMatches (ctx.fieldElement.getter? .metadata ?? []);
181
178
182
179
if (matchingAnnotations.isEmpty) {
183
180
matchingAnnotations = converterMatches (ctx.classElement.metadata);
184
181
185
182
if (matchingAnnotations.isEmpty) {
186
- matchingAnnotations = ctx.config.converters
187
- .map ((e) => _compatibleMatch (targetType, null , e))
188
- .whereType <_ConverterMatch >()
189
- .toList ();
183
+ matchingAnnotations = ctx.config.converters.map ((e) => _compatibleMatch (targetType, null , e)).whereType <_ConverterMatch >().toList ();
190
184
}
191
185
}
192
186
}
@@ -195,9 +189,9 @@ _JsonConvertData? _typeConverter(
195
189
}
196
190
197
191
_JsonConvertData ? _typeConverterFrom (
198
- List <_ConverterMatch > matchingAnnotations,
199
- DartType targetType,
200
- ) {
192
+ List <_ConverterMatch > matchingAnnotations,
193
+ DartType targetType,
194
+ ) {
201
195
if (matchingAnnotations.isEmpty) {
202
196
return null ;
203
197
}
@@ -230,18 +224,13 @@ _JsonConvertData? _typeConverterFrom(
230
224
}
231
225
232
226
final reviver = ConstantReader (match.annotation).revive ();
233
-
234
- if (reviver.namedArguments.isNotEmpty ||
235
- reviver.positionalArguments.isNotEmpty) {
236
- throw InvalidGenerationSourceError (
237
- 'Generators with constructor arguments are not supported.' ,
238
- element: match.elementAnnotation? .element,
239
- );
240
- }
227
+ // Support generators with constructor arguments
228
+ String ? arguments = _argsFromRevivable (reviver);
241
229
242
230
if (match.genericTypeArg != null ) {
243
231
return _JsonConvertData .genericClass (
244
232
match.annotation.type! .element! .name! ,
233
+ arguments,
245
234
match.genericTypeArg! ,
246
235
reviver.accessor,
247
236
match.jsonType,
@@ -251,12 +240,73 @@ _JsonConvertData? _typeConverterFrom(
251
240
252
241
return _JsonConvertData .className (
253
242
match.annotation.type! .element! .name! ,
243
+ arguments,
254
244
reviver.accessor,
255
245
match.jsonType,
256
246
match.fieldType,
257
247
);
258
248
}
259
249
250
+ String ? _argsFromRevivable (Revivable reviver) {
251
+ String ? arguments, positionalArguments, namedArguments;
252
+ if (reviver.positionalArguments.isNotEmpty) {
253
+ positionalArguments = reviver.positionalArguments.map ((DartObject arg) => _argumentValueFromDartObject (arg)).join (', ' );
254
+ }
255
+ if (reviver.namedArguments.isNotEmpty) {
256
+ namedArguments = reviver.namedArguments.keys
257
+ .map ((String key) {
258
+ dynamic arg = _argumentValueFromDartObject (reviver.namedArguments[key]);
259
+ if (null != arg) return '$key : $arg ' ;
260
+ return null ;
261
+ })
262
+ .where (_isNotEmpty)
263
+ .join (', ' );
264
+ }
265
+ arguments = < String ? > [positionalArguments, namedArguments].where (_isNotEmpty).join (', ' );
266
+ return arguments;
267
+ }
268
+
269
+ bool _isNotEmpty (dynamic element) => null != element;
270
+
271
+ dynamic _argumentValueFromDartObject (DartObject ? obj) {
272
+ try {
273
+ if (null != obj) {
274
+ if (obj.type? .isDartCoreString == true ) {
275
+ return '\' ${obj .toStringValue ()}\' ' ;
276
+ } else if (obj.type? .isDartCoreInt == true ) {
277
+ return obj.toIntValue ();
278
+ } else if (obj.type? .isDartCoreDouble == true ) {
279
+ return obj.toDoubleValue ();
280
+ } else if (obj.type? .isDartCoreBool == true ) {
281
+ return obj.toBoolValue ();
282
+ } else if (obj.type? .isDartCoreIterable == true || obj.type? .isDartCoreList == true ) {
283
+ return obj.toListValue ();
284
+ } else if (obj.type? .isDartCoreMap == true ) {
285
+ return obj.toMapValue ();
286
+ } else if (obj.type? .isDartCoreSet == true ) {
287
+ return obj.toSetValue ();
288
+ } else if (obj.type? .isDartCoreSymbol == true ) {
289
+ return obj.toSymbolValue ();
290
+ } else {
291
+ ExecutableElement ? executable = obj.toFunctionValue ();
292
+ if (null != executable) {
293
+ return executable.displayName;
294
+ } else if (null != obj.type) {
295
+ String ? typeDisplayString = obj.type? .getDisplayString (withNullability: false );
296
+ if (null != typeDisplayString && typeDisplayString != 'Null' ) {
297
+ final reviver = ConstantReader (obj).revive ();
298
+ String ? arguments = _argsFromRevivable (reviver);
299
+ return '$typeDisplayString (${arguments ?? '' })' ;
300
+ }
301
+ }
302
+ }
303
+ }
304
+ } catch (e) {
305
+ print (e);
306
+ }
307
+ return null ;
308
+ }
309
+
260
310
class _ConverterMatch {
261
311
final DartObject annotation;
262
312
final DartType fieldType;
@@ -265,24 +315,23 @@ class _ConverterMatch {
265
315
final String ? genericTypeArg;
266
316
267
317
_ConverterMatch (
268
- this .elementAnnotation,
269
- this .annotation,
270
- this .jsonType,
271
- this .genericTypeArg,
272
- this .fieldType,
273
- );
318
+ this .elementAnnotation,
319
+ this .annotation,
320
+ this .jsonType,
321
+ this .genericTypeArg,
322
+ this .fieldType,
323
+ );
274
324
}
275
325
276
326
_ConverterMatch ? _compatibleMatch (
277
- DartType targetType,
278
- ElementAnnotation ? annotation,
279
- DartObject constantValue,
280
- ) {
327
+ DartType targetType,
328
+ ElementAnnotation ? annotation,
329
+ DartObject constantValue,
330
+ ) {
281
331
final converterClassElement = constantValue.type! .element as ClassElement ;
282
332
283
- final jsonConverterSuper =
284
- converterClassElement.allSupertypes.singleWhereOrNull (
285
- (e) => _jsonConverterChecker.isExactly (e.element),
333
+ final jsonConverterSuper = converterClassElement.allSupertypes.singleWhereOrNull (
334
+ (e) => _jsonConverterChecker.isExactly (e.element),
286
335
);
287
336
288
337
if (jsonConverterSuper == null ) {
@@ -311,8 +360,8 @@ _ConverterMatch? _compatibleMatch(
311
360
if (converterClassElement.typeParameters.length > 1 ) {
312
361
throw InvalidGenerationSourceError (
313
362
'`JsonConverter` implementations can have no more than one type '
314
- 'argument. `${converterClassElement .name }` has '
315
- '${converterClassElement .typeParameters .length }.' ,
363
+ 'argument. `${converterClassElement .name }` has '
364
+ '${converterClassElement .typeParameters .length }.' ,
316
365
element: converterClassElement);
317
366
}
318
367
0 commit comments