From 4c563fecbf0be73d2d1df5bd005bca415a9065eb Mon Sep 17 00:00:00 2001 From: Johnni Winther Date: Fri, 29 Apr 2016 10:00:53 +0200 Subject: [PATCH] Serialize more properties of ConstructorElement. Review URL: https://codereview.chromium.org/1924053003 . --- .../serialization/element_serialization.dart | 37 +++++- pkg/compiler/lib/src/serialization/keys.dart | 6 + .../lib/src/serialization/modelz.dart | 109 ++++++++++++++---- .../compiler/dart2js/serialization_test.dart | 18 +++ 4 files changed, 145 insertions(+), 25 deletions(-) diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart index 6f5dc4d83cd..5c8c0d68fc3 100644 --- a/pkg/compiler/lib/src/serialization/element_serialization.dart +++ b/pkg/compiler/lib/src/serialization/element_serialization.dart @@ -13,6 +13,7 @@ import 'constant_serialization.dart'; import 'keys.dart'; import 'modelz.dart'; import 'serialization.dart'; +import 'serialization_util.dart'; /// Enum kinds used for encoding [Element]s. enum SerializedElementKind { @@ -23,6 +24,7 @@ enum SerializedElementKind { NAMED_MIXIN_APPLICATION, GENERATIVE_CONSTRUCTOR, FACTORY_CONSTRUCTOR, + REDIRECTING_FACTORY_CONSTRUCTOR, FORWARDING_CONSTRUCTOR, TOPLEVEL_FIELD, STATIC_FIELD, @@ -346,7 +348,12 @@ class ConstructorSerializer implements ElementSerializer { return SerializedElementKind.GENERATIVE_CONSTRUCTOR; } } else if (element.isFactoryConstructor) { - return SerializedElementKind.FACTORY_CONSTRUCTOR; + ConstructorElement constructor = element; + if (constructor.isRedirectingFactory) { + return SerializedElementKind.REDIRECTING_FACTORY_CONSTRUCTOR; + } else { + return SerializedElementKind.FACTORY_CONSTRUCTOR; + } } return null; } @@ -363,13 +370,37 @@ class ConstructorSerializer implements ElementSerializer { SerializerUtil.serializeParameters(element, encoder); encoder.setBool(Key.IS_CONST, element.isConst); encoder.setBool(Key.IS_EXTERNAL, element.isExternal); - if (element.isExternal) return; if (element.isConst && !element.isFromEnvironmentConstructor) { ConstantConstructor constantConstructor = element.constantConstructor; ObjectEncoder constantEncoder = encoder.createObject(Key.CONSTRUCTOR); const ConstantConstructorSerializer() .visit(constantConstructor, constantEncoder); } + if (element.definingConstructor != null) { + assert(invariant( + element, + element.definingConstructor.enclosingClass == + element.enclosingClass.superclass, + message: "Unexpected defining constructor: " + "${element.definingConstructor}")); + encoder.setString( + Key.DEFINING_CONSTRUCTOR, element.definingConstructor.name); + } + if (kind == SerializedElementKind.GENERATIVE_CONSTRUCTOR) { + encoder.setBool(Key.IS_REDIRECTING, element.isRedirectingGenerative); + } + encoder.setElement(Key.EFFECTIVE_TARGET, element.effectiveTarget); + if (kind == SerializedElementKind.REDIRECTING_FACTORY_CONSTRUCTOR) { + encoder.setType( + Key.EFFECTIVE_TARGET_TYPE, + element + .computeEffectiveTargetType(element.enclosingClass.thisType)); + encoder.setElement(Key.IMMEDIATE_REDIRECTION_TARGET, + element.immediateRedirectionTarget); + if (element.redirectionDeferredPrefix != null) { + encoder.setElement(Key.PREFIX, element.redirectionDeferredPrefix); + } + } } } } @@ -660,6 +691,8 @@ class ElementDeserializer { return new GenerativeConstructorElementZ(decoder); case SerializedElementKind.FACTORY_CONSTRUCTOR: return new FactoryConstructorElementZ(decoder); + case SerializedElementKind.REDIRECTING_FACTORY_CONSTRUCTOR: + return new RedirectingFactoryConstructorElementZ(decoder); case SerializedElementKind.FORWARDING_CONSTRUCTOR: return new ForwardingConstructorElementZ( decoder.getElement(Key.CLASS), decoder.getElement(Key.ELEMENT)); diff --git a/pkg/compiler/lib/src/serialization/keys.dart b/pkg/compiler/lib/src/serialization/keys.dart index c7599b20e90..dba7bec9004 100644 --- a/pkg/compiler/lib/src/serialization/keys.dart +++ b/pkg/compiler/lib/src/serialization/keys.dart @@ -25,7 +25,10 @@ class Key { static const Key DATA = const Key('data'); static const Key DEFAULT = const Key('default'); static const Key DEFAULTS = const Key('defaults'); + static const Key DEFINING_CONSTRUCTOR = const Key('definingConstructor'); static const Key DYNAMIC_USES = const Key('dynamic-uses'); + static const Key EFFECTIVE_TARGET = const Key('effectiveTarget'); + static const Key EFFECTIVE_TARGET_TYPE = const Key('effectiveTargetType'); static const Key ELEMENT = const Key('element'); static const Key ELEMENTS = const Key('elements'); static const Key EXECUTABLE_CONTEXT = const Key('executable-context'); @@ -40,6 +43,8 @@ class Key { static const Key GET_OR_SET = const Key('getOrSet'); static const Key GETTER = const Key('getter'); static const Key ID = const Key('id'); + static const Key IMMEDIATE_REDIRECTION_TARGET = + const Key('immediateRedirectionTarget'); static const Key IMPACTS = const Key('impacts'); static const Key IMPORT = const Key('import'); static const Key IMPORTS = const Key('imports'); @@ -58,6 +63,7 @@ class Key { static const Key IS_OPERATOR = const Key('isOperator'); static const Key IS_OPTIONAL = const Key('isOptional'); static const Key IS_PROXY = const Key('isProxy'); + static const Key IS_REDIRECTING = const Key('isRedirecting'); static const Key IS_SETTER = const Key('isSetter'); static const Key IS_UNNAMED_MIXIN_APPLICATION = const Key('isUnnamedMixinApplication'); diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart index e77d5c0925c..2bfb6e13987 100644 --- a/pkg/compiler/lib/src/serialization/modelz.dart +++ b/pkg/compiler/lib/src/serialization/modelz.dart @@ -30,6 +30,7 @@ import '../tree/tree.dart'; import '../util/util.dart' show Link, LinkBuilder; import 'keys.dart'; import 'serialization.dart'; +import 'serialization_util.dart'; /// Compute a [Link] from an [Iterable]. Link toLink(Iterable iterable) { @@ -1065,6 +1066,7 @@ abstract class ConstructorElementZ extends DeserializedElementZ MemberElementMixin implements ConstructorElement { ConstantConstructor _constantConstructor; + ConstructorElement _effectiveTarget; ConstructorElementZ(ObjectDecoder decoder) : super(decoder); @@ -1102,44 +1104,50 @@ abstract class ConstructorElementZ extends DeserializedElementZ @override AsyncMarker get asyncMarker => AsyncMarker.SYNC; - @override - InterfaceType computeEffectiveTargetType(InterfaceType newType) { - return _unsupported('computeEffectiveTargetType'); - } - @override ConstructorElement get definingConstructor { - return _unsupported('definingConstructor'); + String name = + _decoder.getString(Key.DEFINING_CONSTRUCTOR, isOptional: true); + if (name != null) { + return enclosingClass.superclass.lookupConstructor(name); + } + return null; } @override ConstructorElement get effectiveTarget { - return _unsupported('effectiveTarget'); + if (_effectiveTarget == null) { + _effectiveTarget = + _decoder.getElement(Key.EFFECTIVE_TARGET, isOptional: true); + if (_effectiveTarget == null) { + _effectiveTarget = this; + } + } + return _effectiveTarget; } @override - ConstructorElement get immediateRedirectionTarget { - return _unsupported('immediateRedirectionTarget'); - } + ConstructorElement get immediateRedirectionTarget => null; @override bool get isEffectiveTargetMalformed { return _unsupported('isEffectiveTargetMalformed'); } - @override - bool get isRedirectingFactory => _unsupported('isRedirectingFactory'); - - @override - bool get isRedirectingGenerative => _unsupported('isRedirectingGenerative'); - @override bool get isCyclicRedirection => _unsupported('isCyclicRedirection'); @override - PrefixElement get redirectionDeferredPrefix { - return _unsupported('redirectionDeferredPrefix'); - } + bool get isRedirectingFactory => false; + + @override + bool get isRedirectingGenerative => false; + + @override + PrefixElement get redirectionDeferredPrefix => null; + + @override + InterfaceType computeEffectiveTargetType(InterfaceType newType) => newType; } class GenerativeConstructorElementZ extends ConstructorElementZ { @@ -1149,8 +1157,7 @@ class GenerativeConstructorElementZ extends ConstructorElementZ { ElementKind get kind => ElementKind.GENERATIVE_CONSTRUCTOR; @override - bool get isEffectiveTargetMalformed => - _unsupported('isEffectiveTargetMalformed'); + bool get isRedirectingGenerative => _decoder.getBool(Key.IS_REDIRECTING); } class FactoryConstructorElementZ extends ConstructorElementZ { @@ -1158,10 +1165,66 @@ class FactoryConstructorElementZ extends ConstructorElementZ { @override ElementKind get kind => ElementKind.FACTORY_CONSTRUCTOR; +} + +class RedirectingFactoryConstructorElementZ extends ConstructorElementZ { + InterfaceType _effectiveTargetType; + ConstructorElement _immediateRedirectionTarget; + PrefixElement _redirectionDeferredPrefix; + + RedirectingFactoryConstructorElementZ(ObjectDecoder decoder) : super(decoder); @override - bool get isEffectiveTargetMalformed => - _unsupported('isEffectiveTargetMalformed'); + ElementKind get kind => ElementKind.FACTORY_CONSTRUCTOR; + + @override + bool get isRedirectingFactory => true; + + void _ensureEffectiveTarget() { + if (_effectiveTarget == null) { + _effectiveTarget = + _decoder.getElement(Key.EFFECTIVE_TARGET, isOptional: true); + if (_effectiveTarget == null) { + _effectiveTarget = this; + _effectiveTargetType = enclosingClass.thisType; + } else { + _effectiveTargetType = _decoder.getType(Key.EFFECTIVE_TARGET_TYPE); + } + } + } + + @override + ConstructorElement get effectiveTarget { + _ensureEffectiveTarget(); + return _effectiveTarget; + } + + @override + InterfaceType computeEffectiveTargetType(InterfaceType newType) { + _ensureEffectiveTarget(); + return _effectiveTargetType.substByContext(newType); + } + + void _ensureRedirection() { + if (_immediateRedirectionTarget == null) { + _immediateRedirectionTarget = + _decoder.getElement(Key.IMMEDIATE_REDIRECTION_TARGET); + _redirectionDeferredPrefix = + _decoder.getElement(Key.PREFIX, isOptional: true); + } + } + + @override + ConstructorElement get immediateRedirectionTarget { + _ensureRedirection(); + return _immediateRedirectionTarget; + } + + @override + PrefixElement get redirectionDeferredPrefix { + _ensureRedirection(); + return _redirectionDeferredPrefix; + } } class ForwardingConstructorElementZ extends ElementZ diff --git a/tests/compiler/dart2js/serialization_test.dart b/tests/compiler/dart2js/serialization_test.dart index 7edeb4c55da..5e091e91d5d 100644 --- a/tests/compiler/dart2js/serialization_test.dart +++ b/tests/compiler/dart2js/serialization_test.dart @@ -560,6 +560,24 @@ class ElementPropertyEquivalence extends BaseElementVisitor { element1.constantConstructor, element2.constantConstructor); } + check(element1, element2, 'isRedirectingGenerative', + element1.isRedirectingGenerative, element2.isRedirectingGenerative); + check(element1, element2, 'isRedirectingFactory', + element1.isRedirectingFactory, element2.isRedirectingFactory); + checkElementIdentities(element1, element2, 'effectiveTarget', + element1.effectiveTarget, element2.effectiveTarget); + checkElementIdentities(element1, element2, 'definingConstructor', + element1.definingConstructor, element2.definingConstructor); + check( + element1, element2, 'effectiveTargetType', + element1.computeEffectiveTargetType(element1.enclosingClass.thisType), + element2.computeEffectiveTargetType(element2.enclosingClass.thisType), + areTypesEquivalent); + checkElementIdentities(element1, element2, 'immediateRedirectionTarget', + element1.immediateRedirectionTarget, + element2.immediateRedirectionTarget); + checkElementIdentities(element1, element2, 'redirectionDeferredPrefix', + element1.redirectionDeferredPrefix, element2.redirectionDeferredPrefix); } @override