update json macro and macro code, to handle omitted types better and not crash the analyzer

Change-Id: I2b30568dd4163b0032624f1fd0db6d6a6246f16c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/365960
Auto-Submit: Jake Macdonald <jakemac@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Jake Macdonald
2024-05-09 20:57:07 +00:00
parent ebcf5fee57
commit 2c694286e6
+32 -18
View File
@@ -310,19 +310,14 @@ macro class JsonCodable
/// Returns a [Code] object which is an expression that converts a JSON map
/// (referenced by [jsonReference]) into an instance of type [type].
Future<Code> _convertTypeFromJson(
TypeAnnotation type,
TypeAnnotation rawType,
Code jsonReference,
DefinitionBuilder builder,
_SharedIntrospectionData introspectionData) async {
if (type is! NamedTypeAnnotation) {
builder.report(Diagnostic(
DiagnosticMessage(
'Only fields with named types are allowed on serializable '
'classes',
target: type.asDiagnosticTarget),
Severity.error));
final type = _checkNamedType(rawType, builder);
if (type == null) {
return RawCode.fromString(
"throw 'Unable to deserialize type ${type.code.debugString}'");
"throw 'Unable to deserialize type ${rawType.code.debugString}'");
}
// Follow type aliases until we reach an actual named type.
@@ -407,6 +402,28 @@ macro class JsonCodable
]);
}
/// Returns [type] as a [NamedTypeAnnotation] if it is one, otherwise returns
/// `null` and emits relevant error diagnostics.
NamedTypeAnnotation? _checkNamedType(TypeAnnotation type, Builder builder) {
if (type is NamedTypeAnnotation) return type;
if (type is OmittedTypeAnnotation) {
builder.report(Diagnostic(
DiagnosticMessage(
'Only fields with explicit types are allowed on serializable '
'classes, please add a type.',
target: type.asDiagnosticTarget),
Severity.error));
} else {
builder.report(Diagnostic(
DiagnosticMessage(
'Only fields with named types are allowed on serializable '
'classes.',
target: type.asDiagnosticTarget),
Severity.error));
}
return null;
}
/// Checks that [method] is a valid `toJson` method, and throws a
/// [DiagnosticException] if not.
Future<bool> _checkValidToJson(
@@ -431,19 +448,14 @@ macro class JsonCodable
/// Returns a [Code] object which is an expression that converts an instance
/// of type [type] (referenced by [valueReference]) into a JSON map.
Future<Code> _convertTypeToJson(
TypeAnnotation type,
TypeAnnotation rawType,
Code valueReference,
DefinitionBuilder builder,
_SharedIntrospectionData introspectionData) async {
if (type is! NamedTypeAnnotation) {
builder.report(Diagnostic(
DiagnosticMessage(
'Only fields with named types are allowed on serializable '
'classes',
target: type.asDiagnosticTarget),
Severity.error));
final type = _checkNamedType(rawType, builder);
if (type == null) {
return RawCode.fromString(
"throw 'Unable to serialize type ${type.code.debugString}'");
"throw 'Unable to serialize type ${rawType.code.debugString}'");
}
// Follow type aliases until we reach an actual named type.
@@ -651,6 +663,8 @@ extension on Code {
part._writeDebugString(buffer);
case Identifier():
buffer.write(part.name);
case OmittedTypeAnnotation():
buffer.write('<omitted>');
default:
buffer.write(part);
}