Handle forwarding constructors

Handle serialization of forwarding constructors that are defined by
forwarding constructors:

  class A {}
  class B {}
  class C {}
  class D = A with B, C;

The default constructor of D is a forwarding constructor defined by the
default constructor of its super type A+B, which itself is a forwarding
constructor. Thus, the defining constructor might itself be synthesized
and therefore serialized indirectly.

R=het@google.com

Review URL: https://codereview.chromium.org/2105183003 .
This commit is contained in:
Johnni Winther 2016-07-01 10:28:50 +02:00
parent 95e6dde715
commit 2f1cc9e958
3 changed files with 34 additions and 7 deletions

View file

@ -423,7 +423,8 @@ class ConstructorSerializer implements ElementSerializer {
SerializedElementKind kind) {
SerializerUtil.serializeParentRelation(element, encoder);
if (kind == SerializedElementKind.FORWARDING_CONSTRUCTOR) {
encoder.setElement(Key.ELEMENT, element.definingConstructor);
serializeElementReference(element.enclosingClass, Key.ELEMENT, Key.NAME,
encoder, element.definingConstructor);
} else {
SerializerUtil.serializeMetadata(element, encoder);
encoder.setType(Key.TYPE, element.type);
@ -773,8 +774,10 @@ class ElementDeserializer {
case SerializedElementKind.REDIRECTING_FACTORY_CONSTRUCTOR:
return new RedirectingFactoryConstructorElementZ(decoder);
case SerializedElementKind.FORWARDING_CONSTRUCTOR:
return new ForwardingConstructorElementZ(
decoder.getElement(Key.CLASS), decoder.getElement(Key.ELEMENT));
ClassElement cls = decoder.getElement(Key.CLASS);
Element definingConstructor =
deserializeElementReference(cls, Key.ELEMENT, Key.NAME, decoder);
return new ForwardingConstructorElementZ(cls, definingConstructor);
case SerializedElementKind.TOPLEVEL_FUNCTION:
return new TopLevelFunctionElementZ(decoder);
case SerializedElementKind.STATIC_FUNCTION:

View file

@ -506,10 +506,19 @@ Element deserializeElementReference(
if (elementName == null) {
return null;
}
assert(invariant(NO_LOCATION_SPANNABLE, context.isConstructor,
message: "Unexpected reference of forwarding constructor "
"'${elementName}' from $context."));
ClassElement superclass = context.enclosingClass.superclass;
ClassElement cls;
if (context is ClassElement) {
assert(invariant(NO_LOCATION_SPANNABLE, context.isNamedMixinApplication,
message: "Unexpected reference of forwarding constructor "
"'${elementName}' from $context."));
cls = context;
} else {
assert(invariant(NO_LOCATION_SPANNABLE, context.isConstructor,
message: "Unexpected reference of forwarding constructor "
"'${elementName}' from $context."));
cls = context.enclosingClass;
}
ClassElement superclass = cls.superclass;
element = superclass.lookupConstructor(elementName);
assert(invariant(NO_LOCATION_SPANNABLE, element != null,
message: "Unresolved reference of forwarding constructor "

View file

@ -452,6 +452,21 @@ class A {
final field1;
const A(a) : this.field1 = a + 1.0;
}
''',
}),
const Test('Forwarding constructor defined by forwarding constructor', const {
'main.dart': '''
import 'a.dart';
main() => new C();
''',
}, preserializedSourceFiles: const {
'a.dart': '''
class A {}
class B {}
class C {}
class D = A with B, C;
''',
}),
];