| Index: compiler/java/com/google/dart/compiler/resolver/Resolver.java
|
| diff --git a/compiler/java/com/google/dart/compiler/resolver/Resolver.java b/compiler/java/com/google/dart/compiler/resolver/Resolver.java
|
| index 34802eb95eca9acb82fe2b9656be864a27eb51ac..7e1d1edc1a6d0142ce52ffd60a8344cf848f1bac 100644
|
| --- a/compiler/java/com/google/dart/compiler/resolver/Resolver.java
|
| +++ b/compiler/java/com/google/dart/compiler/resolver/Resolver.java
|
| @@ -234,9 +234,39 @@ public class Resolver {
|
| for (DartNode node : unit.getTopLevelNodes()) {
|
| node.accept(this);
|
| }
|
| + checkRedirectingFactoryConstructorsCycle(unit);
|
| return null;
|
| }
|
|
|
| + private void checkRedirectingFactoryConstructorsCycle(DartUnit unit) {
|
| + unit.accept(new ASTVisitor<Void>() {
|
| + @Override
|
| + public Void visitMethodDefinition(DartMethodDefinition node) {
|
| + MethodNodeElement element = node.getElement();
|
| + if (ElementKind.of(element) == ElementKind.CONSTRUCTOR) {
|
| + ConstructorElement constructor = (ConstructorElement) element;
|
| + if (hasRedirectingFactoryConstructorCycle(constructor)) {
|
| + onError(constructor.getNameLocation(),
|
| + ResolverErrorCode.REDIRECTION_CONSTRUCTOR_CYCLE);
|
| + }
|
| + }
|
| + return super.visitMethodDefinition(node);
|
| + }
|
| + });
|
| + }
|
| +
|
| + private boolean hasRedirectingFactoryConstructorCycle(ConstructorElement element) {
|
| + Set<ConstructorElement> constructors = Sets.newHashSet();
|
| + while (element != null) {
|
| + if (constructors.contains(element)) {
|
| + return true;
|
| + }
|
| + constructors.add(element);
|
| + element = element.getRedirectingFactoryConstructor();
|
| + }
|
| + return false;
|
| + }
|
| +
|
| @Override
|
| public Element visitFunctionTypeAlias(DartFunctionTypeAlias alias) {
|
| alias.getMetadata().accept(this);
|
| @@ -699,12 +729,14 @@ public class Resolver {
|
| TypeErrorCode.NO_SUCH_TYPE, ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
|
| switch (TypeKind.of(rcType)) {
|
| case INTERFACE:
|
| + ConstructorElement targetConstructor = null;
|
| Element element = recordType(rcTypeName, rcType);
|
| DartIdentifier rcName = node.getRedirectedConstructorName();
|
| if (rcName != null) {
|
| element = ((ClassElement) element).lookupConstructor(rcName.getName());
|
| switch (ElementKind.of(element)) {
|
| case CONSTRUCTOR:
|
| + targetConstructor = (ConstructorElement) element;
|
| recordElement(rcName, element);
|
| if (member.getModifiers().isConstant() && !element.getModifiers().isConstant()) {
|
| onError(rcName,
|
| @@ -712,7 +744,11 @@ public class Resolver {
|
| }
|
| break;
|
| }
|
| + } else {
|
| + targetConstructor = ((ClassElement) element).lookupConstructor(element.getName());
|
| }
|
| + Elements.setRedirectingFactoryConstructor(((ConstructorElement) member),
|
| + targetConstructor);
|
| break;
|
| default:
|
| onError(rcTypeName, ResolverErrorCode.REDIRECTION_CONSTRUCTOR_TARGET_TYPE);
|
|
|