1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
16 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
21 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
23 public class AssertStatement extends Statement {
25 public Expression assertExpression, exceptionArgument;
27 // for local variable attribute
28 int preAssertInitStateIndex = -1;
30 private FieldBinding assertionSyntheticFieldBinding;
32 public AssertStatement(Expression exceptionArgument,
33 Expression assertExpression, int startPosition) {
35 this.assertExpression = assertExpression;
36 this.exceptionArgument = exceptionArgument;
37 sourceStart = startPosition;
38 sourceEnd = exceptionArgument.sourceEnd;
41 public AssertStatement(Expression assertExpression, int startPosition) {
43 this.assertExpression = assertExpression;
44 sourceStart = startPosition;
45 sourceEnd = assertExpression.sourceEnd;
48 public FlowInfo analyseCode(BlockScope currentScope,
49 FlowContext flowContext, FlowInfo flowInfo) {
51 preAssertInitStateIndex = currentScope.methodScope()
52 .recordInitializationStates(flowInfo);
54 Constant cst = this.assertExpression.optimizedBooleanConstant();
55 boolean isOptimizedTrueAssertion = cst != NotAConstant
56 && cst.booleanValue() == true;
57 boolean isOptimizedFalseAssertion = cst != NotAConstant
58 && cst.booleanValue() == false;
60 FlowInfo assertInfo = flowInfo.copy();
61 if (isOptimizedTrueAssertion) {
62 assertInfo.setReachMode(FlowInfo.UNREACHABLE);
64 assertInfo = assertExpression.analyseCode(currentScope, flowContext,
65 assertInfo).unconditionalInits();
67 if (exceptionArgument != null) {
68 // only gets evaluated when escaping - results are not taken into
70 FlowInfo exceptionInfo = exceptionArgument.analyseCode(
71 currentScope, flowContext, assertInfo.copy());
73 if (!isOptimizedTrueAssertion) {
74 flowContext.checkExceptionHandlers(currentScope
75 .getJavaLangAssertionError(), this, exceptionInfo,
80 // add the assert support in the clinit
81 manageSyntheticAccessIfNecessary(currentScope);
82 if (isOptimizedFalseAssertion) {
83 return flowInfo; // if assertions are enabled, the following code
84 // will be unreachable
86 return flowInfo.mergedWith(assertInfo.unconditionalInits());
90 // public void generateCode(BlockScope currentScope, CodeStream codeStream)
93 // if ((bits & IsReachableMASK) == 0) {
96 // int pc = codeStream.position;
98 // if (this.assertionSyntheticFieldBinding != null) {
99 // Label assertionActivationLabel = new Label(codeStream);
100 // codeStream.getstatic(this.assertionSyntheticFieldBinding);
101 // codeStream.ifne(assertionActivationLabel);
102 // Label falseLabel = new Label(codeStream);
103 // assertExpression.generateOptimizedBoolean(currentScope, codeStream,
104 // (falseLabel = new Label(codeStream)), null , true);
105 // codeStream.newJavaLangAssertionError();
107 // if (exceptionArgument != null) {
108 // exceptionArgument.generateCode(currentScope, codeStream, true);
109 // codeStream.invokeJavaLangAssertionErrorConstructor(exceptionArgument.implicitConversion
112 // codeStream.invokeJavaLangAssertionErrorDefaultConstructor();
114 // codeStream.athrow();
115 // falseLabel.place();
116 // assertionActivationLabel.place();
119 // // May loose some local variable initializations : affecting the local
120 // variable attributes
121 // if (preAssertInitStateIndex != -1) {
122 // codeStream.removeNotDefinitelyAssignedVariables(currentScope,
123 // preAssertInitStateIndex);
125 // codeStream.recordPositionsFrom(pc, this.sourceStart);
127 public StringBuffer printStatement(int tab, StringBuffer output) {
129 printIndent(tab, output);
130 output.append("assert "); //$NON-NLS-1$
131 this.assertExpression.printExpression(0, output);
132 if (this.exceptionArgument != null) {
133 output.append(": "); //$NON-NLS-1$
134 this.exceptionArgument.printExpression(0, output);
136 return output.append(';');
139 public void resolve(BlockScope scope) {
141 assertExpression.resolveTypeExpecting(scope, BooleanBinding);
142 if (exceptionArgument != null) {
143 TypeBinding exceptionArgumentType = exceptionArgument
145 if (exceptionArgumentType != null) {
146 if (exceptionArgumentType.id == T_void) {
147 scope.problemReporter().illegalVoidExpression(
150 exceptionArgument.implicitConversion = (exceptionArgumentType.id << 4)
151 + exceptionArgumentType.id;
156 public void traverse(ASTVisitor visitor, BlockScope scope) {
158 if (visitor.visit(this, scope)) {
159 assertExpression.traverse(visitor, scope);
160 if (exceptionArgument != null) {
161 exceptionArgument.traverse(visitor, scope);
164 visitor.endVisit(this, scope);
167 public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
169 // need assertion flag: $assertionsDisabled on outer most source clas
170 // (in case of static member of interface, will use the outermost static
171 // member - bug 22334)
172 SourceTypeBinding outerMostClass = currentScope.enclosingSourceType();
173 while (outerMostClass.isLocalType()) {
174 ReferenceBinding enclosing = outerMostClass.enclosingType();
175 if (enclosing == null || enclosing.isInterface())
177 outerMostClass = (SourceTypeBinding) enclosing;
180 this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticField(
183 // find <clinit> and enable assertion support
184 TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType();
185 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
186 for (int i = 0, max = methods.length; i < max; i++) {
187 AbstractMethodDeclaration method = methods[i];
188 if (method.isClinit()) {
190 .addSupportForAssertion(assertionSyntheticFieldBinding);
196 public String toString(int tab) {
198 StringBuffer buffer = new StringBuffer(tabString(tab));
199 buffer.append("assert "); //$NON-NLS-1$
200 buffer.append(this.assertExpression);
201 if (this.exceptionArgument != null) {
202 buffer.append(":"); //$NON-NLS-1$
203 buffer.append(this.exceptionArgument);
204 buffer.append(";"); //$NON-NLS-1$
206 return buffer.toString();