KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > CaseStatement


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.ast;
12
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
15 import org.eclipse.jdt.internal.compiler.codegen.CaseLabel;
16 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
17 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
18 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
19 import org.eclipse.jdt.internal.compiler.impl.Constant;
20 import org.eclipse.jdt.internal.compiler.impl.IntConstant;
21 import org.eclipse.jdt.internal.compiler.lookup.Binding;
22 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
23 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
24 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
25 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
26
27 public class CaseStatement extends Statement {
28     
29     public Expression constantExpression;
30     public CaseLabel targetLabel;
31     
32 public CaseStatement(Expression constantExpression, int sourceEnd, int sourceStart) {
33     this.constantExpression = constantExpression;
34     this.sourceEnd = sourceEnd;
35     this.sourceStart = sourceStart;
36 }
37
38 public FlowInfo analyseCode(
39     BlockScope currentScope,
40     FlowContext flowContext,
41     FlowInfo flowInfo) {
42
43     if (this.constantExpression != null) {
44         if (this.constantExpression.constant == Constant.NotAConstant
45                 && !this.constantExpression.resolvedType.isEnum()) {
46             currentScope.problemReporter().caseExpressionMustBeConstant(this.constantExpression);
47         }
48         this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
49     }
50     return flowInfo;
51 }
52
53 public StringBuffer JavaDoc printStatement(int tab, StringBuffer JavaDoc output) {
54     printIndent(tab, output);
55     if (this.constantExpression == null) {
56         output.append("default : "); //$NON-NLS-1$
57
} else {
58         output.append("case "); //$NON-NLS-1$
59
this.constantExpression.printExpression(0, output).append(" : "); //$NON-NLS-1$
60
}
61     return output.append(';');
62 }
63
64 /**
65  * Case code generation
66  *
67  */

68 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
69     if ((this.bits & ASTNode.IsReachable) == 0) {
70         return;
71     }
72     int pc = codeStream.position;
73     this.targetLabel.place();
74     codeStream.recordPositionsFrom(pc, this.sourceStart);
75 }
76
77 /**
78  * No-op : should use resolveCase(...) instead.
79  */

80 public void resolve(BlockScope scope) {
81     // no-op : should use resolveCase(...) instead.
82
}
83
84 /**
85  * Returns the constant intValue or ordinal for enum constants. If constant is NotAConstant, then answers Float.MIN_VALUE
86  * @see org.eclipse.jdt.internal.compiler.ast.Statement#resolveCase(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.ast.SwitchStatement)
87  */

88 public Constant resolveCase(BlockScope scope, TypeBinding switchExpressionType, SwitchStatement switchStatement) {
89     // switchExpressionType maybe null in error case
90
scope.enclosingCase = this; // record entering in a switch case block
91

92     if (this.constantExpression == null) {
93         // remember the default case into the associated switch statement
94
if (switchStatement.defaultCase != null)
95             scope.problemReporter().duplicateDefaultCase(this);
96
97         // on error the last default will be the selected one ...
98
switchStatement.defaultCase = this;
99         return Constant.NotAConstant;
100     }
101     // add into the collection of cases of the associated switch statement
102
switchStatement.cases[switchStatement.caseCount++] = this;
103     // tag constant name with enum type for privileged access to its members
104
if (switchExpressionType != null && switchExpressionType.isEnum() && (this.constantExpression instanceof SingleNameReference)) {
105         ((SingleNameReference) this.constantExpression).setActualReceiverType((ReferenceBinding)switchExpressionType);
106     }
107     TypeBinding caseType = this.constantExpression.resolveType(scope);
108     if (caseType == null || switchExpressionType == null) return Constant.NotAConstant;
109     if (this.constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchExpressionType)
110             || caseType.isCompatibleWith(switchExpressionType)) {
111         if (caseType.isEnum()) {
112             if (((this.constantExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) {
113                 scope.problemReporter().enumConstantsCannotBeSurroundedByParenthesis(this.constantExpression);
114             }
115
116             if (this.constantExpression instanceof NameReference
117                     && (this.constantExpression.bits & ASTNode.RestrictiveFlagMASK) == Binding.FIELD) {
118                 NameReference reference = (NameReference) this.constantExpression;
119                 FieldBinding field = reference.fieldBinding();
120                 if ((field.modifiers & ClassFileConstants.AccEnum) == 0) {
121                      scope.problemReporter().enumSwitchCannotTargetField(reference, field);
122                 } else if (reference instanceof QualifiedNameReference) {
123                      scope.problemReporter().cannotUseQualifiedEnumConstantInCaseLabel(reference, field);
124                 }
125                 return IntConstant.fromValue(field.original().id + 1); // (ordinal value + 1) zero should not be returned see bug 141810
126
}
127         } else {
128             return this.constantExpression.constant;
129         }
130     } else if (scope.isBoxingCompatibleWith(caseType, switchExpressionType)
131                     || (caseType.isBaseType() // narrowing then boxing ?
132
&& scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
133
&& !switchExpressionType.isBaseType()
134                             && this.constantExpression.isConstantValueOfTypeAssignableToType(caseType, scope.environment().computeBoxingType(switchExpressionType)))) {
135         // constantExpression.computeConversion(scope, caseType, switchExpressionType); - do not report boxing/unboxing conversion
136
return this.constantExpression.constant;
137     }
138     scope.problemReporter().typeMismatchError(caseType, switchExpressionType, this.constantExpression);
139     return Constant.NotAConstant;
140 }
141
142 public void traverse(ASTVisitor visitor, BlockScope blockScope) {
143     if (visitor.visit(this, blockScope)) {
144         if (this.constantExpression != null) this.constantExpression.traverse(visitor, blockScope);
145     }
146     visitor.endVisit(this, blockScope);
147 }
148 }
149
Popular Tags