Refactory: smarty.ui plugin.
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / AssertStatement.java
index 66a16eb..64705dc 100644 (file)
@@ -1,34 +1,37 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * 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 v0.5 
+ * 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-v05.html
+ * 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.impl.*;
-import net.sourceforge.phpdt.internal.compiler.codegen.*;
-import net.sourceforge.phpdt.internal.compiler.flow.*;
-import net.sourceforge.phpdt.internal.compiler.lookup.*;
-import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+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) {
-                       
+
+       public AssertStatement(Expression exceptionArgument,
+                       Expression assertExpression, int startPosition) {
+
                this.assertExpression = assertExpression;
                this.exceptionArgument = exceptionArgument;
                sourceStart = startPosition;
@@ -42,91 +45,115 @@ public class AssertStatement extends Statement {
                sourceEnd = assertExpression.sourceEnd;
        }
 
-       public FlowInfo analyseCode(
-               BlockScope currentScope,
-               FlowContext flowContext,
-               FlowInfo flowInfo) {
-                       
-               Constant constant = assertExpression.constant;
-               if (constant != NotAConstant && constant.booleanValue() == true) {
-                       return flowInfo;
-               }
+       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;
 
-               preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
                FlowInfo assertInfo = flowInfo.copy();
-                       
-               if (exceptionArgument != null) {
-                       assertInfo = exceptionArgument.analyseCode(
-                                               currentScope,
-                                               flowContext,
-                                               assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits())
-                                       .unconditionalInits();
-               } else {
-                       assertInfo = assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits();
+               if (isOptimizedTrueAssertion) {
+                       assertInfo.setReachMode(FlowInfo.UNREACHABLE);
                }
-               
-               // assertion might throw AssertionError (unchecked), which can have consequences in term of
-               // definitely assigned variables (depending on caught exception in the context)
-               // DISABLED - AssertionError is unchecked, try statements are already protected against these.
-               //flowContext.checkExceptionHandlers(currentScope.getJavaLangAssertionError(), this, assertInfo, currentScope);
+               assertInfo = assertExpression.analyseCode(currentScope, flowContext,
+                               assertInfo).unconditionalInits();
 
-               // only retain potential initializations
-               flowInfo.addPotentialInitializationsFrom(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);
-                                       
-               return flowInfo;
+               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();
+       // 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);
                }
-               
-               // May loose some local variable initializations : affecting the local variable attributes
-               if (preAssertInitStateIndex != -1) {
-                       codeStream.removeNotDefinitelyAssignedVariables(currentScope, preAssertInitStateIndex);
-               }       
-               codeStream.recordPositionsFrom(pc, this.sourceStart);
+               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);
+                       TypeBinding exceptionArgumentType = exceptionArgument
+                                       .resolveType(scope);
+                       if (exceptionArgumentType != null) {
+                               if (exceptionArgumentType.id == T_void) {
+                                       scope.problemReporter().illegalVoidExpression(
+                                                       exceptionArgument);
                                }
-                               exceptionArgument.implicitConversion = (exceptionArgumentType.id << 4) + exceptionArgumentType.id;
+                               exceptionArgument.implicitConversion = (exceptionArgumentType.id << 4)
+                                               + exceptionArgumentType.id;
                        }
                }
        }
-       
-       public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
 
                if (visitor.visit(this, scope)) {
                        assertExpression.traverse(visitor, scope);
@@ -135,22 +162,32 @@ public class AssertStatement extends Statement {
                        }
                }
                visitor.endVisit(this, scope);
-       }       
-       
+       }
+
        public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
 
-               // need assertion flag: $assertionsDisabled on outer most source type
-               ClassScope outerMostClassScope = currentScope.outerMostClassScope();
-               SourceTypeBinding sourceTypeBinding = outerMostClassScope.enclosingSourceType();
-               this.assertionSyntheticFieldBinding = sourceTypeBinding.addSyntheticField(this, 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 <clinit> and enable assertion support
-               TypeDeclaration typeDeclaration = outerMostClassScope.referenceType();
+               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);
+                               ((Clinit) method)
+                                               .addSupportForAssertion(assertionSyntheticFieldBinding);
                                break;
                        }
                }
@@ -159,7 +196,7 @@ public class AssertStatement extends Statement {
        public String toString(int tab) {
 
                StringBuffer buffer = new StringBuffer(tabString(tab));
-               buffer.append("assert"); //$NON-NLS-1$
+               buffer.append("assert "); //$NON-NLS-1$
                buffer.append(this.assertExpression);
                if (this.exceptionArgument != null) {
                        buffer.append(":"); //$NON-NLS-1$
@@ -168,5 +205,5 @@ public class AssertStatement extends Statement {
                }
                return buffer.toString();
        }
-       
-}
\ No newline at end of file
+
+}