KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.classfmt.ClassFileConstants;
14 import org.eclipse.jdt.internal.compiler.codegen.*;
15 import org.eclipse.jdt.internal.compiler.flow.*;
16 import org.eclipse.jdt.internal.compiler.impl.Constant;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
18 import org.eclipse.jdt.internal.compiler.ASTVisitor;
19
20 public class AssertStatement extends Statement {
21     
22     public Expression assertExpression, exceptionArgument;
23
24     // for local variable attribute
25
int preAssertInitStateIndex = -1;
26     private FieldBinding assertionSyntheticFieldBinding;
27     
28     public AssertStatement(
29         Expression exceptionArgument,
30         Expression assertExpression,
31         int startPosition) {
32             
33         this.assertExpression = assertExpression;
34         this.exceptionArgument = exceptionArgument;
35         sourceStart = startPosition;
36         sourceEnd = exceptionArgument.sourceEnd;
37     }
38
39     public AssertStatement(Expression assertExpression, int startPosition) {
40
41         this.assertExpression = assertExpression;
42         sourceStart = startPosition;
43         sourceEnd = assertExpression.sourceEnd;
44     }
45
46     public FlowInfo analyseCode(
47         BlockScope currentScope,
48         FlowContext flowContext,
49         FlowInfo flowInfo) {
50             
51         preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
52
53         Constant cst = this.assertExpression.optimizedBooleanConstant();
54         boolean isOptimizedTrueAssertion = cst != Constant.NotAConstant && cst.booleanValue() == true;
55         boolean isOptimizedFalseAssertion = cst != Constant.NotAConstant && cst.booleanValue() == false;
56
57         FlowInfo assertRawInfo = assertExpression.
58             analyseCode(currentScope, flowContext, flowInfo.copy());
59         UnconditionalFlowInfo assertWhenTrueInfo = assertRawInfo.initsWhenTrue().
60             unconditionalInits();
61         UnconditionalFlowInfo assertInfo = assertRawInfo.unconditionalCopy();
62         if (isOptimizedTrueAssertion) {
63             assertInfo.setReachMode(FlowInfo.UNREACHABLE);
64         }
65         
66         if (exceptionArgument != null) {
67             // only gets evaluated when escaping - results are not taken into account
68
FlowInfo exceptionInfo = exceptionArgument.analyseCode(currentScope, flowContext, assertInfo.copy());
69             
70             if (!isOptimizedTrueAssertion){
71                 flowContext.checkExceptionHandlers(
72                     currentScope.getJavaLangAssertionError(),
73                     this,
74                     exceptionInfo,
75                     currentScope);
76             }
77         }
78         
79         if (!isOptimizedTrueAssertion){
80             // add the assert support in the clinit
81
manageSyntheticAccessIfNecessary(currentScope, flowInfo);
82         }
83         if (isOptimizedFalseAssertion) {
84             return flowInfo; // if assertions are enabled, the following code will be unreachable
85
// change this if we need to carry null analysis results of the assert
86
// expression downstream
87
} else {
88             return flowInfo.mergedWith(assertInfo.nullInfoLessUnconditionalCopy()).
89                 addInitializationsFrom(assertWhenTrueInfo.discardInitializationInfo());
90             // keep the merge from the initial code for the definite assignment
91
// analysis, tweak the null part to influence nulls downstream
92
}
93     }
94
95     public void generateCode(BlockScope currentScope, CodeStream codeStream) {
96
97         if ((bits & IsReachable) == 0) {
98             return;
99         }
100         int pc = codeStream.position;
101     
102         if (this.assertionSyntheticFieldBinding != null) {
103             BranchLabel assertionActivationLabel = new BranchLabel(codeStream);
104             codeStream.getstatic(this.assertionSyntheticFieldBinding);
105             codeStream.ifne(assertionActivationLabel);
106             
107             BranchLabel falseLabel;
108             this.assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new BranchLabel(codeStream)), null , true);
109             codeStream.newJavaLangAssertionError();
110             codeStream.dup();
111             if (exceptionArgument != null) {
112                 exceptionArgument.generateCode(currentScope, codeStream, true);
113                 codeStream.invokeJavaLangAssertionErrorConstructor(exceptionArgument.implicitConversion & 0xF);
114             } else {
115                 codeStream.invokeJavaLangAssertionErrorDefaultConstructor();
116             }
117             codeStream.athrow();
118             
119             // May loose some local variable initializations : affecting the local variable attributes
120
if (preAssertInitStateIndex != -1) {
121                 codeStream.removeNotDefinitelyAssignedVariables(currentScope, preAssertInitStateIndex);
122             }
123             falseLabel.place();
124             assertionActivationLabel.place();
125         } else {
126             // May loose some local variable initializations : affecting the local variable attributes
127
if (preAssertInitStateIndex != -1) {
128                 codeStream.removeNotDefinitelyAssignedVariables(currentScope, preAssertInitStateIndex);
129             }
130         }
131         codeStream.recordPositionsFrom(pc, this.sourceStart);
132     }
133
134     public void resolve(BlockScope scope) {
135
136         assertExpression.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
137         if (exceptionArgument != null) {
138             TypeBinding exceptionArgumentType = exceptionArgument.resolveType(scope);
139             if (exceptionArgumentType != null){
140                 int id = exceptionArgumentType.id;
141                 switch(id) {
142                     case T_void :
143                         scope.problemReporter().illegalVoidExpression(exceptionArgument);
144                     default:
145                         id = T_JavaLangObject;
146                     case T_boolean :
147                     case T_byte :
148                     case T_char :
149                     case T_short :
150                     case T_double :
151                     case T_float :
152                     case T_int :
153                     case T_long :
154                     case T_JavaLangString :
155                         exceptionArgument.implicitConversion = (id << 4) + id;
156                 }
157             }
158         }
159     }
160
161     public void traverse(ASTVisitor visitor, BlockScope scope) {
162
163         if (visitor.visit(this, scope)) {
164             assertExpression.traverse(visitor, scope);
165             if (exceptionArgument != null) {
166                 exceptionArgument.traverse(visitor, scope);
167             }
168         }
169         visitor.endVisit(this, scope);
170     }
171     
172     public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
173
174         if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
175             
176             // need assertion flag: $assertionsDisabled on outer most source clas
177
// (in case of static member of interface, will use the outermost static member - bug 22334)
178
SourceTypeBinding outerMostClass = currentScope.enclosingSourceType();
179             while (outerMostClass.isLocalType()) {
180                 ReferenceBinding enclosing = outerMostClass.enclosingType();
181                 if (enclosing == null || enclosing.isInterface()) break;
182                 outerMostClass = (SourceTypeBinding) enclosing;
183             }
184     
185             this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticFieldForAssert(currentScope);
186     
187             // find <clinit> and enable assertion support
188
TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType();
189             AbstractMethodDeclaration[] methods = typeDeclaration.methods;
190             for (int i = 0, max = methods.length; i < max; i++) {
191                 AbstractMethodDeclaration method = methods[i];
192                 if (method.isClinit()) {
193                     ((Clinit) method).setAssertionSupport(assertionSyntheticFieldBinding, currentScope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5);
194                     break;
195                 }
196             }
197         }
198     }
199
200     public StringBuffer JavaDoc printStatement(int tab, StringBuffer JavaDoc output) {
201
202         printIndent(tab, output);
203         output.append("assert "); //$NON-NLS-1$
204
this.assertExpression.printExpression(0, output);
205         if (this.exceptionArgument != null) {
206             output.append(": "); //$NON-NLS-1$
207
this.exceptionArgument.printExpression(0, output);
208         }
209         return output.append(';');
210     }
211     
212 }
213
Popular Tags