| Index: dart/lib/compiler/implementation/resolver.dart
|
| diff --git a/dart/lib/compiler/implementation/resolver.dart b/dart/lib/compiler/implementation/resolver.dart
|
| index 6ffc29fd5779555e3147ef72b6240d36586b77bc..c0e26f0e1f08135c79b6701963c62486c59f4a9c 100644
|
| --- a/dart/lib/compiler/implementation/resolver.dart
|
| +++ b/dart/lib/compiler/implementation/resolver.dart
|
| @@ -225,11 +225,40 @@ class ResolverTask extends CompilerTask {
|
| return result;
|
| }
|
|
|
| + void loadSupertypes(ClassElement cls, Node from) {
|
| + compiler.withCurrentElement(cls, () => measure(() {
|
| + if (cls.supertypesAreLoaded) return;
|
| + if (cls.isLoadingSupertypes) {
|
| + compiler.reportMessage(
|
| + compiler.spanFromNode(from),
|
| + MessageKind.CYCLIC_CLASS_HIERARCHY.error([cls.name]),
|
| + api.Diagnostic.ERROR);
|
| + cls.allSupertypes = const EmptyLink<Type>().prepend(
|
| + compiler.objectClass.computeType(compiler));
|
| + return;
|
| + }
|
| + cls.isLoadingSupertypes = true;
|
| + compiler.withCurrentElement(cls, () {
|
| + // TODO(ahe): Cache the node in cls.
|
| + cls.parseNode(compiler).accept(new ClassSupertypeResolver(compiler,
|
| + cls));
|
| + });
|
| + cls.isLoadingSupertypes = false;
|
| + cls.supertypesAreLoaded = true;
|
| + toResolve.add(cls);
|
| + }));
|
| + }
|
| +
|
| + /**
|
| + * Do not call this method directly. Instead use
|
| + * [:element.ensureResolved(compiler):].
|
| + */
|
| void resolveClass(ClassElement element) {
|
| - if (element.isResolved || element.isBeingResolved) return;
|
| - element.isBeingResolved = true;
|
| - measure(() {
|
| + compiler.withCurrentElement(element, () => measure(() {
|
| + assert(element.isBeingResolved && !element.isResolved);
|
| + loadSupertypes(element, null);
|
| ClassNode tree = element.parseNode(compiler);
|
| +
|
| ClassResolverVisitor visitor =
|
| new ClassResolverVisitor(compiler, element);
|
| visitor.visit(tree);
|
| @@ -242,7 +271,7 @@ class ResolverTask extends CompilerTask {
|
| }
|
|
|
| checkMembers(element);
|
| - });
|
| + }));
|
| }
|
|
|
| checkMembers(ClassElement cls) {
|
| @@ -288,7 +317,6 @@ class ResolverTask extends CompilerTask {
|
| api.Diagnostic.INFO);
|
| }
|
|
|
| -
|
| void checkValidOverride(Element member, Element superMember) {
|
| if (superMember === null) return;
|
| if (member.modifiers.isStatic()) {
|
| @@ -769,7 +797,7 @@ class TypeResolver {
|
| type = element.computeType(compiler);
|
| } else if (element.isClass()) {
|
| ClassElement cls = element;
|
| - if (!cls.isResolved) compiler.resolveClass(cls);
|
| + cls.ensureResolved(compiler);
|
| Link<Type> arguments =
|
| resolveTypeArguments(node, cls.typeVariables, scope,
|
| onFailure, whenResolved);
|
| @@ -1908,6 +1936,78 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
|
| }
|
| }
|
|
|
| +class ClassSupertypeResolver extends CommonResolverVisitor {
|
| + Scope context;
|
| + ClassElement classElement;
|
| +
|
| + ClassSupertypeResolver(Compiler compiler, ClassElement cls)
|
| + : context = new TopScope(cls.getLibrary()),
|
| + this.classElement = cls,
|
| + super(compiler);
|
| +
|
| + void visitClassNode(ClassNode node) {
|
| + if (node.superclass === null) {
|
| + // TODO(ahe): Handle this.
|
| + } else {
|
| + node.superclass.accept(this);
|
| + }
|
| + if (node.interfaces === null) {
|
| + // TODO(ahe): Can this happen?
|
| + } else {
|
| + node.interfaces.accept(this);
|
| + }
|
| + }
|
| +
|
| + void visitTypeAnnotation(TypeAnnotation node) {
|
| + node.typeName.accept(this);
|
| + }
|
| +
|
| + void visitIdentifier(Identifier node) {
|
| + Element element = context.lookup(node.source);
|
| + if (element === null) {
|
| + error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]);
|
| + } else if (!element.impliesType()) {
|
| + error(node, MessageKind.NOT_A_TYPE, [node]);
|
| + } else {
|
| + if (element.isClass()) {
|
| + compiler.resolver.loadSupertypes(element, node);
|
| + } else {
|
| + compiler.reportMessage(
|
| + compiler.spanFromNode(node),
|
| + MessageKind.TYPE_NAME_EXPECTED.error([]),
|
| + api.Diagnostic.ERROR);
|
| + }
|
| + }
|
| + }
|
| +
|
| + void visitNodeList(NodeList node) {
|
| + for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) {
|
| + visit(link.head);
|
| + }
|
| + }
|
| +
|
| + void visitSend(Send node) {
|
| + Identifier prefix = node.receiver.asIdentifier();
|
| + if (prefix === null) {
|
| + error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
|
| + return;
|
| + }
|
| + Element element = context.lookup(prefix.source);
|
| + if (element === null || element.kind !== ElementKind.PREFIX) {
|
| + error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
|
| + return;
|
| + }
|
| + PrefixElement prefixElement = element;
|
| + Identifier selector = node.selector.asIdentifier();
|
| + var e = prefixElement.lookupLocalMember(selector.source);
|
| + if (e === null || !e.impliesType()) {
|
| + error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]);
|
| + return;
|
| + }
|
| + compiler.resolver.loadSupertypes(e, node);
|
| + }
|
| +}
|
| +
|
| class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> {
|
| VariableDefinitions definitions;
|
| ResolverVisitor resolver;
|
|
|