| 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 ccf2e5d3e158417e7ee6228637df5e7c0b806f24..cf75138a5e7422bb3b8e65b4b26d1b471c591697 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| @@ -675,12 +675,14 @@ class ResolverTask extends CompilerTask {
|
| compiler.reportError(from, MessageKind.CYCLIC_CLASS_HIERARCHY,
|
| {'className': cls.name});
|
| cls.supertypeLoadState = STATE_DONE;
|
| + cls.hasIncompleteHierarchy = true;
|
| cls.allSupertypesAndSelf =
|
| compiler.objectClass.allSupertypesAndSelf.extendClass(
|
| cls.computeType(compiler));
|
| cls.supertype = cls.allSupertypes.head;
|
| assert(invariant(from, cls.supertype != null,
|
| message: 'Missing supertype on cyclic class $cls.'));
|
| + cls.interfaces = const Link<DartType>();
|
| return;
|
| }
|
| cls.supertypeLoadState = STATE_STARTED;
|
| @@ -697,8 +699,40 @@ class ResolverTask extends CompilerTask {
|
|
|
| // TODO(johnniwinther): Remove this queue when resolution has been split into
|
| // syntax and semantic resolution.
|
| - ClassElement currentlyResolvedClass;
|
| + TypeDeclarationElement currentlyResolvedTypeDeclaration;
|
| Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>();
|
| + Queue<ClassElement> pendingClassesToBePostProcessed =
|
| + new Queue<ClassElement>();
|
| +
|
| + /// Resolve [element] using [resolveTypeDeclaration].
|
| + ///
|
| + /// This methods ensure that class declarations encountered through type
|
| + /// annotations during the resolution of [element] are resolved after
|
| + /// [element] has been resolved.
|
| + // TODO(johnniwinther): Encapsulate this functionality in a
|
| + // 'TypeDeclarationResolver'.
|
| + _resolveTypeDeclaration(TypeDeclarationElement element,
|
| + resolveTypeDeclaration()) {
|
| + TypeDeclarationElement previousResolvedTypeDeclaration =
|
| + currentlyResolvedTypeDeclaration;
|
| + currentlyResolvedTypeDeclaration = element;
|
| + var result = resolveTypeDeclaration();
|
| + if (previousResolvedTypeDeclaration == null) {
|
| + do {
|
| + while (!pendingClassesToBeResolved.isEmpty) {
|
| + pendingClassesToBeResolved.removeFirst().ensureResolved(compiler);
|
| + }
|
| + while (!pendingClassesToBePostProcessed.isEmpty) {
|
| + _postProcessClassElement(
|
| + pendingClassesToBePostProcessed.removeFirst());
|
| + }
|
| + } while (!pendingClassesToBeResolved.isEmpty);
|
| + assert(pendingClassesToBeResolved.isEmpty);
|
| + assert(pendingClassesToBePostProcessed.isEmpty);
|
| + }
|
| + currentlyResolvedTypeDeclaration = previousResolvedTypeDeclaration;
|
| + return result;
|
| + }
|
|
|
| /**
|
| * Resolve the class [element].
|
| @@ -712,21 +746,15 @@ class ResolverTask extends CompilerTask {
|
| * [:element.ensureResolved(compiler):].
|
| */
|
| void resolveClass(ClassElement element) {
|
| - ClassElement previousResolvedClass = currentlyResolvedClass;
|
| - currentlyResolvedClass = element;
|
| - // TODO(johnniwinther): Store the mapping in the resolution enqueuer.
|
| - TreeElementMapping mapping = new TreeElementMapping(element);
|
| - resolveClassInternal(element, mapping);
|
| - if (previousResolvedClass == null) {
|
| - while (!pendingClassesToBeResolved.isEmpty) {
|
| - pendingClassesToBeResolved.removeFirst().ensureResolved(compiler);
|
| - }
|
| - }
|
| - currentlyResolvedClass = previousResolvedClass;
|
| + _resolveTypeDeclaration(element, () {
|
| + // TODO(johnniwinther): Store the mapping in the resolution enqueuer.
|
| + TreeElementMapping mapping = new TreeElementMapping(element);
|
| + resolveClassInternal(element, mapping);
|
| + });
|
| }
|
|
|
| void _ensureClassWillBeResolved(ClassElement element) {
|
| - if (currentlyResolvedClass == null) {
|
| + if (currentlyResolvedTypeDeclaration == null) {
|
| element.ensureResolved(compiler);
|
| } else {
|
| pendingClassesToBeResolved.add(element);
|
| @@ -747,6 +775,7 @@ class ResolverTask extends CompilerTask {
|
| visitor.visit(tree);
|
| element.resolutionState = STATE_DONE;
|
| compiler.onClassResolved(element);
|
| + pendingClassesToBePostProcessed.add(element);
|
| }));
|
| if (element.isPatched) {
|
| // Ensure handling patch after origin.
|
| @@ -769,6 +798,9 @@ class ResolverTask extends CompilerTask {
|
| // TODO(johnniwinther): Check matching type variables and
|
| // empty extends/implements clauses.
|
| }
|
| + }
|
| +
|
| + void _postProcessClassElement(BaseClassElementX element) {
|
| for (MetadataAnnotation metadata in element.metadata) {
|
| metadata.ensureResolved(compiler);
|
| if (!element.isProxy && metadata.value == compiler.proxyConstant) {
|
| @@ -790,6 +822,8 @@ class ResolverTask extends CompilerTask {
|
| });
|
| }
|
| });
|
| +
|
| + MembersCreator.computeClassMembers(compiler, element);
|
| }
|
|
|
| void checkClass(ClassElement element) {
|
| @@ -993,7 +1027,6 @@ class ResolverTask extends CompilerTask {
|
| bool isMinus = false;
|
| int requiredParameterCount;
|
| MessageKind messageKind;
|
| - FunctionSignature signature = function.computeSignature(compiler);
|
| if (identical(value, 'unary-')) {
|
| isMinus = true;
|
| messageKind = MessageKind.MINUS_OPERATOR_BAD_ARITY;
|
| @@ -1095,10 +1128,7 @@ class ResolverTask extends CompilerTask {
|
| errorMessage,
|
| {'memberName': contextElement.name,
|
| 'className': contextElement.getEnclosingClass().name});
|
| - compiler.reportMessage(
|
| - compiler.spanFromElement(contextElement),
|
| - contextMessage.error(),
|
| - Diagnostic.INFO);
|
| + compiler.reportInfo(contextElement, contextMessage);
|
| }
|
|
|
| void checkValidOverride(Element member, Element superMember) {
|
| @@ -1166,18 +1196,20 @@ class ResolverTask extends CompilerTask {
|
|
|
| TreeElements resolveTypedef(TypedefElementX element) {
|
| if (element.isResolved) return element.mapping;
|
| - TreeElementMapping mapping = new TreeElementMapping(element);
|
| - // TODO(johnniwinther): Store the mapping in the resolution enqueuer.
|
| - element.mapping = mapping;
|
| - return compiler.withCurrentElement(element, () {
|
| - return measure(() {
|
| - Typedef node =
|
| - compiler.parser.measure(() => element.parseNode(compiler));
|
| - TypedefResolverVisitor visitor =
|
| - new TypedefResolverVisitor(compiler, element, mapping);
|
| - visitor.visit(node);
|
| -
|
| - return mapping;
|
| + return _resolveTypeDeclaration(element, () {
|
| + TreeElementMapping mapping = new TreeElementMapping(element);
|
| + // TODO(johnniwinther): Store the mapping in the resolution enqueuer.
|
| + element.mapping = mapping;
|
| + return compiler.withCurrentElement(element, () {
|
| + return measure(() {
|
| + Typedef node =
|
| + compiler.parser.measure(() => element.parseNode(compiler));
|
| + TypedefResolverVisitor visitor =
|
| + new TypedefResolverVisitor(compiler, element, mapping);
|
| + visitor.visit(node);
|
| +
|
| + return mapping;
|
| + });
|
| });
|
| });
|
| }
|
| @@ -3863,8 +3895,11 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
|
| }
|
| }
|
|
|
| - assert(element.interfaces == null);
|
| - element.interfaces = resolveInterfaces(node.interfaces, node.superclass);
|
| + if (element.interfaces == null) {
|
| + element.interfaces = resolveInterfaces(node.interfaces, node.superclass);
|
| + } else {
|
| + assert(invariant(element, element.hasIncompleteHierarchy));
|
| + }
|
| calculateAllSupertypes(element);
|
|
|
| if (!element.hasConstructor) {
|
| @@ -3938,7 +3973,7 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
|
| element.getCompilationUnit(),
|
| compiler.getNextFreeClassId(),
|
| node,
|
| - Modifiers.EMPTY); // TODO(kasperl): Should this be abstract?
|
| + new Modifiers.withFlags(new NodeList.empty(), Modifiers.FLAG_ABSTRACT));
|
| // Create synthetic type variables for the mixin application.
|
| LinkBuilder<DartType> typeVariablesBuilder = new LinkBuilder<DartType>();
|
| element.typeVariables.forEach((TypeVariableType type) {
|
| @@ -4010,13 +4045,20 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
|
| // The class that is the result of a mixin application implements
|
| // the interface of the class that was mixed in so always prepend
|
| // that to the interface list.
|
| -
|
| - interfaces = interfaces.prepend(mixinType);
|
| - assert(mixinApplication.interfaces == null);
|
| - mixinApplication.interfaces = interfaces;
|
| + if (mixinApplication.interfaces == null) {
|
| + if (mixinType.kind == TypeKind.INTERFACE) {
|
| + // Avoid malformed types in the interfaces.
|
| + interfaces = interfaces.prepend(mixinType);
|
| + }
|
| + mixinApplication.interfaces = interfaces;
|
| + } else {
|
| + assert(invariant(mixinApplication,
|
| + mixinApplication.hasIncompleteHierarchy));
|
| + }
|
|
|
| ClassElement superclass = supertype.element;
|
| if (mixinType.kind != TypeKind.INTERFACE) {
|
| + mixinApplication.hasIncompleteHierarchy = true;
|
| mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf;
|
| return;
|
| }
|
|
|