import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
/**
- * 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 ExceptionHandlingFlowContext extends FlowContext {
-
+
public ReferenceBinding[] handledExceptions;
-
+
public final static int BitCacheSize = 32; // 32 bits per int
+
int[] isReached;
+
int[] isNeeded;
+
UnconditionalFlowInfo[] initsOnExceptions;
+
ObjectCache indexes = new ObjectCache();
+
boolean isMethodContext;
public UnconditionalFlowInfo initsOnReturn;
// for dealing with anonymous constructor thrown exceptions
public ArrayList extendedExceptions;
-
- public ExceptionHandlingFlowContext(
- FlowContext parent,
- ASTNode associatedNode,
- ReferenceBinding[] handledExceptions,
- BlockScope scope,
- UnconditionalFlowInfo flowInfo) {
+
+ public ExceptionHandlingFlowContext(FlowContext parent,
+ ASTNode associatedNode, ReferenceBinding[] handledExceptions,
+ BlockScope scope, UnconditionalFlowInfo flowInfo) {
super(parent, associatedNode);
isMethodContext = scope == scope.methodScope();
this.isNeeded = new int[cacheSize]; // none is needed by default
this.initsOnExceptions = new UnconditionalFlowInfo[count];
for (int i = 0; i < count; i++) {
- this.indexes.put(handledExceptions[i], i); // key type -> value index
- boolean isUnchecked =
- (scope.compareUncheckedException(handledExceptions[i]) != NotRelated);
+ this.indexes.put(handledExceptions[i], i); // key type -> value
+ // index
+ boolean isUnchecked = (scope
+ .compareUncheckedException(handledExceptions[i]) != NotRelated);
int cacheIndex = i / BitCacheSize, bitMask = 1 << (i % BitCacheSize);
if (isUnchecked) {
isReached[cacheIndex] |= bitMask;
- this.initsOnExceptions[i] = flowInfo.copy().unconditionalInits();
+ this.initsOnExceptions[i] = flowInfo.copy()
+ .unconditionalInits();
} else {
this.initsOnExceptions[i] = FlowInfo.DEAD_END;
}
}
System.arraycopy(this.isReached, 0, this.isNeeded, 0, cacheSize);
- this.initsOnReturn = FlowInfo.DEAD_END;
+ this.initsOnReturn = FlowInfo.DEAD_END;
}
-
-
-// public void complainIfUnusedExceptionHandlers(
-// ASTNode[] exceptionHandlers,
-// BlockScope scope,
-// TryStatement tryStatement) {
-// // report errors for unreachable exception handlers
-// for (int i = 0, count = handledExceptions.length; i < count; i++) {
-// int index = indexes.get(handledExceptions[i]);
-// int cacheIndex = index / BitCacheSize;
-// int bitMask = 1 << (index % BitCacheSize);
-// if ((isReached[cacheIndex] & bitMask) == 0) {
-// scope.problemReporter().unreachableExceptionHandler(
-// handledExceptions[index],
-// exceptionHandlers[index]);
-// } else {
-// if ((isNeeded[cacheIndex] & bitMask) == 0) {
-// scope.problemReporter().maskedExceptionHandler(
-// handledExceptions[index],
-// exceptionHandlers[index]);
-// }
-// }
-// }
-// // will optimized out unnecessary catch block during code gen
-// tryStatement.preserveExceptionHandler = isNeeded;
-// }
+
+ // public void complainIfUnusedExceptionHandlers(
+ // ASTNode[] exceptionHandlers,
+ // BlockScope scope,
+ // TryStatement tryStatement) {
+ // // report errors for unreachable exception handlers
+ // for (int i = 0, count = handledExceptions.length; i < count; i++) {
+ // int index = indexes.get(handledExceptions[i]);
+ // int cacheIndex = index / BitCacheSize;
+ // int bitMask = 1 << (index % BitCacheSize);
+ // if ((isReached[cacheIndex] & bitMask) == 0) {
+ // scope.problemReporter().unreachableExceptionHandler(
+ // handledExceptions[index],
+ // exceptionHandlers[index]);
+ // } else {
+ // if ((isNeeded[cacheIndex] & bitMask) == 0) {
+ // scope.problemReporter().maskedExceptionHandler(
+ // handledExceptions[index],
+ // exceptionHandlers[index]);
+ // }
+ // }
+ // }
+ // // will optimized out unnecessary catch block during code gen
+ // tryStatement.preserveExceptionHandler = isNeeded;
+ // }
public String individualToString() {
-
+
StringBuffer buffer = new StringBuffer("Exception flow context"); //$NON-NLS-1$
int length = handledExceptions.length;
for (int i = 0; i < length; i++) {
} else {
buffer.append("-not reached"); //$NON-NLS-1$
}
- buffer.append('-').append(initsOnExceptions[i].toString()).append(']');
+ buffer.append('-').append(initsOnExceptions[i].toString()).append(
+ ']');
}
- buffer.append("[initsOnReturn -").append(initsOnReturn.toString()).append(']'); //$NON-NLS-1$
+ buffer
+ .append("[initsOnReturn -").append(initsOnReturn.toString()).append(']'); //$NON-NLS-1$
return buffer.toString();
}
public UnconditionalFlowInfo initsOnException(ReferenceBinding exceptionType) {
-
+
int index;
if ((index = indexes.get(exceptionType)) < 0) {
return FlowInfo.DEAD_END;
return initsOnExceptions[index];
}
- public UnconditionalFlowInfo initsOnReturn(){
+ public UnconditionalFlowInfo initsOnReturn() {
return this.initsOnReturn;
}
-
- public void recordHandlingException(
- ReferenceBinding exceptionType,
- UnconditionalFlowInfo flowInfo,
- TypeBinding raisedException,
- ASTNode invocationSite,
- boolean wasAlreadyDefinitelyCaught) {
-
+
+ public void recordHandlingException(ReferenceBinding exceptionType,
+ UnconditionalFlowInfo flowInfo, TypeBinding raisedException,
+ ASTNode invocationSite, boolean wasAlreadyDefinitelyCaught) {
+
int index = indexes.get(exceptionType);
// if already flagged as being reached (unchecked exception handler)
int cacheIndex = index / BitCacheSize;
this.isNeeded[cacheIndex] |= bitMask;
}
this.isReached[cacheIndex] |= bitMask;
-
- initsOnExceptions[index] =
- initsOnExceptions[index] == FlowInfo.DEAD_END
- ? flowInfo.copy().unconditionalInits()
+
+ initsOnExceptions[index] = initsOnExceptions[index] == FlowInfo.DEAD_END ? flowInfo
+ .copy().unconditionalInits()
: initsOnExceptions[index].mergedWith(flowInfo);
}
-
+
public void recordReturnFrom(FlowInfo flowInfo) {
- if (!flowInfo.isReachable()) return;
+ if (!flowInfo.isReachable())
+ return;
if (initsOnReturn == FlowInfo.DEAD_END) {
initsOnReturn = flowInfo.copy().unconditionalInits();
} else {
- initsOnReturn = initsOnReturn.mergedWith(flowInfo.unconditionalInits());
+ initsOnReturn = initsOnReturn.mergedWith(flowInfo
+ .unconditionalInits());
}
}
-
+
/*
- * Compute a merged list of unhandled exception types (keeping only the most generic ones).
- * This is necessary to add synthetic thrown exceptions for anonymous type constructors (JLS 8.6).
+ * Compute a merged list of unhandled exception types (keeping only the most
+ * generic ones). This is necessary to add synthetic thrown exceptions for
+ * anonymous type constructors (JLS 8.6).
*/
- public void mergeUnhandledException(TypeBinding newException){
-
- if (this.extendedExceptions == null){
+ public void mergeUnhandledException(TypeBinding newException) {
+
+ if (this.extendedExceptions == null) {
this.extendedExceptions = new ArrayList(5);
- for (int i = 0; i < this.handledExceptions.length; i++){
+ for (int i = 0; i < this.handledExceptions.length; i++) {
this.extendedExceptions.add(this.handledExceptions[i]);
}
}
-
+
boolean isRedundant = false;
-
- for(int i = this.extendedExceptions.size()-1; i >= 0; i--){
- switch(Scope.compareTypes(newException, (TypeBinding)this.extendedExceptions.get(i))){
- case MoreGeneric :
- this.extendedExceptions.remove(i);
- break;
- case EqualOrMoreSpecific :
- isRedundant = true;
- break;
- case NotRelated :
- break;
+
+ for (int i = this.extendedExceptions.size() - 1; i >= 0; i--) {
+ switch (Scope.compareTypes(newException,
+ (TypeBinding) this.extendedExceptions.get(i))) {
+ case MoreGeneric:
+ this.extendedExceptions.remove(i);
+ break;
+ case EqualOrMoreSpecific:
+ isRedundant = true;
+ break;
+ case NotRelated:
+ break;
}
}
- if (!isRedundant){
+ if (!isRedundant) {
this.extendedExceptions.add(newException);
}
}