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 dca4536..8daeeba 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 @@ -24,99 +24,100 @@ import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants; import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding; /** - * Reflects the context of code analysis, keeping track of enclosing - * try statements, exception handlers, etc... + * Reflects the context of code analysis, keeping track of enclosing try + * statements, exception handlers, etc... */ public class FlowContext implements TypeConstants { - + 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) { this.parent = parent; this.associatedNode = associatedNode; } - + public Label breakLabel() { return null; } - - public void checkExceptionHandlers( - TypeBinding[] raisedExceptions, - ASTNode location, - FlowInfo flowInfo, - BlockScope scope) { + + public void checkExceptionHandlers(TypeBinding[] raisedExceptions, + ASTNode location, FlowInfo flowInfo, BlockScope scope) { // check that all the argument exception types are handled - // JDK Compatible implementation - when an exception type is thrown, - // all related catch blocks are marked as reachable... instead of those only - // until the point where it is safely handled (Smarter - see comment at the end) - int remainingCount; // counting the number of remaining unhandled exceptions + // JDK Compatible implementation - when an exception type is thrown, + // all related catch blocks are marked as reachable... instead of those + // only + // until the point where it is safely handled (Smarter - see comment at + // the end) + int remainingCount; // counting the number of remaining unhandled + // exceptions int raisedCount; // total number of exceptions raised if ((raisedExceptions == null) - || ((raisedCount = raisedExceptions.length) == 0)) + || ((raisedCount = raisedExceptions.length) == 0)) return; remainingCount = raisedCount; // duplicate the array of raised exceptions since it will be updated // (null replaces any handled exception) - System.arraycopy( - raisedExceptions, - 0, - (raisedExceptions = new TypeBinding[raisedCount]), - 0, - raisedCount); + System.arraycopy(raisedExceptions, 0, + (raisedExceptions = new TypeBinding[raisedCount]), 0, + raisedCount); FlowContext traversedContext = this; while (traversedContext != null) { ASTNode sub; - if (((sub = traversedContext.subRoutine()) != null) && sub.cannotReturn()) { - // traversing a non-returning subroutine means that all unhandled + 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 innermost enclosing + // filter exceptions that are locally caught from the innermost + // enclosing // try statement to the outermost ones. if (traversedContext instanceof ExceptionHandlingFlowContext) { - ExceptionHandlingFlowContext exceptionContext = - (ExceptionHandlingFlowContext) traversedContext; + ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) traversedContext; ReferenceBinding[] caughtExceptions; if ((caughtExceptions = exceptionContext.handledExceptions) != NoExceptions) { int caughtCount = caughtExceptions.length; - boolean[] locallyCaught = new boolean[raisedCount]; // at most + boolean[] locallyCaught = new boolean[raisedCount]; // at + // most for (int caughtIndex = 0; caughtIndex < caughtCount; caughtIndex++) { ReferenceBinding caughtException = caughtExceptions[caughtIndex]; for (int raisedIndex = 0; raisedIndex < raisedCount; raisedIndex++) { TypeBinding raisedException; if ((raisedException = raisedExceptions[raisedIndex]) != null) { - switch (Scope.compareTypes(raisedException, caughtException)) { - case EqualOrMoreSpecific : - exceptionContext.recordHandlingException( - caughtException, - flowInfo.unconditionalInits(), - raisedException, - location, + switch (Scope.compareTypes(raisedException, + caughtException)) { + case EqualOrMoreSpecific: + exceptionContext.recordHandlingException( + caughtException, flowInfo + .unconditionalInits(), + raisedException, location, locallyCaught[raisedIndex]); - // was already definitely caught ? - if (!locallyCaught[raisedIndex]) { - locallyCaught[raisedIndex] = true; - // remember that this exception has been definitely caught - remainingCount--; - } - break; - case MoreGeneric : - exceptionContext.recordHandlingException( - caughtException, - flowInfo.unconditionalInits(), - raisedException, - location, - false); - // was not caught already per construction + // was already definitely caught ? + if (!locallyCaught[raisedIndex]) { + locallyCaught[raisedIndex] = true; + // remember that this exception has been + // definitely caught + remainingCount--; + } + break; + case MoreGeneric: + exceptionContext.recordHandlingException( + caughtException, flowInfo + .unconditionalInits(), + raisedException, location, false); + // was not caught already per construction } } } @@ -124,7 +125,8 @@ public class FlowContext implements TypeConstants { // remove locally caught exceptions from the remaining ones for (int i = 0; i < raisedCount; i++) { if (locallyCaught[i]) { - raisedExceptions[i] = null; // removed from the remaining ones. + raisedExceptions[i] = null; // removed from the + // remaining ones. } } } @@ -133,26 +135,33 @@ public class FlowContext implements TypeConstants { for (int i = 0; i < raisedCount; i++) { TypeBinding raisedException; if ((raisedException = raisedExceptions[i]) != null) { - if (raisedException.isCompatibleWith(scope.getJavaLangRuntimeException()) - || raisedException.isCompatibleWith(scope.getJavaLangError())) { + if (raisedException.isCompatibleWith(scope + .getJavaLangRuntimeException()) + || raisedException.isCompatibleWith(scope + .getJavaLangError())) { remainingCount--; raisedExceptions[i] = null; } } } - // anonymous constructors are allowed to throw any exceptions (their thrown exceptions + // anonymous constructors are allowed to throw any + // exceptions (their thrown exceptions // clause will be fixed up later as per JLS 8.6). - if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration){ - AbstractMethodDeclaration method = (AbstractMethodDeclaration)exceptionContext.associatedNode; - if (method.isConstructor() && method.binding.declaringClass.isAnonymousType()){ - + if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration) { + AbstractMethodDeclaration method = (AbstractMethodDeclaration) exceptionContext.associatedNode; + if (method.isConstructor() + && method.binding.declaringClass + .isAnonymousType()) { + for (int i = 0; i < raisedCount; i++) { TypeBinding raisedException; if ((raisedException = raisedExceptions[i]) != null) { - exceptionContext.mergeUnhandledException(raisedException); + exceptionContext + .mergeUnhandledException(raisedException); } } - return; // no need to complain, will fix up constructor exceptions + return; // no need to complain, will fix up + // constructor exceptions } } break; // not handled anywhere, thus jump to error handling @@ -160,77 +169,80 @@ 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); + 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. + // if reaches this point, then there are some remaining unhandled + // exception types. 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 + // 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 + if (raisedExceptions[j] == exception) + continue nextReport; // already reported } scope.problemReporter().unhandledException(exception, location); } } } - public void checkExceptionHandlers( - TypeBinding raisedException, - ASTNode location, - FlowInfo flowInfo, - BlockScope scope) { + public void checkExceptionHandlers(TypeBinding raisedException, + ASTNode location, FlowInfo flowInfo, BlockScope scope) { // LIGHT-VERSION OF THE EQUIVALENT WITH AN ARRAY OF EXCEPTIONS // check that all the argument exception types are handled - // JDK Compatible implementation - when an exception type is thrown, - // all related catch blocks are marked as reachable... instead of those only - // until the point where it is safely handled (Smarter - see comment at the end) + // JDK Compatible implementation - when an exception type is thrown, + // all related catch blocks are marked as reachable... instead of those + // only + // until the point where it is safely handled (Smarter - see comment at + // the end) FlowContext traversedContext = this; while (traversedContext != null) { ASTNode sub; - if (((sub = traversedContext.subRoutine()) != null) && sub.cannotReturn()) { - // traversing a non-returning subroutine means that all unhandled + 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 innermost enclosing + + // filter exceptions that are locally caught from the innermost + // enclosing // try statement to the outermost ones. if (traversedContext instanceof ExceptionHandlingFlowContext) { - ExceptionHandlingFlowContext exceptionContext = - (ExceptionHandlingFlowContext) traversedContext; + ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) traversedContext; ReferenceBinding[] caughtExceptions; if ((caughtExceptions = exceptionContext.handledExceptions) != NoExceptions) { boolean definitelyCaught = false; - for (int caughtIndex = 0, caughtCount = caughtExceptions.length; - caughtIndex < caughtCount; - caughtIndex++) { + for (int caughtIndex = 0, caughtCount = caughtExceptions.length; caughtIndex < caughtCount; caughtIndex++) { ReferenceBinding caughtException = caughtExceptions[caughtIndex]; - switch (Scope.compareTypes(raisedException, caughtException)) { - case EqualOrMoreSpecific : - exceptionContext.recordHandlingException( - caughtException, - flowInfo.unconditionalInits(), - raisedException, - location, - definitelyCaught); - // was it already definitely caught ? - definitelyCaught = true; - break; - case MoreGeneric : - exceptionContext.recordHandlingException( - caughtException, - flowInfo.unconditionalInits(), - raisedException, - location, - false); - // was not caught already per construction + switch (Scope.compareTypes(raisedException, + caughtException)) { + case EqualOrMoreSpecific: + exceptionContext + .recordHandlingException(caughtException, + flowInfo.unconditionalInits(), + raisedException, location, + definitelyCaught); + // was it already definitely caught ? + definitelyCaught = true; + break; + case MoreGeneric: + exceptionContext.recordHandlingException( + caughtException, flowInfo + .unconditionalInits(), + raisedException, location, false); + // was not caught already per construction } } if (definitelyCaught) @@ -238,18 +250,25 @@ public class FlowContext implements TypeConstants { } // method treatment for unchecked exceptions if (exceptionContext.isMethodContext) { - if (raisedException.isCompatibleWith(scope.getJavaLangRuntimeException()) - || raisedException.isCompatibleWith(scope.getJavaLangError())) + if (raisedException.isCompatibleWith(scope + .getJavaLangRuntimeException()) + || raisedException.isCompatibleWith(scope + .getJavaLangError())) return; - - // anonymous constructors are allowed to throw any exceptions (their thrown exceptions + + // anonymous constructors are allowed to throw any + // exceptions (their thrown exceptions // clause will be fixed up later as per JLS 8.6). - if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration){ - AbstractMethodDeclaration method = (AbstractMethodDeclaration)exceptionContext.associatedNode; - if (method.isConstructor() && method.binding.declaringClass.isAnonymousType()){ - - exceptionContext.mergeUnhandledException(raisedException); - return; // no need to complain, will fix up constructor exceptions + if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration) { + AbstractMethodDeclaration method = (AbstractMethodDeclaration) exceptionContext.associatedNode; + if (method.isConstructor() + && method.binding.declaringClass + .isAnonymousType()) { + + exceptionContext + .mergeUnhandledException(raisedException); + return; // no need to complain, will fix up + // constructor exceptions } } break; // not handled anywhere, thus jump to error handling @@ -257,12 +276,16 @@ public class FlowContext implements TypeConstants { } traversedContext.recordReturnFrom(flowInfo.unconditionalInits()); - if (traversedContext.associatedNode instanceof TryStatement){ - flowInfo = flowInfo.copy().addInitializationsFrom(((TryStatement) traversedContext.associatedNode).subRoutineInits); + 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. + // if reaches this point, then there are some remaining unhandled + // exception types. scope.problemReporter().unhandledException(raisedException, location); } @@ -283,7 +306,7 @@ public class FlowContext implements TypeConstants { } char[] currentLabelName; if (((currentLabelName = current.labelName()) != null) - && CharOperation.equals(currentLabelName, labelName)) { + && CharOperation.equals(currentLabelName, labelName)) { if (lastNonReturningSubRoutine == null) { return current; } else { @@ -313,14 +336,15 @@ 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 + // matching label found if ((lastContinuable != null) - && (current.associatedNode.concreteStatement() == lastContinuable.associatedNode)) { - + && (current.associatedNode.concreteStatement() == lastContinuable.associatedNode)) { + if (lastNonReturningSubRoutine == null) { return lastContinuable; } else { @@ -429,9 +453,8 @@ public class FlowContext implements TypeConstants { public void recordContinueFrom(FlowInfo flowInfo) { } - boolean recordFinalAssignment( - VariableBinding variable, - Reference finalReference) { + boolean recordFinalAssignment(VariableBinding variable, + Reference finalReference) { return true; // keep going } @@ -439,9 +462,8 @@ public class FlowContext implements TypeConstants { public void recordReturnFrom(FlowInfo flowInfo) { } - public void recordSettingFinal( - VariableBinding variable, - Reference finalReference) { + public void recordSettingFinal(VariableBinding variable, + Reference finalReference) { // for initialization inside looping statement that effectively loops FlowContext context = this;