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;
29 private FieldBinding assertionSyntheticFieldBinding;
31 public AssertStatement(
32 Expression exceptionArgument,
33 Expression assertExpression,
36 this.assertExpression = assertExpression;
37 this.exceptionArgument = exceptionArgument;
38 sourceStart = startPosition;
39 sourceEnd = exceptionArgument.sourceEnd;
42 public AssertStatement(Expression assertExpression, int startPosition) {
44 this.assertExpression = assertExpression;
45 sourceStart = startPosition;
46 sourceEnd = assertExpression.sourceEnd;
49 public FlowInfo analyseCode(
50 BlockScope currentScope,
51 FlowContext flowContext,
54 preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
56 Constant cst = this.assertExpression.optimizedBooleanConstant();
57 boolean isOptimizedTrueAssertion = cst != NotAConstant && cst.booleanValue() == true;
58 boolean isOptimizedFalseAssertion = cst != NotAConstant && cst.booleanValue() == false;
60 FlowInfo assertInfo = flowInfo.copy();
61 if (isOptimizedTrueAssertion) {
62 assertInfo.setReachMode(FlowInfo.UNREACHABLE);
64 assertInfo = assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits();
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());
70 if (!isOptimizedTrueAssertion){
71 flowContext.checkExceptionHandlers(
72 currentScope.getJavaLangAssertionError(),
79 // add the assert support in the clinit
80 manageSyntheticAccessIfNecessary(currentScope);
81 if (isOptimizedFalseAssertion) {
82 return flowInfo; // if assertions are enabled, the following code will be unreachable
84 return flowInfo.mergedWith(assertInfo.unconditionalInits());
88 // public void generateCode(BlockScope currentScope, CodeStream codeStream) {
90 // if ((bits & IsReachableMASK) == 0) {
93 // int pc = codeStream.position;
95 // if (this.assertionSyntheticFieldBinding != null) {
96 // Label assertionActivationLabel = new Label(codeStream);
97 // codeStream.getstatic(this.assertionSyntheticFieldBinding);
98 // codeStream.ifne(assertionActivationLabel);
99 // Label falseLabel = new Label(codeStream);
100 // assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new Label(codeStream)), null , true);
101 // codeStream.newJavaLangAssertionError();
103 // if (exceptionArgument != null) {
104 // exceptionArgument.generateCode(currentScope, codeStream, true);
105 // codeStream.invokeJavaLangAssertionErrorConstructor(exceptionArgument.implicitConversion & 0xF);
107 // codeStream.invokeJavaLangAssertionErrorDefaultConstructor();
109 // codeStream.athrow();
110 // falseLabel.place();
111 // assertionActivationLabel.place();
114 // // May loose some local variable initializations : affecting the local variable attributes
115 // if (preAssertInitStateIndex != -1) {
116 // codeStream.removeNotDefinitelyAssignedVariables(currentScope, preAssertInitStateIndex);
118 // codeStream.recordPositionsFrom(pc, this.sourceStart);
120 public StringBuffer printStatement(int tab, StringBuffer output) {
122 printIndent(tab, output);
123 output.append("assert "); //$NON-NLS-1$
124 this.assertExpression.printExpression(0, output);
125 if (this.exceptionArgument != null) {
126 output.append(": "); //$NON-NLS-1$
127 this.exceptionArgument.printExpression(0, output);
129 return output.append(';');
131 public void resolve(BlockScope scope) {
133 assertExpression.resolveTypeExpecting(scope, BooleanBinding);
134 if (exceptionArgument != null) {
135 TypeBinding exceptionArgumentType = exceptionArgument.resolveType(scope);
136 if (exceptionArgumentType != null){
137 if (exceptionArgumentType.id == T_void){
138 scope.problemReporter().illegalVoidExpression(exceptionArgument);
140 exceptionArgument.implicitConversion = (exceptionArgumentType.id << 4) + exceptionArgumentType.id;
145 public void traverse(ASTVisitor visitor, BlockScope scope) {
147 if (visitor.visit(this, scope)) {
148 assertExpression.traverse(visitor, scope);
149 if (exceptionArgument != null) {
150 exceptionArgument.traverse(visitor, scope);
153 visitor.endVisit(this, scope);
156 public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
158 // need assertion flag: $assertionsDisabled on outer most source clas
159 // (in case of static member of interface, will use the outermost static member - bug 22334)
160 SourceTypeBinding outerMostClass = currentScope.enclosingSourceType();
161 while (outerMostClass.isLocalType()){
162 ReferenceBinding enclosing = outerMostClass.enclosingType();
163 if (enclosing == null || enclosing.isInterface()) break;
164 outerMostClass = (SourceTypeBinding) enclosing;
167 this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticField(this, currentScope);
169 // find <clinit> and enable assertion support
170 TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType();
171 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
172 for (int i = 0, max = methods.length; i < max; i++) {
173 AbstractMethodDeclaration method = methods[i];
174 if (method.isClinit()) {
175 ((Clinit) method).addSupportForAssertion(assertionSyntheticFieldBinding);
181 public String toString(int tab) {
183 StringBuffer buffer = new StringBuffer(tabString(tab));
184 buffer.append("assert "); //$NON-NLS-1$
185 buffer.append(this.assertExpression);
186 if (this.exceptionArgument != null) {
187 buffer.append(":"); //$NON-NLS-1$
188 buffer.append(this.exceptionArgument);
189 buffer.append(";"); //$NON-NLS-1$
191 return buffer.toString();