X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/flow/FlowContext.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/flow/FlowContext.java index 60196d0..dca4536 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/flow/FlowContext.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/flow/FlowContext.java @@ -1,18 +1,20 @@ /******************************************************************************* - * 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.flow; +import net.sourceforge.phpdt.core.compiler.CharOperation; +import net.sourceforge.phpdt.internal.compiler.ast.ASTNode; import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration; -import net.sourceforge.phpdt.internal.compiler.ast.AstNode; import net.sourceforge.phpdt.internal.compiler.ast.Reference; +import net.sourceforge.phpdt.internal.compiler.ast.TryStatement; import net.sourceforge.phpdt.internal.compiler.codegen.Label; import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope; import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding; @@ -20,31 +22,32 @@ import net.sourceforge.phpdt.internal.compiler.lookup.Scope; import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants; import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding; -import net.sourceforge.phpdt.internal.compiler.util.CharOperation; /** * Reflects the context of code analysis, keeping track of enclosing * try statements, exception handlers, etc... */ public class FlowContext implements TypeConstants { - public AstNode associatedNode; + + public ASTNode associatedNode; public FlowContext parent; - public final static FlowContext NotContinuableContext = - new FlowContext(null, null); + public final static FlowContext NotContinuableContext = new FlowContext(null, null); - public FlowContext(FlowContext parent, AstNode associatedNode) { + public FlowContext(FlowContext parent, ASTNode associatedNode) { + this.parent = parent; this.associatedNode = associatedNode; } public Label breakLabel() { + return null; } public void checkExceptionHandlers( TypeBinding[] raisedExceptions, - AstNode location, + ASTNode location, FlowInfo flowInfo, BlockScope scope) { @@ -68,15 +71,16 @@ public class FlowContext implements TypeConstants { 0, raisedCount); FlowContext traversedContext = this; + while (traversedContext != null) { - AstNode sub; + ASTNode sub; if (((sub = traversedContext.subRoutine()) != null) && sub.cannotReturn()) { // traversing a non-returning subroutine means that all unhandled // exceptions will actually never get sent... return; } - // filter exceptions that are locally caught from the most enclosing - // try statement to the outer ones. + // filter exceptions that are locally caught from the innermost enclosing + // try statement to the outermost ones. if (traversedContext instanceof ExceptionHandlingFlowContext) { ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) traversedContext; @@ -129,9 +133,8 @@ public class FlowContext implements TypeConstants { for (int i = 0; i < raisedCount; i++) { TypeBinding raisedException; if ((raisedException = raisedExceptions[i]) != null) { - if (BlockScope - .areTypesCompatible(raisedException, scope.getJavaLangRuntimeException()) - || BlockScope.areTypesCompatible(raisedException, scope.getJavaLangError())) { + if (raisedException.isCompatibleWith(scope.getJavaLangRuntimeException()) + || raisedException.isCompatibleWith(scope.getJavaLangError())) { remainingCount--; raisedExceptions[i] = null; } @@ -157,12 +160,21 @@ public class FlowContext implements TypeConstants { } if (remainingCount == 0) return; + + traversedContext.recordReturnFrom(flowInfo.unconditionalInits()); + if (traversedContext.associatedNode instanceof TryStatement){ + flowInfo = flowInfo.copy().addInitializationsFrom(((TryStatement) traversedContext.associatedNode).subRoutineInits); + } traversedContext = traversedContext.parent; } // if reaches this point, then there are some remaining unhandled exception types. - for (int i = 0; i < raisedCount; i++) { + nextReport: for (int i = 0; i < raisedCount; i++) { TypeBinding exception; if ((exception = raisedExceptions[i]) != null) { + // only one complaint if same exception declared to be thrown more than once + for (int j = 0; j < i; j++) { + if (raisedExceptions[j] == exception) continue nextReport; // already reported + } scope.problemReporter().unhandledException(exception, location); } } @@ -170,7 +182,7 @@ public class FlowContext implements TypeConstants { public void checkExceptionHandlers( TypeBinding raisedException, - AstNode location, + ASTNode location, FlowInfo flowInfo, BlockScope scope) { @@ -181,14 +193,15 @@ public class FlowContext implements TypeConstants { // until the point where it is safely handled (Smarter - see comment at the end) FlowContext traversedContext = this; while (traversedContext != null) { - AstNode sub; + ASTNode sub; if (((sub = traversedContext.subRoutine()) != null) && sub.cannotReturn()) { // traversing a non-returning subroutine means that all unhandled // exceptions will actually never get sent... return; } - // filter exceptions that are locally caught from the most enclosing - // try statement to the outer ones. + + // filter exceptions that are locally caught from the innermost enclosing + // try statement to the outermost ones. if (traversedContext instanceof ExceptionHandlingFlowContext) { ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) traversedContext; @@ -225,9 +238,8 @@ public class FlowContext implements TypeConstants { } // method treatment for unchecked exceptions if (exceptionContext.isMethodContext) { - if (BlockScope - .areTypesCompatible(raisedException, scope.getJavaLangRuntimeException()) - || BlockScope.areTypesCompatible(raisedException, scope.getJavaLangError())) + if (raisedException.isCompatibleWith(scope.getJavaLangRuntimeException()) + || raisedException.isCompatibleWith(scope.getJavaLangError())) return; // anonymous constructors are allowed to throw any exceptions (their thrown exceptions @@ -243,6 +255,11 @@ public class FlowContext implements TypeConstants { break; // not handled anywhere, thus jump to error handling } } + + traversedContext.recordReturnFrom(flowInfo.unconditionalInits()); + if (traversedContext.associatedNode instanceof TryStatement){ + flowInfo = flowInfo.copy().addInitializationsFrom(((TryStatement) traversedContext.associatedNode).subRoutineInits); + } traversedContext = traversedContext.parent; } // if reaches this point, then there are some remaining unhandled exception types. @@ -250,6 +267,7 @@ public class FlowContext implements TypeConstants { } public Label continueLabel() { + return null; } @@ -257,6 +275,7 @@ public class FlowContext implements TypeConstants { * lookup through break labels */ public FlowContext getTargetContextForBreakLabel(char[] labelName) { + FlowContext current = this, lastNonReturningSubRoutine = null; while (current != null) { if (current.isNonReturningContext()) { @@ -281,9 +300,11 @@ public class FlowContext implements TypeConstants { * lookup through continue labels */ public FlowContext getTargetContextForContinueLabel(char[] labelName) { - FlowContext current = this, - lastContinuable = null, - lastNonReturningSubRoutine = null; + + FlowContext current = this; + FlowContext lastContinuable = null; + FlowContext lastNonReturningSubRoutine = null; + while (current != null) { if (current.isNonReturningContext()) { lastNonReturningSubRoutine = current; @@ -292,12 +313,14 @@ public class FlowContext implements TypeConstants { lastContinuable = current; } } + char[] currentLabelName; - if (((currentLabelName = current.labelName()) != null) - && CharOperation.equals(currentLabelName, labelName)) { + if ((currentLabelName = current.labelName()) != null && CharOperation.equals(currentLabelName, labelName)) { + + // matching label found if ((lastContinuable != null) - && (current.associatedNode.concreteStatement() - == lastContinuable.associatedNode)) { + && (current.associatedNode.concreteStatement() == lastContinuable.associatedNode)) { + if (lastNonReturningSubRoutine == null) { return lastContinuable; } else { @@ -318,12 +341,13 @@ public class FlowContext implements TypeConstants { * lookup a default break through breakable locations */ public FlowContext getTargetContextForDefaultBreak() { + FlowContext current = this, lastNonReturningSubRoutine = null; while (current != null) { if (current.isNonReturningContext()) { lastNonReturningSubRoutine = current; } - if (current.isBreakable()) { + if (current.isBreakable() && current.labelName() == null) { if (lastNonReturningSubRoutine == null) { return current; } else { @@ -340,6 +364,7 @@ public class FlowContext implements TypeConstants { * lookup a default continue amongst continuable locations */ public FlowContext getTargetContextForDefaultContinue() { + FlowContext current = this, lastNonReturningSubRoutine = null; while (current != null) { if (current.isNonReturningContext()) { @@ -359,30 +384,42 @@ public class FlowContext implements TypeConstants { } public String individualToString() { + return "Flow context"; //$NON-NLS-1$ } public FlowInfo initsOnBreak() { - return FlowInfo.DeadEnd; + + return FlowInfo.DEAD_END; + } + + public UnconditionalFlowInfo initsOnReturn() { + + return FlowInfo.DEAD_END; } public boolean isBreakable() { + return false; } public boolean isContinuable() { + return false; } public boolean isNonReturningContext() { + return false; } public boolean isSubRoutine() { + return false; } public char[] labelName() { + return null; } @@ -395,15 +432,17 @@ public class FlowContext implements TypeConstants { boolean recordFinalAssignment( VariableBinding variable, Reference finalReference) { + return true; // keep going } - public void recordReturnFrom(UnconditionalFlowInfo flowInfo) { + public void recordReturnFrom(FlowInfo flowInfo) { } public void recordSettingFinal( VariableBinding variable, Reference finalReference) { + // for initialization inside looping statement that effectively loops FlowContext context = this; while (context != null) { @@ -417,11 +456,13 @@ public class FlowContext implements TypeConstants { void removeFinalAssignmentIfAny(Reference reference) { } - public AstNode subRoutine() { + public ASTNode subRoutine() { + return null; } public String toString() { + StringBuffer buffer = new StringBuffer(); FlowContext current = this; int parentsCount = 0; @@ -446,4 +487,4 @@ public class FlowContext implements TypeConstants { buffer.append(individualToString()).append('\n'); return buffer.toString(); } -} \ No newline at end of file +}