X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/AssertStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/AssertStatement.java new file mode 100644 index 0000000..87f61e8 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/AssertStatement.java @@ -0,0 +1,194 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpdt.internal.compiler.ast; + +import net.sourceforge.phpdt.internal.compiler.ASTVisitor; +import net.sourceforge.phpdt.internal.compiler.flow.FlowContext; +import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo; +import net.sourceforge.phpdt.internal.compiler.impl.Constant; +import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope; +import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; + +public class AssertStatement extends Statement { + + public Expression assertExpression, exceptionArgument; + + // for local variable attribute + int preAssertInitStateIndex = -1; + private FieldBinding assertionSyntheticFieldBinding; + + public AssertStatement( + Expression exceptionArgument, + Expression assertExpression, + int startPosition) { + + this.assertExpression = assertExpression; + this.exceptionArgument = exceptionArgument; + sourceStart = startPosition; + sourceEnd = exceptionArgument.sourceEnd; + } + + public AssertStatement(Expression assertExpression, int startPosition) { + + this.assertExpression = assertExpression; + sourceStart = startPosition; + sourceEnd = assertExpression.sourceEnd; + } + + public FlowInfo analyseCode( + BlockScope currentScope, + FlowContext flowContext, + FlowInfo flowInfo) { + + preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); + + Constant cst = this.assertExpression.optimizedBooleanConstant(); + boolean isOptimizedTrueAssertion = cst != NotAConstant && cst.booleanValue() == true; + boolean isOptimizedFalseAssertion = cst != NotAConstant && cst.booleanValue() == false; + + FlowInfo assertInfo = flowInfo.copy(); + if (isOptimizedTrueAssertion) { + assertInfo.setReachMode(FlowInfo.UNREACHABLE); + } + assertInfo = assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits(); + + if (exceptionArgument != null) { + // only gets evaluated when escaping - results are not taken into account + FlowInfo exceptionInfo = exceptionArgument.analyseCode(currentScope, flowContext, assertInfo.copy()); + + if (!isOptimizedTrueAssertion){ + flowContext.checkExceptionHandlers( + currentScope.getJavaLangAssertionError(), + this, + exceptionInfo, + currentScope); + } + } + + // add the assert support in the clinit + manageSyntheticAccessIfNecessary(currentScope); + if (isOptimizedFalseAssertion) { + return flowInfo; // if assertions are enabled, the following code will be unreachable + } else { + return flowInfo.mergedWith(assertInfo.unconditionalInits()); + } + } + +// public void generateCode(BlockScope currentScope, CodeStream codeStream) { +// +// if ((bits & IsReachableMASK) == 0) { +// return; +// } +// int pc = codeStream.position; +// +// if (this.assertionSyntheticFieldBinding != null) { +// Label assertionActivationLabel = new Label(codeStream); +// codeStream.getstatic(this.assertionSyntheticFieldBinding); +// codeStream.ifne(assertionActivationLabel); +// Label falseLabel = new Label(codeStream); +// assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new Label(codeStream)), null , true); +// codeStream.newJavaLangAssertionError(); +// codeStream.dup(); +// if (exceptionArgument != null) { +// exceptionArgument.generateCode(currentScope, codeStream, true); +// codeStream.invokeJavaLangAssertionErrorConstructor(exceptionArgument.implicitConversion & 0xF); +// } else { +// codeStream.invokeJavaLangAssertionErrorDefaultConstructor(); +// } +// codeStream.athrow(); +// falseLabel.place(); +// assertionActivationLabel.place(); +// } +// +// // May loose some local variable initializations : affecting the local variable attributes +// if (preAssertInitStateIndex != -1) { +// codeStream.removeNotDefinitelyAssignedVariables(currentScope, preAssertInitStateIndex); +// } +// codeStream.recordPositionsFrom(pc, this.sourceStart); +// } + public StringBuffer printStatement(int tab, StringBuffer output) { + + printIndent(tab, output); + output.append("assert "); //$NON-NLS-1$ + this.assertExpression.printExpression(0, output); + if (this.exceptionArgument != null) { + output.append(": "); //$NON-NLS-1$ + this.exceptionArgument.printExpression(0, output); + } + return output.append(';'); + } + public void resolve(BlockScope scope) { + + assertExpression.resolveTypeExpecting(scope, BooleanBinding); + if (exceptionArgument != null) { + TypeBinding exceptionArgumentType = exceptionArgument.resolveType(scope); + if (exceptionArgumentType != null){ + if (exceptionArgumentType.id == T_void){ + scope.problemReporter().illegalVoidExpression(exceptionArgument); + } + exceptionArgument.implicitConversion = (exceptionArgumentType.id << 4) + exceptionArgumentType.id; + } + } + } + + public void traverse(ASTVisitor visitor, BlockScope scope) { + + if (visitor.visit(this, scope)) { + assertExpression.traverse(visitor, scope); + if (exceptionArgument != null) { + exceptionArgument.traverse(visitor, scope); + } + } + visitor.endVisit(this, scope); + } + + public void manageSyntheticAccessIfNecessary(BlockScope currentScope) { + + // need assertion flag: $assertionsDisabled on outer most source clas + // (in case of static member of interface, will use the outermost static member - bug 22334) + SourceTypeBinding outerMostClass = currentScope.enclosingSourceType(); + while (outerMostClass.isLocalType()){ + ReferenceBinding enclosing = outerMostClass.enclosingType(); + if (enclosing == null || enclosing.isInterface()) break; + outerMostClass = (SourceTypeBinding) enclosing; + } + + this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticField(this, currentScope); + + // find and enable assertion support + TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType(); + AbstractMethodDeclaration[] methods = typeDeclaration.methods; + for (int i = 0, max = methods.length; i < max; i++) { + AbstractMethodDeclaration method = methods[i]; + if (method.isClinit()) { + ((Clinit) method).addSupportForAssertion(assertionSyntheticFieldBinding); + break; + } + } + } + + public String toString(int tab) { + + StringBuffer buffer = new StringBuffer(tabString(tab)); + buffer.append("assert "); //$NON-NLS-1$ + buffer.append(this.assertExpression); + if (this.exceptionArgument != null) { + buffer.append(":"); //$NON-NLS-1$ + buffer.append(this.exceptionArgument); + buffer.append(";"); //$NON-NLS-1$ + } + return buffer.toString(); + } + +}