| 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 697154ad9876ba88c29d0e6ce1d1de42fd0af671..204a795201e681adb45289e07875dde47532462d 100644
|
| --- a/compiler/java/com/google/dart/compiler/resolver/Resolver.java
|
| +++ b/compiler/java/com/google/dart/compiler/resolver/Resolver.java
|
| @@ -18,6 +18,7 @@ import com.google.dart.compiler.ast.DartBreakStatement;
|
| import com.google.dart.compiler.ast.DartCatchBlock;
|
| import com.google.dart.compiler.ast.DartClass;
|
| import com.google.dart.compiler.ast.DartClassMember;
|
| +import com.google.dart.compiler.ast.DartContinueStatement;
|
| import com.google.dart.compiler.ast.DartDoWhileStatement;
|
| import com.google.dart.compiler.ast.DartDoubleLiteral;
|
| import com.google.dart.compiler.ast.DartExpression;
|
| @@ -69,6 +70,7 @@ import com.google.dart.compiler.ast.Modifiers;
|
| import com.google.dart.compiler.common.HasSourceInfo;
|
| import com.google.dart.compiler.common.SourceInfo;
|
| import com.google.dart.compiler.parser.Token;
|
| +import com.google.dart.compiler.resolver.LabelElement.LabeledStatementType;
|
| import com.google.dart.compiler.type.InterfaceType;
|
| import com.google.dart.compiler.type.InterfaceType.Member;
|
| import com.google.dart.compiler.type.Type;
|
| @@ -753,17 +755,22 @@ public class Resolver {
|
|
|
| @Override
|
| public Element visitLabel(DartLabel x) {
|
| - LabelElement currentLabel = Elements.labelElement(x, x.getName(), innermostFunction);
|
| - recordElement(x.getLabel(), currentLabel);
|
| - recordElement(x, currentLabel);
|
| - x.visitChildren(this);
|
| - if (!labelsInScopes.contains(currentLabel)) {
|
| - // TODO(zundel): warning, not type error.
|
| - // topLevelContext.typeError(x, DartCompilerErrorCode.USELESS_LABEL, x.getName());
|
| - } else if (!referencedLabels.contains(currentLabel)) {
|
| - // TODO(zundel): warning, not type error.
|
| - // topLevelContext.typeError(x, DartCompilerErrorCode.UNREFERENCED_LABEL, x.getName());
|
| + DartNode parent = x.getParent();
|
| + if (!(parent instanceof DartSwitchMember)) {
|
| + LabelElement labelElement;
|
| + DartStatement childStatement = x.getStatement();
|
| + while (childStatement instanceof DartLabel) {
|
| + childStatement = ((DartLabel)childStatement).getStatement();
|
| + }
|
| + if (childStatement instanceof DartSwitchStatement) {
|
| + labelElement = Elements.switchLabelElement(x, x.getName(), innermostFunction);
|
| + } else {
|
| + labelElement = Elements.statementLabelElement(x, x.getName(), innermostFunction);
|
| + }
|
| + recordElement(x.getLabel(), labelElement);
|
| + recordElement(x, labelElement);
|
| }
|
| + x.visitChildren(this);
|
| return null;
|
| }
|
|
|
| @@ -903,29 +910,17 @@ public class Resolver {
|
| return null;
|
| }
|
|
|
| - private void addLabelToStatement(DartStatement x) {
|
| + private void addLabelToStatement(DartNode x) {
|
| DartNode parent = x.getParent();
|
| while (parent instanceof DartLabel) {
|
| - LabelElement currentLabel = ((DartLabel) parent).getElement();
|
| + DartLabel label = (DartLabel) parent;
|
| + LabelElement currentLabel = label.getElement();
|
| getContext().getScope().addLabel(currentLabel);
|
| labelsInScopes.add(currentLabel);
|
| parent = parent.getParent();
|
| }
|
| }
|
|
|
| - private void addLabelToSwitchMember(DartSwitchMember x) {
|
| - DartLabel label = x.getLabel();
|
| - if (label != null) {
|
| - LabelElement currentLabel = label.getElement(); // TODO(zundel): Y U NO HAVE ELEMENT?
|
| - if (getContext().getScope().hasLocalLabel(label.getName())) {
|
| - onError(label, ResolverErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT);
|
| - }
|
| - getContext().getScope().addLabel(currentLabel);
|
| - labelsInScopes.add(currentLabel);
|
| - }
|
| - }
|
| -
|
| -
|
| @Override
|
| public Element visitForStatement(DartForStatement x) {
|
| getContext().pushScope("<for>");
|
| @@ -940,6 +935,11 @@ public class Resolver {
|
| public Element visitSwitchStatement(DartSwitchStatement x) {
|
| getContext().pushScope("<switch>");
|
| addLabelToStatement(x);
|
| + // The scope of a label on the case statement is the case statement itself. These labels
|
| + // need to be resolved before the continue <label>; statements can be resolved.
|
| + for (DartSwitchMember member : x.getMembers()) {
|
| + recordSwitchMamberLabel(member);
|
| + }
|
| x.visitChildren(this);
|
| getContext().popScope();
|
| return null;
|
| @@ -950,11 +950,24 @@ public class Resolver {
|
| getContext().pushScope("<switch member>");
|
| x.visitChildren(this);
|
| getContext().popScope();
|
| - // The scope of a label on the case statement is the case statement itself.
|
| - addLabelToSwitchMember(x);
|
| return null;
|
| }
|
|
|
| + private void recordSwitchMamberLabel(DartSwitchMember x) {
|
| + DartLabel label = x.getLabel();
|
| + if (label != null) {
|
| + LabelElement labelElement = Elements.switchMemberLabelElement(label, label.getName(),
|
| + innermostFunction);
|
| + recordElement(label.getLabel(), labelElement);
|
| + recordElement(label, labelElement);
|
| + if (getContext().getScope().hasLocalLabel(label.getName())) {
|
| + onError(label, ResolverErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT);
|
| + }
|
| + getContext().getScope().addLabel(labelElement);
|
| + labelsInScopes.add(labelElement);
|
| + }
|
| + }
|
| +
|
| @Override
|
| public Element visitThisExpression(DartThisExpression x) {
|
| if (ElementKind.of(currentHolder).equals(ElementKind.LIBRARY)) {
|
| @@ -1568,6 +1581,16 @@ public class Resolver {
|
| Element element = getContext().getScope().findLabel(x.getTargetName(), innermostFunction);
|
| if (ElementKind.of(element).equals(ElementKind.LABEL)) {
|
| LabelElement labelElement = (LabelElement) element;
|
| + if (x instanceof DartBreakStatement
|
| + && labelElement.getStatementType() == LabeledStatementType.SWITCH_MEMBER_STATEMENT) {
|
| + onError(x.getLabel(), ResolverErrorCode.BREAK_LABEL_RESOLVES_TO_CASE_OR_DEFAULT);
|
| + return null;
|
| + }
|
| + if (x instanceof DartContinueStatement
|
| + && labelElement.getStatementType() == LabeledStatementType.SWITCH_STATEMENT) {
|
| + onError(x.getLabel(), ResolverErrorCode.CONTINUE_LABEL_RESOLVES_TO_SWITCH);
|
| + return null;
|
| + }
|
| MethodElement enclosingFunction = (labelElement).getEnclosingFunction();
|
| if (enclosingFunction == innermostFunction) {
|
| referencedLabels.add(labelElement);
|
| @@ -1615,7 +1638,7 @@ public class Resolver {
|
|
|
| case CONSTRUCTOR:
|
| onError(errorNode, ResolverErrorCode.IS_A_CONSTRUCTOR, classOrLibrary.getName(),
|
| - name);
|
| + name);
|
| break;
|
|
|
| case METHOD: {
|
|
|