diff --git a/json_serializable/lib/src/type_helper_ctx.dart b/json_serializable/lib/src/type_helper_ctx.dart index 4e85cb48..eee89039 100644 --- a/json_serializable/lib/src/type_helper_ctx.dart +++ b/json_serializable/lib/src/type_helper_ctx.dart @@ -4,6 +4,7 @@ import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/src/dart/constant/value.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:source_helper/source_helper.dart'; @@ -122,12 +123,19 @@ ConvertData? _convertData(DartObject obj, FieldElement element, bool isFrom) { if (objectValue == null || objectValue.isNull) { return null; } - final executableElement = objectValue.toFunctionValue()!; + var executableType = executableElement.type; + var qualifiedName = executableElement.qualifiedName; + final state = (objectValue as DartObjectImpl).state; + if (((state as FunctionState).typeArguments?.length ?? 0) > 0) { + final generics = state.typeArguments!.cast(); + executableType = executableType.instantiate(generics); + qualifiedName += "<${generics.join(',')}>"; + } - if (executableElement.formalParameters.isEmpty || - executableElement.formalParameters.first.isNamed || - executableElement.formalParameters.where((pe) => !pe.isOptional).length > + if (executableType.formalParameters.isEmpty || + executableType.formalParameters.first.isNamed || + executableType.formalParameters.where((pe) => !pe.isOptional).length > 1) { throwUnsupported( element, @@ -136,8 +144,8 @@ ConvertData? _convertData(DartObject obj, FieldElement element, bool isFrom) { ); } - final returnType = executableElement.returnType; - final argType = executableElement.formalParameters.first.type; + final returnType = executableType.returnType; + final argType = executableType.formalParameters.first.type; if (isFrom) { final hasDefaultValue = !jsonKeyAnnotation( element, @@ -179,5 +187,5 @@ ConvertData? _convertData(DartObject obj, FieldElement element, bool isFrom) { } } - return ConvertData(executableElement.qualifiedName, argType, returnType); + return ConvertData(qualifiedName, argType, returnType); } diff --git a/json_serializable/lib/src/type_helpers/json_converter_helper.dart b/json_serializable/lib/src/type_helpers/json_converter_helper.dart index 1288b7c9..78e8c7b8 100644 --- a/json_serializable/lib/src/type_helpers/json_converter_helper.dart +++ b/json_serializable/lib/src/type_helpers/json_converter_helper.dart @@ -4,6 +4,7 @@ import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:source_gen/source_gen.dart'; @@ -281,9 +282,20 @@ _ConverterMatch? _compatibleMatch( ElementAnnotation? annotation, DartObject constantValue, ) { - final converterClassElement = constantValue.type!.element as ClassElement; + var converterClassType = constantValue.type! as InterfaceType; + final converterClassElement = converterClassType.element as ClassElement; + String? genericTypeArg; + + final generics = (constantValue.type as InterfaceType).typeArguments; + if (generics.isNotEmpty) { + converterClassType = converterClassElement.instantiate( + typeArguments: generics, + nullabilitySuffix: NullabilitySuffix.none, + ); + genericTypeArg = generics.join(", "); + } - final jsonConverterSuper = converterClassElement.allSupertypes + final jsonConverterSuper = converterClassType.allSupertypes .where((e) => _jsonConverterChecker.isExactly(e.element)) .singleOrNull; @@ -302,7 +314,7 @@ _ConverterMatch? _compatibleMatch( annotation, constantValue, jsonConverterSuper.typeArguments[1], - null, + genericTypeArg, fieldType, ); }