| Index: sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| index 568ae79229f3a14c7a3cde9e79e84ff009b63f3e..75f3f8363c4cf24dba4cd1d3ca3f2c8cc639dd7c 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| @@ -386,7 +386,7 @@ class ResolverTask extends CompilerTask {
|
| * Warning: do not call this method directly. It should only be
|
| * called by [resolveClass] and [ClassSupertypeResolver].
|
| */
|
| - void loadSupertypes(ClassElement cls, Node from) {
|
| + void loadSupertypes(ClassElement cls, Spannable from) {
|
| compiler.withCurrentElement(cls, () => measure(() {
|
| if (cls.supertypeLoadState == STATE_DONE) return;
|
| if (cls.supertypeLoadState == STATE_STARTED) {
|
| @@ -404,8 +404,8 @@ class ResolverTask extends CompilerTask {
|
| cls.supertypeLoadState = STATE_STARTED;
|
| compiler.withCurrentElement(cls, () {
|
| // TODO(ahe): Cache the node in cls.
|
| - cls.parseNode(compiler).accept(new ClassSupertypeResolver(compiler,
|
| - cls));
|
| + cls.parseNode(compiler).accept(
|
| + new ClassSupertypeResolver(compiler, cls));
|
| if (cls.supertypeLoadState != STATE_DONE) {
|
| cls.supertypeLoadState = STATE_DONE;
|
| }
|
| @@ -418,17 +418,6 @@ class ResolverTask extends CompilerTask {
|
| ClassElement currentlyResolvedClass;
|
| Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>();
|
|
|
| - void resolveMixinApplication(MixinApplicationElement element) {
|
| - // TODO(kasperl): Implement this.
|
| - assert(element.resolutionState == STATE_NOT_STARTED);
|
| - element.resolutionState = STATE_STARTED;
|
| - compiler.reportMessage(
|
| - compiler.spanFromSpannable(element.cachedNode),
|
| - MessageKind.GENERIC.error(['unimplemented mixin application']),
|
| - Diagnostic.ERROR);
|
| - element.resolutionState = STATE_DONE;
|
| - }
|
| -
|
| /**
|
| * Resolve the class [element].
|
| *
|
| @@ -2748,24 +2737,8 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
|
| // resolve this class again.
|
| resolveTypeVariableBounds(node.typeParameters);
|
|
|
| - // Find super type.
|
| - DartType supertype = null;
|
| - if (node.superclass != null) {
|
| - supertype = typeResolver.resolveTypeAnnotation(node.superclass, scope,
|
| - element, onFailure: error);
|
| - }
|
| - if (supertype != null) {
|
| - if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) {
|
| - // Error has already been reported.
|
| - } else if (!identical(supertype.kind, TypeKind.INTERFACE)) {
|
| - // TODO(johnniwinther): Handle dynamic.
|
| - error(node.superclass.typeName, MessageKind.CLASS_NAME_EXPECTED, []);
|
| - } else if (isBlackListed(supertype)) {
|
| - error(node.superclass, MessageKind.CANNOT_EXTEND, [supertype]);
|
| - } else {
|
| - element.supertype = supertype;
|
| - }
|
| - }
|
| + // Resolve super type and deal with the Object class nicely.
|
| + element.supertype = resolveSupertype(element, node.superclass);
|
| final objectElement = compiler.objectClass;
|
| if (!identical(element, objectElement) && element.supertype == null) {
|
| if (objectElement == null) {
|
| @@ -2776,6 +2749,7 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
|
| }
|
| element.supertype = objectElement.computeType(compiler);
|
| }
|
| +
|
| assert(element.interfaces == null);
|
| Link<DartType> interfaces = const Link<DartType>();
|
| for (Link<Node> link = node.interfaces.nodes;
|
| @@ -2820,10 +2794,61 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
|
| if (node.defaultClause != null) {
|
| element.defaultClass = visit(node.defaultClause);
|
| }
|
| - addDefaultConstructorIfNeeded(element);
|
| + element.addDefaultConstructorIfNeeded(compiler);
|
| return element.computeType(compiler);
|
| }
|
|
|
| + DartType visitMixinApplication(MixinApplication node) {
|
| + compiler.ensure(element != null);
|
| + compiler.ensure(element.resolutionState == STATE_STARTED);
|
| +
|
| + // Generate anonymous mixin application elements for the
|
| + // intermediate mixin applications (excluding the last).
|
| + DartType supertype = resolveSupertype(element, node.superclass);
|
| + Link<Node> link = node.mixins.nodes;
|
| + while (!link.tail.isEmpty) {
|
| + supertype = applyMixin(supertype, visit(link.head));
|
| + link = link.tail;
|
| + }
|
| + doApplyMixinTo(element, supertype, visit(link.head));
|
| + return element.computeType(compiler);
|
| + }
|
| +
|
| + DartType applyMixin(DartType supertype, DartType mixinType) {
|
| + String superName = supertype.name.slowToString();
|
| + String mixinName = mixinType.name.slowToString();
|
| + // TODO(kasperl): This is a little bit weird. Maybe we should
|
| + // restructure the parsed nodes for mixin applications to better
|
| + // match the nesting implied by the list of mixins so that each
|
| + // mixin application element could get it's own proper node.
|
| + MixinApplication fakeTree = element.parseNode(compiler);
|
| + ClassElement mixinApplication = new MixinApplicationElementX(
|
| + new SourceString("${superName}_${mixinName}"),
|
| + element.getCompilationUnit(),
|
| + compiler.getNextFreeClassId(),
|
| + fakeTree);
|
| + doApplyMixinTo(mixinApplication, supertype, mixinType);
|
| + mixinApplication.resolutionState = STATE_DONE;
|
| + return mixinApplication.computeType(compiler);
|
| + }
|
| +
|
| + void doApplyMixinTo(ClassElement mixinApplication,
|
| + DartType supertype,
|
| + DartType mixinType) {
|
| + assert(mixinApplication.supertype == null);
|
| + mixinApplication.supertype = supertype;
|
| +
|
| + assert(mixinApplication.interfaces == null);
|
| + mixinApplication.interfaces = const Link<DartType>();
|
| +
|
| + assert(element.mixin == null);
|
| + mixinApplication.mixin = mixinType.element;
|
| + mixinApplication.mixin.ensureResolved(compiler);
|
| + mixinApplication.addDefaultConstructorIfNeeded(compiler);
|
| + calculateAllSupertypes(mixinApplication);
|
| + }
|
| +
|
| +
|
| // TODO(johnniwinther): Remove when default class is no longer supported.
|
| DartType visitTypeAnnotation(TypeAnnotation node) {
|
| return visit(node.typeName);
|
| @@ -2874,9 +2899,30 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
|
| return e.computeType(compiler);
|
| }
|
|
|
| + DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) {
|
| + DartType supertype;
|
| + if (superclass != null) {
|
| + supertype = typeResolver.resolveTypeAnnotation(
|
| + superclass, scope, cls, onFailure: error);
|
| + }
|
| + if (supertype != null) {
|
| + if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) {
|
| + // Error has already been reported.
|
| + } else if (!identical(supertype.kind, TypeKind.INTERFACE)) {
|
| + // TODO(johnniwinther): Handle dynamic.
|
| + error(superclass.typeName, MessageKind.CLASS_NAME_EXPECTED, []);
|
| + return null;
|
| + } else if (isBlackListed(supertype)) {
|
| + error(superclass, MessageKind.CANNOT_EXTEND, [supertype]);
|
| + return null;
|
| + }
|
| + }
|
| + return supertype;
|
| + }
|
| +
|
| void calculateAllSupertypes(ClassElement cls) {
|
| - // TODO(karlklose): check if type arguments match, if a classelement occurs
|
| - // more than once in the supertypes.
|
| + // TODO(karlklose): Check if type arguments match, if a class
|
| + // element occurs more than once in the supertypes.
|
| if (cls.allSupertypes != null) return;
|
| final DartType supertype = cls.supertype;
|
| if (supertype != null) {
|
| @@ -2914,17 +2960,6 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
|
| }
|
| }
|
|
|
| - /**
|
| - * Add a synthetic nullary constructor if there are no other
|
| - * constructors.
|
| - */
|
| - void addDefaultConstructorIfNeeded(ClassElement element) {
|
| - if (element.hasConstructor) return;
|
| - FunctionElement constructor =
|
| - new SynthesizedConstructorElementX.forDefault(element, compiler);
|
| - element.addToScope(constructor, compiler);
|
| - }
|
| -
|
| isBlackListed(DartType type) {
|
| LibraryElement lib = element.getLibrary();
|
| return
|
| @@ -2956,6 +2991,12 @@ class ClassSupertypeResolver extends CommonResolverVisitor {
|
| element.ensureResolved(compiler);
|
| }
|
|
|
| + void visitNodeList(NodeList node) {
|
| + for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
|
| + link.head.accept(this);
|
| + }
|
| + }
|
| +
|
| void visitClassNode(ClassNode node) {
|
| if (node.superclass == null) {
|
| if (!identical(classElement, compiler.objectClass)) {
|
| @@ -2964,11 +3005,12 @@ class ClassSupertypeResolver extends CommonResolverVisitor {
|
| } else {
|
| node.superclass.accept(this);
|
| }
|
| - for (Link<Node> link = node.interfaces.nodes;
|
| - !link.isEmpty;
|
| - link = link.tail) {
|
| - link.head.accept(this);
|
| - }
|
| + visitNodeList(node.interfaces);
|
| + }
|
| +
|
| + void visitMixinApplication(MixinApplication node) {
|
| + node.superclass.accept(this);
|
| + visitNodeList(node.mixins);
|
| }
|
|
|
| void visitTypeAnnotation(TypeAnnotation node) {
|
|
|