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.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;
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.phpeclipse.internal.compiler.ast.ASTNode;
-import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
-import net.sourceforge.phpeclipse.internal.compiler.ast.Reference;
-import net.sourceforge.phpeclipse.internal.compiler.ast.TryStatement;
/**
- * 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
}
}
}
// 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.
}
}
}
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
}
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)
}
// 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
}
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);
}
}
char[] currentLabelName;
if (((currentLabelName = current.labelName()) != null)
- && CharOperation.equals(currentLabelName, labelName)) {
+ && CharOperation.equals(currentLabelName, labelName)) {
if (lastNonReturningSubRoutine == null) {
return current;
} else {
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 {
public void recordContinueFrom(FlowInfo flowInfo) {
}
- boolean recordFinalAssignment(
- VariableBinding variable,
- Reference finalReference) {
+ boolean recordFinalAssignment(VariableBinding variable,
+ Reference finalReference) {
return true; // keep going
}
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;