Chromium Code Reviews| 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 a5cc401ac61b30e4ca1e198ca9051e9b9348ac47..8222b4a54ce38bb68b3bcf0acc046cae4a18242e 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart |
| @@ -3466,6 +3466,92 @@ class ResolverVisitor extends MappingVisitor<Element> { |
| visit(node.expression); |
| } |
| + DartType typeOfConstant(Constant constant) { |
| + if (constant.isInt()) return compiler.intClass.computeType(compiler); |
| + if (constant.isBool()) return compiler.boolClass.computeType(compiler); |
| + if (constant.isDouble()) return compiler.doubleClass.computeType(compiler); |
| + if (constant.isString()) return compiler.stringClass.computeType(compiler); |
| + if (constant.isNull()) return compiler.nullClass.computeType(compiler); |
| + if (constant.isFunction()) { |
| + return compiler.functionClass.computeType(compiler); |
| + } |
| + assert(constant.isObject()); |
| + ObjectConstant objectConstant = constant; |
| + return objectConstant.type; |
| + } |
| + |
| + bool overridesEquals(DartType type) { |
| + ClassElement cls = type.element; |
| + Element equals = cls.lookupMember('=='); |
| + return equals.getEnclosingClass() != compiler.objectClass; |
| + } |
| + |
| + void checkCaseExpressions(SwitchStatement node) { |
| + TargetElement breakElement = getOrCreateTargetElement(node); |
| + Map<String, LabelElement> continueLabels = <String, LabelElement>{}; |
| + |
| + Link<Node> cases = node.cases.nodes; |
| + SwitchCase switchCase = cases.head; |
| + CaseMatch firstCase = null; |
| + DartType firstCaseType = null; |
| + bool hasReportedProblem = false; |
| + |
| + for (Link<Node> cases = node.cases.nodes; |
| + !cases.isEmpty; |
| + cases = cases.tail) { |
| + SwitchCase switchCase = cases.head; |
| + |
| + for (Node labelOrCase in switchCase.labelsAndCases) { |
| + CaseMatch caseMatch = labelOrCase.asCaseMatch(); |
| + if (caseMatch == null) continue; |
| + |
| + // Analyze the constant. |
| + Constant constant = mapping.getConstant(caseMatch.expression); |
| + assert(invariant(node, constant != null, |
| + message: 'No constant computed for $node')); |
| + |
| + DartType caseType = typeOfConstant(constant); |
| + |
| + if (firstCaseType == null) { |
| + firstCase = caseMatch; |
| + firstCaseType = caseType; |
| + |
| + // We only report the bad type on the first class element. All others |
| + // get a "type differs" error. |
| + if (caseType.element == compiler.doubleClass) { |
| + compiler.reportError(node, MessageKind.SWITCH_CASE_FORBIDDEN, |
| + {'type': "double"}); |
| + } else if (caseType.element == compiler.functionClass) { |
| + compiler.reportError(node, MessageKind.SWITCH_CASE_FORBIDDEN, |
| + {'type': "Function"}); |
| + } else if (constant.isObject() && overridesEquals(caseType)) { |
| + compiler.reportError(firstCase.expression, |
| + MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS, |
| + {'type': caseType}); |
| + } |
| + } else { |
| + if (caseType != firstCaseType) { |
| + if (!hasReportedProblem) { |
| + compiler.reportError( |
| + node, |
| + MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL, |
| + {'type': firstCaseType}); |
| + compiler.reportInfo( |
| + firstCase.expression, |
| + MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE, |
| + {'type': firstCaseType}); |
| + hasReportedProblem = true; |
| + } |
| + compiler.reportInfo( |
| + caseMatch.expression, |
| + MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE, |
| + {'type': caseType}); |
| + } |
| + } |
| + } |
| + } |
| + } |
| + |
| visitSwitchStatement(SwitchStatement node) { |
| node.expression.accept(this); |
| @@ -3517,6 +3603,10 @@ class ResolverVisitor extends MappingVisitor<Element> { |
| } |
| } |
| + addDeferredAction(enclosingElement, () { |
|
floitsch
2014/02/28 22:00:27
I need the constants to be evaluated. I'm not sure
|
| + checkCaseExpressions(node); |
| + }); |
| + |
| statementScope.enterSwitch(breakElement, continueLabels); |
| node.cases.accept(this); |
| statementScope.exitSwitch(); |