added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / ast / CaseStatement.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-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.impl.*;
15 import org.eclipse.jdt.internal.compiler.codegen.*;
16 import org.eclipse.jdt.internal.compiler.flow.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
18
19 public class CaseStatement extends Statement {
20         
21         public Expression constantExpression;
22         public CaseLabel targetLabel;
23         boolean isEnumConstant;
24         
25         public CaseStatement(Expression constantExpression, int sourceEnd, int sourceStart) {
26                 this.constantExpression = constantExpression;
27                 this.sourceEnd = sourceEnd;
28                 this.sourceStart = sourceStart;
29         }
30
31         public FlowInfo analyseCode(
32                 BlockScope currentScope,
33                 FlowContext flowContext,
34                 FlowInfo flowInfo) {
35
36                 if (constantExpression != null) {
37                         if (!this.isEnumConstant && constantExpression.constant == NotAConstant) {
38                                 currentScope.problemReporter().caseExpressionMustBeConstant(constantExpression);
39                         }
40                         this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
41                 }
42                 return flowInfo;
43         }
44
45         public StringBuffer printStatement(int tab, StringBuffer output) {
46
47                 printIndent(tab, output);
48                 if (constantExpression == null) {
49                         output.append("default : "); //$NON-NLS-1$
50                 } else {
51                         output.append("case "); //$NON-NLS-1$
52                         constantExpression.printExpression(0, output).append(" : "); //$NON-NLS-1$
53                 }
54                 return output.append(';');
55         }
56         
57         /**
58          * Case code generation
59          *
60          */
61         public void generateCode(BlockScope currentScope, CodeStream codeStream) {
62
63                 if ((bits & IsReachableMASK) == 0) {
64                         return;
65                 }
66                 int pc = codeStream.position;
67                 targetLabel.place();
68                 codeStream.recordPositionsFrom(pc, this.sourceStart);
69         }
70
71         /**
72          * No-op : should use resolveCase(...) instead.
73          */
74         public void resolve(BlockScope scope) {
75                 // no-op : should use resolveCase(...) instead.
76         }
77
78         /**
79          * Returns the constant intValue or ordinal for enum constants. If constant is NotAConstant, then answers Float.MIN_VALUE
80          * @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)
81          */
82         public Constant resolveCase(
83                 BlockScope scope,
84                 TypeBinding switchExpressionType,
85                 SwitchStatement switchStatement) {
86
87             scope.switchCase = this; // record entering in a switch case block
88             
89                 if (constantExpression == null) {
90                         // remember the default case into the associated switch statement
91                         if (switchStatement.defaultCase != null)
92                                 scope.problemReporter().duplicateDefaultCase(this);
93         
94                         // on error the last default will be the selected one ...       
95                         switchStatement.defaultCase = this;
96                         return NotAConstant;
97                 }
98                 // add into the collection of cases of the associated switch statement
99                 switchStatement.cases[switchStatement.caseCount++] = this;
100                 // tag constant name with enum type for privileged access to its members
101                 if (switchExpressionType.isEnum() && (constantExpression instanceof SingleNameReference)) {
102                         ((SingleNameReference) constantExpression).setActualReceiverType((ReferenceBinding)switchExpressionType);
103                 }
104                 TypeBinding caseType = constantExpression.resolveType(scope);
105                 if (caseType == null || switchExpressionType == null) return NotAConstant;
106                 if (constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchExpressionType)
107                                 || caseType.isCompatibleWith(switchExpressionType)) {
108                         if (caseType.isEnum()) {
109                                 this.isEnumConstant = true;
110                                 if (constantExpression instanceof NameReference
111                                                 && (constantExpression.bits & RestrictiveFlagMASK) == Binding.FIELD) {
112                                         if (constantExpression instanceof QualifiedNameReference) {
113                                                  scope.problemReporter().cannotUseQualifiedEnumConstantInCaseLabel((QualifiedNameReference)constantExpression);
114                                         }
115                                         return Constant.fromValue(((NameReference)constantExpression).fieldBinding().id); // ordinal value
116                                 }
117                         } else {
118                                 return constantExpression.constant;
119                         }
120                 } else if (scope.isBoxingCompatibleWith(switchExpressionType, caseType)) {
121                         constantExpression.computeConversion(scope, caseType, switchExpressionType);
122                         return constantExpression.constant;
123                 }
124                 scope.problemReporter().typeMismatchError(caseType, switchExpressionType, constantExpression);
125                 return NotAConstant;
126         }
127
128
129         public void traverse(
130                 ASTVisitor visitor,
131                 BlockScope blockScope) {
132
133                 if (visitor.visit(this, blockScope)) {
134                         if (constantExpression != null) constantExpression.traverse(visitor, blockScope);
135                 }
136                 visitor.endVisit(this, blockScope);
137         }
138 }