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; |