Refactored packagename to net.sourceforge.phpdt.internal.compiler.ast
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / AssertStatement.java
index f67d14f..87f61e8 100644 (file)
@@ -1,24 +1,22 @@
 /*******************************************************************************
- * 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.IAbstractSyntaxTreeVisitor;
-import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
-import net.sourceforge.phpdt.internal.compiler.codegen.Label;
+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.ClassScope;
 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;
 
@@ -53,71 +51,83 @@ public class AssertStatement extends Statement {
                FlowContext flowContext,
                FlowInfo flowInfo) {
                        
-               Constant constant = assertExpression.constant;
-               if (constant != NotAConstant && constant.booleanValue() == true) {
-                       return 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) {
-                       assertInfo = exceptionArgument.analyseCode(
-                                               currentScope,
-                                               flowContext,
-                                               assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits())
-                                       .unconditionalInits();
-               } else {
-                       assertInfo = assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits();
+                       // 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);
+                       }
                }
                
-               // 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);
-
-               // only retain potential initializations
-               flowInfo.addPotentialInitializationsFrom(assertInfo.unconditionalInits());
-
                // 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);
@@ -132,7 +142,7 @@ public class AssertStatement extends Statement {
                }
        }
        
-       public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
 
                if (visitor.visit(this, scope)) {
                        assertExpression.traverse(visitor, scope);
@@ -145,13 +155,19 @@ public class AssertStatement extends Statement {
        
        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];
@@ -165,7 +181,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$
@@ -175,4 +191,4 @@ public class AssertStatement extends Statement {
                return buffer.toString();
        }
        
-}
\ No newline at end of file
+}