1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
15 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
17 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
18 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
19 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
20 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
21 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
22 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
23 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
25 public class AssertStatement extends Statement {
27 public Expression assertExpression, exceptionArgument;
29 // for local variable attribute
30 int preAssertInitStateIndex = -1;
31 private FieldBinding assertionSyntheticFieldBinding;
33 public AssertStatement(
34 Expression exceptionArgument,
35 Expression assertExpression,
38 this.assertExpression = assertExpression;
39 this.exceptionArgument = exceptionArgument;
40 sourceStart = startPosition;
41 sourceEnd = exceptionArgument.sourceEnd;
44 public AssertStatement(Expression assertExpression, int startPosition) {
46 this.assertExpression = assertExpression;
47 sourceStart = startPosition;
48 sourceEnd = assertExpression.sourceEnd;
51 public FlowInfo analyseCode(
52 BlockScope currentScope,
53 FlowContext flowContext,
56 Constant constant = assertExpression.constant;
57 if (constant != NotAConstant && constant.booleanValue() == true) {
61 preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
62 FlowInfo assertInfo = flowInfo.copy();
64 if (exceptionArgument != null) {
65 assertInfo = exceptionArgument.analyseCode(
68 assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits())
69 .unconditionalInits();
71 assertInfo = assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits();
74 // assertion might throw AssertionError (unchecked), which can have consequences in term of
75 // definitely assigned variables (depending on caught exception in the context)
76 // DISABLED - AssertionError is unchecked, try statements are already protected against these.
77 //flowContext.checkExceptionHandlers(currentScope.getJavaLangAssertionError(), this, assertInfo, currentScope);
79 // only retain potential initializations
80 flowInfo.addPotentialInitializationsFrom(assertInfo.unconditionalInits());
82 // add the assert support in the clinit
83 manageSyntheticAccessIfNecessary(currentScope);
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();
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);
121 public void resolve(BlockScope scope) {
123 assertExpression.resolveTypeExpecting(scope, BooleanBinding);
124 if (exceptionArgument != null) {
125 TypeBinding exceptionArgumentType = exceptionArgument.resolveType(scope);
126 if (exceptionArgumentType != null){
127 if (exceptionArgumentType.id == T_void){
128 scope.problemReporter().illegalVoidExpression(exceptionArgument);
130 exceptionArgument.implicitConversion = (exceptionArgumentType.id << 4) + exceptionArgumentType.id;
135 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
137 if (visitor.visit(this, scope)) {
138 assertExpression.traverse(visitor, scope);
139 if (exceptionArgument != null) {
140 exceptionArgument.traverse(visitor, scope);
143 visitor.endVisit(this, scope);
146 public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
148 // need assertion flag: $assertionsDisabled on outer most source type
149 ClassScope outerMostClassScope = currentScope.outerMostClassScope();
150 SourceTypeBinding sourceTypeBinding = outerMostClassScope.enclosingSourceType();
151 this.assertionSyntheticFieldBinding = sourceTypeBinding.addSyntheticField(this, currentScope);
153 // find <clinit> and enable assertion support
154 TypeDeclaration typeDeclaration = outerMostClassScope.referenceType();
155 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
156 for (int i = 0, max = methods.length; i < max; i++) {
157 AbstractMethodDeclaration method = methods[i];
158 if (method.isClinit()) {
159 ((Clinit) method).addSupportForAssertion(assertionSyntheticFieldBinding);
165 public String toString(int tab) {
167 StringBuffer buffer = new StringBuffer(tabString(tab));
168 buffer.append("assert"); //$NON-NLS-1$
169 buffer.append(this.assertExpression);
170 if (this.exceptionArgument != null) {
171 buffer.append(":"); //$NON-NLS-1$
172 buffer.append(this.exceptionArgument);
173 buffer.append(";"); //$NON-NLS-1$
175 return buffer.toString();