mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:09:49 +00:00
Use less static types, just check names and library URIs of declarations.
Also adds some additional "parallelizatoin" of async tasks. Overall speedup of >50%, definitions phase in particular is about 75% faster. Before: [time: 16043 ms] (name: <scheduler>, count: 0, elapsed: 0:00:00.000000, elapsedSelf: -0:00:15.823859) (name: analyzeFile, count: 104, elapsed: 0:00:15.823859, elapsedSelf: 0:00:01.428470) (name: libraryContext, count: 104, elapsed: 0:00:14.395389, elapsedSelf: 0:00:00.272344)(bytesPut: 5386317, cycleCount: 9, libraryCount: 115) (name: link, count: 9, elapsed: 0:00:11.027694, elapsedSelf: 0:00:00.529548) (name: computeLibraryScopes, count: 9, elapsed: 0:00:00.305524, elapsedSelf: 0:00:00.126633) (name: buildMacroApplier, count: 9, elapsed: 0:00:00.178642, elapsedSelf: 0:00:00.178642) (name: executeMacroTypesPhase, count: 9, elapsed: 0:00:00.000249, elapsedSelf: 0:00:00.000249) (name: executeMacroDeclarationsPhase, count: 9, elapsed: 0:00:00.367608, elapsedSelf: 0:00:00.367608)(constructorsOf: 100, methodsOf: 100) (name: executeMacroDefinitionsPhase, count: 9, elapsed: 0:00:09.226594, elapsedSelf: 0:00:00.002483) (name: executeDefinitionsPhase, count: 315, elapsed: 0:00:08.188795, elapsedSelf: 0:00:08.188795)(constructorsOf: 300, methodsOf: 300, resolve: 42000, typeDeclarationOf: 1200) (name: addMacroResults, count: 200, elapsed: 0:00:01.035316, elapsedSelf: 0:00:01.035316) (name: mergeMacroAugmentations, count: 9, elapsed: 0:00:00.598420, elapsedSelf: 0:00:00.598420) (name: macroCompileKernel, count: 1, elapsed: 0:00:03.095351, elapsedSelf: 0:00:03.095351) After: [time: 7774 ms] (name: <scheduler>, count: 0, elapsed: 0:00:00.000000, elapsedSelf: -0:00:07.582758) (name: analyzeFile, count: 104, elapsed: 0:00:07.582758, elapsedSelf: 0:00:01.049135) (name: libraryContext, count: 104, elapsed: 0:00:06.533623, elapsedSelf: 0:00:00.232088)(bytesPut: 5385998, cycleCount: 9, libraryCount: 115) (name: link, count: 9, elapsed: 0:00:03.198967, elapsedSelf: 0:00:00.309712) (name: computeLibraryScopes, count: 9, elapsed: 0:00:00.184852, elapsedSelf: 0:00:00.079394) (name: buildMacroApplier, count: 9, elapsed: 0:00:00.105297, elapsedSelf: 0:00:00.105297) (name: executeMacroTypesPhase, count: 9, elapsed: 0:00:00.000161, elapsedSelf: 0:00:00.000161) (name: executeMacroDeclarationsPhase, count: 9, elapsed: 0:00:00.301573, elapsedSelf: 0:00:00.301573)(constructorsOf: 100, methodsOf: 100) (name: executeMacroDefinitionsPhase, count: 9, elapsed: 0:00:01.823845, elapsedSelf: 0:00:00.001162) (name: executeDefinitionsPhase, count: 315, elapsed: 0:00:01.101564, elapsedSelf: 0:00:01.101564)(constructorsOf: 300, methodsOf: 300, resolve: 400, typeDeclarationOf: 41200) (name: addMacroResults, count: 200, elapsed: 0:00:00.721119, elapsedSelf: 0:00:00.721119) (name: mergeMacroAugmentations, count: 9, elapsed: 0:00:00.578985, elapsedSelf: 0:00:00.578985) (name: macroCompileKernel, count: 1, elapsed: 0:00:03.102568, elapsedSelf: 0:00:03.102568) Change-Id: I88f390ec01469e96ca8a43a49897e3e5b173b731 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/362041 Commit-Queue: Jake Macdonald <jakemac@google.com> Auto-Submit: Jake Macdonald <jakemac@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
c2f3418251
commit
ddca3d2386
|
@ -38,13 +38,15 @@ macro class JsonSerializable implements ClassDeclarationsMacro {
|
|||
Severity.error));
|
||||
}
|
||||
|
||||
var map = await builder.resolveIdentifier(_dartCore, 'Map');
|
||||
var string = NamedTypeAnnotationCode(
|
||||
name: await builder.resolveIdentifier(_dartCore, 'String'));
|
||||
var object = NamedTypeAnnotationCode(
|
||||
name: await builder.resolveIdentifier(_dartCore, 'Object'));
|
||||
var mapStringObject = NamedTypeAnnotationCode(
|
||||
name: map, typeArguments: [string, object.asNullable]);
|
||||
var [map, string, object] = await Future.wait([
|
||||
builder.resolveIdentifier(_dartCore, 'Map'),
|
||||
builder.resolveIdentifier(_dartCore, 'String'),
|
||||
builder.resolveIdentifier(_dartCore, 'Object'),
|
||||
]);
|
||||
var mapStringObject = NamedTypeAnnotationCode(name: map, typeArguments: [
|
||||
NamedTypeAnnotationCode(name: string),
|
||||
NamedTypeAnnotationCode(name: object).asNullable
|
||||
]);
|
||||
|
||||
var jsonSerializableUri = clazz.jsonSerializableUri;
|
||||
|
||||
|
@ -84,39 +86,40 @@ macro class FromJson implements ConstructorDefinitionMacro {
|
|||
as ClassDeclaration;
|
||||
var superclass = clazz.superclass;
|
||||
var superclassHasFromJson = false;
|
||||
if (superclass != null &&
|
||||
!await (await builder
|
||||
.resolve(NamedTypeAnnotationCode(name: superclass.identifier)))
|
||||
.isExactly(fromJsonData.objectType)) {
|
||||
if (superclass != null) {
|
||||
var superclassDeclaration =
|
||||
await builder.typeDeclarationOf(superclass.identifier);
|
||||
var superclassConstructors =
|
||||
await builder.constructorsOf(superclassDeclaration);
|
||||
for (var superConstructor in superclassConstructors) {
|
||||
if (superConstructor.identifier.name == 'fromJson') {
|
||||
await _checkValidFromJson(superConstructor, fromJsonData, builder);
|
||||
superclassHasFromJson = true;
|
||||
break;
|
||||
if (!superclassDeclaration.isExactly('Object', _dartCore)) {
|
||||
var superclassConstructors =
|
||||
await builder.constructorsOf(superclassDeclaration);
|
||||
for (var superConstructor in superclassConstructors) {
|
||||
if (superConstructor.identifier.name == 'fromJson') {
|
||||
await _checkValidFromJson(superConstructor, fromJsonData, builder);
|
||||
superclassHasFromJson = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!superclassHasFromJson) {
|
||||
throw new DiagnosticException(Diagnostic(
|
||||
DiagnosticMessage(
|
||||
'Serialization of classes that extend other classes is only '
|
||||
'supported if those classes have a valid '
|
||||
'`fromJson(Map<String, Object?> json)` constructor.',
|
||||
target: superclass.asDiagnosticTarget),
|
||||
Severity.error));
|
||||
}
|
||||
}
|
||||
if (!superclassHasFromJson) {
|
||||
throw new DiagnosticException(Diagnostic(
|
||||
DiagnosticMessage(
|
||||
'Serialization of classes that extend other classes is only '
|
||||
'supported if those classes have a valid '
|
||||
'`fromJson(Map<String, Object?> json)` constructor.',
|
||||
target: superclass.asDiagnosticTarget),
|
||||
Severity.error));
|
||||
}
|
||||
}
|
||||
|
||||
var fields = await builder.fieldsOf(clazz);
|
||||
var jsonParam = constructor.positionalParameters.single.identifier;
|
||||
var initializers = <Code>[];
|
||||
for (var field in fields) {
|
||||
var config = await field.readConfig(builder);
|
||||
|
||||
Future<Code> _initializerForField(FieldDeclaration field) async {
|
||||
var config = field.metadata.isEmpty
|
||||
? _FieldConfig(field, null)
|
||||
: await field.readConfig(builder);
|
||||
var defaultValue = config.defaultValue;
|
||||
initializers.add(RawCode.fromParts([
|
||||
return RawCode.fromParts([
|
||||
field.identifier,
|
||||
' = ',
|
||||
if (defaultValue != null) ...[
|
||||
|
@ -139,8 +142,9 @@ macro class FromJson implements ConstructorDefinitionMacro {
|
|||
' : ',
|
||||
defaultValue,
|
||||
],
|
||||
]));
|
||||
]);
|
||||
}
|
||||
var initializers = await Future.wait(fields.map(_initializerForField));
|
||||
|
||||
if (superclassHasFromJson) {
|
||||
initializers.add(RawCode.fromParts([
|
||||
|
@ -205,13 +209,7 @@ macro class FromJson implements ConstructorDefinitionMacro {
|
|||
"throw 'Unable to deserialize type ${type.code.debugString}'");
|
||||
}
|
||||
|
||||
// The static type of the expected type, without any type arguments.
|
||||
var typeDeclType = await builder.resolve(
|
||||
NamedTypeAnnotationCode(name: typeDecl.identifier, typeArguments: [
|
||||
for (var typeParam in typeDecl.typeParameters)
|
||||
typeParam.bound?.code ?? fromJsonData.objectCode.asNullable,
|
||||
]));
|
||||
if (await typeDeclType.isExactly(fromJsonData.listType)) {
|
||||
if (typeDecl.isExactly('List', _dartCore)) {
|
||||
return RawCode.fromParts([
|
||||
'[ for (var item in ',
|
||||
jsonReference,
|
||||
|
@ -222,7 +220,7 @@ macro class FromJson implements ConstructorDefinitionMacro {
|
|||
RawCode.fromString('item'), builder, fromJsonData),
|
||||
']',
|
||||
]);
|
||||
} else if (await typeDeclType.isExactly(fromJsonData.setType)) {
|
||||
} else if (typeDecl.isExactly('Set', _dartCore)) {
|
||||
return RawCode.fromParts([
|
||||
'{ for (var item in ',
|
||||
jsonReference,
|
||||
|
@ -233,7 +231,7 @@ macro class FromJson implements ConstructorDefinitionMacro {
|
|||
RawCode.fromString('item'), builder, fromJsonData),
|
||||
'}',
|
||||
]);
|
||||
} else if (await typeDeclType.isExactly(fromJsonData.mapType)) {
|
||||
} else if (typeDecl.isExactly('Map', _dartCore)) {
|
||||
return RawCode.fromParts([
|
||||
'{ for (var entry in ',
|
||||
jsonReference,
|
||||
|
@ -348,30 +346,21 @@ final class _FromJsonData {
|
|||
final NamedTypeAnnotationCode jsonListCode;
|
||||
final NamedTypeAnnotationCode jsonMapCode;
|
||||
final StaticType jsonMapType;
|
||||
final StaticType listType;
|
||||
final StaticType mapType;
|
||||
final NamedTypeAnnotationCode objectCode;
|
||||
final StaticType objectType;
|
||||
final StaticType setType;
|
||||
|
||||
_FromJsonData({
|
||||
required this.jsonListCode,
|
||||
required this.jsonMapCode,
|
||||
required this.jsonMapType,
|
||||
required this.listType,
|
||||
required this.mapType,
|
||||
required this.objectCode,
|
||||
required this.objectType,
|
||||
required this.setType,
|
||||
});
|
||||
|
||||
static Future<_FromJsonData> build(
|
||||
ConstructorDefinitionBuilder builder) async {
|
||||
var [list, map, object, set, string] = await Future.wait([
|
||||
var [list, map, object, string] = await Future.wait([
|
||||
builder.resolveIdentifier(_dartCore, 'List'),
|
||||
builder.resolveIdentifier(_dartCore, 'Map'),
|
||||
builder.resolveIdentifier(_dartCore, 'Object'),
|
||||
builder.resolveIdentifier(_dartCore, 'Set'),
|
||||
builder.resolveIdentifier(_dartCore, 'String'),
|
||||
]);
|
||||
var objectCode = NamedTypeAnnotationCode(name: object);
|
||||
|
@ -383,27 +372,13 @@ final class _FromJsonData {
|
|||
NamedTypeAnnotationCode(name: string),
|
||||
nullableObjectCode,
|
||||
]);
|
||||
var [jsonMapType, listType, mapType, objectType, setType] =
|
||||
await Future.wait([
|
||||
builder.resolve(jsonMapCode),
|
||||
builder.resolve(NamedTypeAnnotationCode(
|
||||
name: list, typeArguments: [nullableObjectCode])),
|
||||
builder.resolve(NamedTypeAnnotationCode(
|
||||
name: map, typeArguments: [nullableObjectCode, nullableObjectCode])),
|
||||
builder.resolve(objectCode),
|
||||
builder.resolve(NamedTypeAnnotationCode(
|
||||
name: set, typeArguments: [nullableObjectCode])),
|
||||
]);
|
||||
var jsonMapType = await builder.resolve(jsonMapCode);
|
||||
|
||||
return _FromJsonData(
|
||||
jsonListCode: jsonListCode,
|
||||
jsonMapCode: jsonMapCode,
|
||||
jsonMapType: jsonMapType,
|
||||
listType: listType,
|
||||
mapType: mapType,
|
||||
objectCode: objectCode,
|
||||
objectType: objectType,
|
||||
setType: setType,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -424,31 +399,30 @@ macro class ToJson implements MethodDefinitionMacro {
|
|||
as ClassDeclaration;
|
||||
var superclass = clazz.superclass;
|
||||
var superclassHasToJson = false;
|
||||
if (superclass != null &&
|
||||
!await (await builder
|
||||
.resolve(NamedTypeAnnotationCode(name: superclass.identifier)))
|
||||
.isExactly(toJsonData.objectType)) {
|
||||
if (superclass != null) {
|
||||
var superclassDeclaration =
|
||||
await builder.typeDeclarationOf(superclass.identifier);
|
||||
var superclassMethods = await builder.methodsOf(superclassDeclaration);
|
||||
for (var superMethod in superclassMethods) {
|
||||
if (superMethod.identifier.name == 'toJson') {
|
||||
if (!(await _checkValidToJson(superMethod, toJsonData, builder))) {
|
||||
return;
|
||||
if (!superclassDeclaration.isExactly('Object', _dartCore)) {
|
||||
var superclassMethods = await builder.methodsOf(superclassDeclaration);
|
||||
for (var superMethod in superclassMethods) {
|
||||
if (superMethod.identifier.name == 'toJson') {
|
||||
if (!(await _checkValidToJson(superMethod, toJsonData, builder))) {
|
||||
return;
|
||||
}
|
||||
superclassHasToJson = true;
|
||||
break;
|
||||
}
|
||||
superclassHasToJson = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!superclassHasToJson) {
|
||||
builder.report(Diagnostic(
|
||||
DiagnosticMessage(
|
||||
'Serialization of classes that extend other classes is only '
|
||||
'supported if those classes have a valid '
|
||||
'`Map<String, Object?> toJson()` method.',
|
||||
target: superclass.asDiagnosticTarget),
|
||||
Severity.error));
|
||||
return;
|
||||
if (!superclassHasToJson) {
|
||||
builder.report(Diagnostic(
|
||||
DiagnosticMessage(
|
||||
'Serialization of classes that extend other classes is only '
|
||||
'supported if those classes have a valid '
|
||||
'`Map<String, Object?> toJson()` method.',
|
||||
target: superclass.asDiagnosticTarget),
|
||||
Severity.error));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,8 +440,12 @@ macro class ToJson implements MethodDefinitionMacro {
|
|||
],
|
||||
';\n '
|
||||
];
|
||||
for (var field in fields) {
|
||||
var config = await field.readConfig(builder);
|
||||
|
||||
Future<Code> _addEntryForField(FieldDeclaration field) async {
|
||||
var parts = <Object>[];
|
||||
var config = field.metadata.isEmpty
|
||||
? _FieldConfig(field, null)
|
||||
: await field.readConfig(builder);
|
||||
var doNullCheck = !config.includeIfNull && field.type.isNullable;
|
||||
if (doNullCheck) {
|
||||
// TODO: Compare == `null` instead, once we can resolve `null`.
|
||||
|
@ -490,7 +468,10 @@ macro class ToJson implements MethodDefinitionMacro {
|
|||
if (doNullCheck) {
|
||||
parts.add(' }\n');
|
||||
}
|
||||
return RawCode.fromParts(parts);
|
||||
}
|
||||
parts.addAll(await Future.wait(fields.map(_addEntryForField)));
|
||||
|
||||
parts.add(' return json;\n }');
|
||||
|
||||
builder.augment(FunctionBodyCode.fromParts(parts));
|
||||
|
@ -547,14 +528,9 @@ macro class ToJson implements MethodDefinitionMacro {
|
|||
"throw 'Unable to serialize type ${type.code.debugString}'");
|
||||
}
|
||||
|
||||
var typeDeclType = await builder.resolve(
|
||||
NamedTypeAnnotationCode(name: typeDecl.identifier, typeArguments: [
|
||||
for (var typeParam in typeDecl.typeParameters)
|
||||
typeParam.bound?.code ?? toJsonData.objectCode.asNullable,
|
||||
]));
|
||||
// If it is a List/Set type, serialize it as a JSON list.
|
||||
if (await typeDeclType.isExactly(toJsonData.listType) ||
|
||||
await typeDeclType.isExactly(toJsonData.setType)) {
|
||||
if (typeDecl.isExactly('List', _dartCore) ||
|
||||
typeDecl.isExactly('Set', _dartCore)) {
|
||||
return RawCode.fromParts([
|
||||
'[ for (var item in ',
|
||||
valueReference,
|
||||
|
@ -564,7 +540,7 @@ macro class ToJson implements MethodDefinitionMacro {
|
|||
']',
|
||||
]);
|
||||
// If it is a Map type, serialize it as a JSON map.
|
||||
} else if (await typeDeclType.isExactly(toJsonData.mapType)) {
|
||||
} else if (typeDecl.isExactly('Map', _dartCore)) {
|
||||
return RawCode.fromParts([
|
||||
'{ for (var entry in ',
|
||||
valueReference,
|
||||
|
@ -595,60 +571,37 @@ macro class ToJson implements MethodDefinitionMacro {
|
|||
|
||||
final class _ToJsonData {
|
||||
final StaticType jsonMapType;
|
||||
final StaticType listType;
|
||||
final StaticType mapType;
|
||||
final Identifier nullIdentifier;
|
||||
final NamedTypeAnnotationCode objectCode;
|
||||
final StaticType objectType;
|
||||
final StaticType setType;
|
||||
final NamedTypeAnnotationCode stringCode;
|
||||
|
||||
_ToJsonData({
|
||||
required this.jsonMapType,
|
||||
required this.listType,
|
||||
required this.mapType,
|
||||
required this.nullIdentifier,
|
||||
required this.objectCode,
|
||||
required this.objectType,
|
||||
required this.setType,
|
||||
required this.stringCode,
|
||||
});
|
||||
|
||||
static Future<_ToJsonData> build(FunctionDefinitionBuilder builder) async {
|
||||
var [list, map, nullIdentifier, object, set, string] = await Future.wait([
|
||||
builder.resolveIdentifier(_dartCore, 'List'),
|
||||
var [map, nullIdentifier, object, string] = await Future.wait([
|
||||
builder.resolveIdentifier(_dartCore, 'Map'),
|
||||
builder.resolveIdentifier(_dartCore, 'Null'),
|
||||
builder.resolveIdentifier(_dartCore, 'Object'),
|
||||
builder.resolveIdentifier(_dartCore, 'Set'),
|
||||
builder.resolveIdentifier(_dartCore, 'String'),
|
||||
]);
|
||||
var objectCode = NamedTypeAnnotationCode(name: object);
|
||||
var stringCode = NamedTypeAnnotationCode(name: string);
|
||||
var nullableObjectCode = objectCode.asNullable;
|
||||
var [jsonMapType, listType, mapType, objectType, setType] =
|
||||
await Future.wait([
|
||||
builder.resolve(NamedTypeAnnotationCode(name: map, typeArguments: [
|
||||
stringCode,
|
||||
nullableObjectCode,
|
||||
])),
|
||||
builder.resolve(NamedTypeAnnotationCode(
|
||||
name: list, typeArguments: [nullableObjectCode])),
|
||||
builder.resolve(NamedTypeAnnotationCode(
|
||||
name: map, typeArguments: [nullableObjectCode, nullableObjectCode])),
|
||||
builder.resolve(objectCode),
|
||||
builder.resolve(NamedTypeAnnotationCode(
|
||||
name: set, typeArguments: [nullableObjectCode])),
|
||||
]);
|
||||
var jsonMapType = await builder
|
||||
.resolve(NamedTypeAnnotationCode(name: map, typeArguments: [
|
||||
stringCode,
|
||||
nullableObjectCode,
|
||||
]));
|
||||
|
||||
return _ToJsonData(
|
||||
jsonMapType: jsonMapType,
|
||||
listType: listType,
|
||||
mapType: mapType,
|
||||
nullIdentifier: nullIdentifier,
|
||||
objectCode: objectCode,
|
||||
objectType: objectType,
|
||||
setType: setType,
|
||||
stringCode: stringCode,
|
||||
);
|
||||
}
|
||||
|
@ -693,3 +646,8 @@ extension _RelativeUris on Declaration {
|
|||
|
||||
Uri get jsonSerializableUri => library.uri.resolve('json_serializable.dart');
|
||||
}
|
||||
|
||||
extension _IsExactly on TypeDeclaration {
|
||||
bool isExactly(String name, Uri library) =>
|
||||
identifier.name == name && this.library.uri == library;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue