KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > flow > ExceptionHandlingFlowContext


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.flow;
12
13 import java.util.ArrayList JavaDoc;
14
15 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
16 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
17 import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement;
18 import org.eclipse.jdt.internal.compiler.ast.TryStatement;
19 import org.eclipse.jdt.internal.compiler.codegen.ObjectCache;
20 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
21 import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
22 import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
23 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
24 import org.eclipse.jdt.internal.compiler.lookup.Scope;
25 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
26
27 /**
28  * Reflects the context of code analysis, keeping track of enclosing
29  * try statements, exception handlers, etc...
30  */

31 public class ExceptionHandlingFlowContext extends FlowContext {
32     
33     public final static int BitCacheSize = 32; // 32 bits per int
34

35     public ReferenceBinding[] handledExceptions;
36     int[] isReached;
37     int[] isNeeded;
38     UnconditionalFlowInfo[] initsOnExceptions;
39     ObjectCache indexes = new ObjectCache();
40     boolean isMethodContext;
41
42     public UnconditionalFlowInfo initsOnReturn;
43
44     // for dealing with anonymous constructor thrown exceptions
45
public ArrayList JavaDoc extendedExceptions;
46     
47 public ExceptionHandlingFlowContext(
48         FlowContext parent,
49         ASTNode associatedNode,
50         ReferenceBinding[] handledExceptions,
51         BlockScope scope,
52         UnconditionalFlowInfo flowInfo) {
53
54     super(parent, associatedNode);
55     this.isMethodContext = scope == scope.methodScope();
56     this.handledExceptions = handledExceptions;
57     int count = handledExceptions.length, cacheSize = (count / ExceptionHandlingFlowContext.BitCacheSize) + 1;
58     this.isReached = new int[cacheSize]; // none is reached by default
59
this.isNeeded = new int[cacheSize]; // none is needed by default
60
this.initsOnExceptions = new UnconditionalFlowInfo[count];
61     for (int i = 0; i < count; i++) {
62         this.indexes.put(handledExceptions[i], i); // key type -> value index
63
int cacheIndex = i / ExceptionHandlingFlowContext.BitCacheSize, bitMask = 1 << (i % ExceptionHandlingFlowContext.BitCacheSize);
64         if (handledExceptions[i].isUncheckedException(true)) {
65             this.isReached[cacheIndex] |= bitMask;
66             this.initsOnExceptions[i] = flowInfo.unconditionalCopy();
67         } else {
68             this.initsOnExceptions[i] = FlowInfo.DEAD_END;
69         }
70     }
71     System.arraycopy(this.isReached, 0, this.isNeeded, 0, cacheSize);
72     this.initsOnReturn = FlowInfo.DEAD_END;
73 }
74
75 public void complainIfUnusedExceptionHandlers(AbstractMethodDeclaration method) {
76     MethodScope scope = method.scope;
77     // can optionally skip overriding methods
78
if ((method.binding.modifiers & (ExtraCompilerModifiers.AccOverriding | ExtraCompilerModifiers.AccImplementing)) != 0
79             && !scope.compilerOptions().reportUnusedDeclaredThrownExceptionWhenOverriding) {
80         return;
81     }
82         
83     // report errors for unreachable exception handlers
84
for (int i = 0, count = this.handledExceptions.length; i < count; i++) {
85         int index = this.indexes.get(this.handledExceptions[i]);
86         int cacheIndex = index / ExceptionHandlingFlowContext.BitCacheSize;
87         int bitMask = 1 << (index % ExceptionHandlingFlowContext.BitCacheSize);
88         if ((this.isReached[cacheIndex] & bitMask) == 0) {
89             scope.problemReporter().unusedDeclaredThrownException(
90                 this.handledExceptions[index],
91                 method,
92                 method.thrownExceptions[index]);
93         }
94     }
95 }
96
97 public void complainIfUnusedExceptionHandlers(BlockScope scope,TryStatement tryStatement) {
98     // report errors for unreachable exception handlers
99
for (int i = 0, count = this.handledExceptions.length; i < count; i++) {
100         int index = this.indexes.get(this.handledExceptions[i]);
101         int cacheIndex = index / ExceptionHandlingFlowContext.BitCacheSize;
102         int bitMask = 1 << (index % ExceptionHandlingFlowContext.BitCacheSize);
103         if ((this.isReached[cacheIndex] & bitMask) == 0) {
104             scope.problemReporter().unreachableCatchBlock(
105                 this.handledExceptions[index],
106                 tryStatement.catchArguments[index].type);
107         } else {
108             if ((this.isNeeded[cacheIndex] & bitMask) == 0) {
109                 scope.problemReporter().hiddenCatchBlock(
110                     this.handledExceptions[index],
111                     tryStatement.catchArguments[index].type);
112             }
113         }
114     }
115 }
116
117 public String JavaDoc individualToString() {
118     StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("Exception flow context"); //$NON-NLS-1$
119
int length = this.handledExceptions.length;
120     for (int i = 0; i < length; i++) {
121         int cacheIndex = i / ExceptionHandlingFlowContext.BitCacheSize;
122         int bitMask = 1 << (i % ExceptionHandlingFlowContext.BitCacheSize);
123         buffer.append('[').append(this.handledExceptions[i].readableName());
124         if ((this.isReached[cacheIndex] & bitMask) != 0) {
125             if ((this.isNeeded[cacheIndex] & bitMask) == 0) {
126                 buffer.append("-masked"); //$NON-NLS-1$
127
} else {
128                 buffer.append("-reached"); //$NON-NLS-1$
129
}
130         } else {
131             buffer.append("-not reached"); //$NON-NLS-1$
132
}
133         buffer.append('-').append(this.initsOnExceptions[i].toString()).append(']');
134     }
135     buffer.append("[initsOnReturn -").append(this.initsOnReturn.toString()).append(']'); //$NON-NLS-1$
136
return buffer.toString();
137 }
138
139 public UnconditionalFlowInfo initsOnException(ReferenceBinding exceptionType) {
140     int index;
141     if ((index = this.indexes.get(exceptionType)) < 0) {
142         return FlowInfo.DEAD_END;
143     }
144     return this.initsOnExceptions[index];
145 }
146
147 public UnconditionalFlowInfo initsOnReturn(){
148     return this.initsOnReturn;
149 }
150     
151 /*
152  * Compute a merged list of unhandled exception types (keeping only the most generic ones).
153  * This is necessary to add synthetic thrown exceptions for anonymous type constructors (JLS 8.6).
154  */

155 public void mergeUnhandledException(TypeBinding newException){
156     if (this.extendedExceptions == null){
157         this.extendedExceptions = new ArrayList JavaDoc(5);
158         for (int i = 0; i < this.handledExceptions.length; i++){
159             this.extendedExceptions.add(this.handledExceptions[i]);
160         }
161     }
162     boolean isRedundant = false;
163     
164     for(int i = this.extendedExceptions.size()-1; i >= 0; i--){
165         switch(Scope.compareTypes(newException, (TypeBinding)this.extendedExceptions.get(i))){
166             case Scope.MORE_GENERIC :
167                 this.extendedExceptions.remove(i);
168                 break;
169             case Scope.EQUAL_OR_MORE_SPECIFIC :
170                 isRedundant = true;
171                 break;
172             case Scope.NOT_RELATED :
173                 break;
174         }
175     }
176     if (!isRedundant){
177         this.extendedExceptions.add(newException);
178     }
179 }
180     
181 public void recordHandlingException(
182         ReferenceBinding exceptionType,
183         UnconditionalFlowInfo flowInfo,
184         TypeBinding raisedException,
185         ASTNode invocationSite,
186         boolean wasAlreadyDefinitelyCaught) {
187         
188     int index = this.indexes.get(exceptionType);
189     // if already flagged as being reached (unchecked exception handler)
190
int cacheIndex = index / ExceptionHandlingFlowContext.BitCacheSize;
191     int bitMask = 1 << (index % ExceptionHandlingFlowContext.BitCacheSize);
192     if (!wasAlreadyDefinitelyCaught) {
193         this.isNeeded[cacheIndex] |= bitMask;
194     }
195     this.isReached[cacheIndex] |= bitMask;
196     
197     this.initsOnExceptions[index] =
198         (this.initsOnExceptions[index].tagBits & FlowInfo.UNREACHABLE) == 0 ?
199             this.initsOnExceptions[index].mergedWith(flowInfo):
200             flowInfo.unconditionalCopy();
201 }
202
203 public void recordReturnFrom(UnconditionalFlowInfo flowInfo) {
204     if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
205         if ((this.initsOnReturn.tagBits & FlowInfo.UNREACHABLE) == 0) {
206             this.initsOnReturn = this.initsOnReturn.mergedWith(flowInfo);
207         }
208         else {
209             this.initsOnReturn = (UnconditionalFlowInfo) flowInfo.copy();
210         }
211     }
212 }
213
214 /**
215  * Exception handlers (with no finally block) are also included with subroutine
216  * only once (in case parented with true InsideSubRoutineFlowContext).
217  * Standard management of subroutines need to also operate on intermediate
218  * exception handlers.
219  * @see org.eclipse.jdt.internal.compiler.flow.FlowContext#subroutine()
220  */

221 public SubRoutineStatement subroutine() {
222     if (this.associatedNode instanceof SubRoutineStatement) {
223         // exception handler context may be child of InsideSubRoutineFlowContext, which maps to same handler
224
if (this.parent.subroutine() == this.associatedNode)
225             return null;
226         return (SubRoutineStatement) this.associatedNode;
227     }
228     return null;
229 }
230 }
231
Popular Tags