KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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 org.eclipse.jdt.internal.compiler.ast.ASTNode;
14 import org.eclipse.jdt.internal.compiler.ast.Expression;
15 import org.eclipse.jdt.internal.compiler.ast.Reference;
16 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
17 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
18 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
19 import org.eclipse.jdt.internal.compiler.lookup.Scope;
20 import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
21
22 /**
23  * Reflects the context of code analysis, keeping track of enclosing
24  * try statements, exception handlers, etc...
25  */

26 public class FinallyFlowContext extends FlowContext {
27     
28     Reference[] finalAssignments;
29     VariableBinding[] finalVariables;
30     int assignCount;
31
32     LocalVariableBinding[] nullLocals;
33     Expression[] nullReferences;
34     int[] nullCheckTypes;
35     int nullCount;
36     
37     public FinallyFlowContext(FlowContext parent, ASTNode associatedNode) {
38         super(parent, associatedNode);
39     }
40
41 /**
42  * Given some contextual initialization info (derived from a try block or a catch block), this
43  * code will check that the subroutine context does not also initialize a final variable potentially set
44  * redundantly.
45  */

46 public void complainOnDeferredChecks(FlowInfo flowInfo, BlockScope scope) {
47     
48     // check redundant final assignments
49
for (int i = 0; i < this.assignCount; i++) {
50         VariableBinding variable = this.finalVariables[i];
51         if (variable == null) continue;
52         
53         boolean complained = false; // remember if have complained on this final assignment
54
if (variable instanceof FieldBinding) {
55             // final field
56
if (flowInfo.isPotentiallyAssigned((FieldBinding)variable)) {
57                 complained = true;
58                 scope.problemReporter().duplicateInitializationOfBlankFinalField((FieldBinding)variable, finalAssignments[i]);
59             }
60         } else {
61             // final local variable
62
if (flowInfo.isPotentiallyAssigned((LocalVariableBinding) variable)) {
63                 complained = true;
64                 scope.problemReporter().duplicateInitializationOfFinalLocal(
65                     (LocalVariableBinding) variable,
66                     this.finalAssignments[i]);
67             }
68         }
69         // any reference reported at this level is removed from the parent context
70
// where it could also be reported again
71
if (complained) {
72             FlowContext currentContext = this.parent;
73             while (currentContext != null) {
74                 //if (currentContext.isSubRoutine()) {
75
currentContext.removeFinalAssignmentIfAny(this.finalAssignments[i]);
76                 //}
77
currentContext = currentContext.parent;
78             }
79         }
80     }
81     
82     // check inconsistent null checks
83
if (this.deferNullDiagnostic) { // within an enclosing loop, be conservative
84
for (int i = 0; i < this.nullCount; i++) {
85             this.parent.recordUsingNullReference(scope, this.nullLocals[i],
86                     this.nullReferences[i], this.nullCheckTypes[i], flowInfo);
87         }
88     }
89     else { // no enclosing loop, be as precise as possible right now
90
for (int i = 0; i < this.nullCount; i++) {
91             Expression expression = this.nullReferences[i];
92             // final local variable
93
LocalVariableBinding local = this.nullLocals[i];
94             switch (this.nullCheckTypes[i]) {
95                 case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL:
96                 case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL:
97                     if (flowInfo.isDefinitelyNonNull(local)) {
98                         if (this.nullCheckTypes[i] == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
99                             scope.problemReporter().localVariableRedundantCheckOnNonNull(local, expression);
100                         } else {
101                             scope.problemReporter().localVariableNonNullComparedToNull(local, expression);
102                         }
103                         continue;
104                     }
105                 case CAN_ONLY_NULL | IN_COMPARISON_NULL:
106                 case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL:
107                 case CAN_ONLY_NULL | IN_ASSIGNMENT:
108                 case CAN_ONLY_NULL | IN_INSTANCEOF:
109                     if (flowInfo.isDefinitelyNull(local)) {
110                         switch(this.nullCheckTypes[i] & CONTEXT_MASK) {
111                             case FlowContext.IN_COMPARISON_NULL:
112                                 scope.problemReporter().localVariableRedundantCheckOnNull(local, expression);
113                                 continue;
114                             case FlowContext.IN_COMPARISON_NON_NULL:
115                                 scope.problemReporter().localVariableNullComparedToNonNull(local, expression);
116                                 continue;
117                             case FlowContext.IN_ASSIGNMENT:
118                                 scope.problemReporter().localVariableRedundantNullAssignment(local, expression);
119                                 continue;
120                             case FlowContext.IN_INSTANCEOF:
121                                 scope.problemReporter().localVariableNullInstanceof(local, expression);
122                                 continue;
123                         }
124                     }
125                     break;
126                 case MAY_NULL:
127                     if (flowInfo.isDefinitelyNull(local)) {
128                         scope.problemReporter().localVariableNullReference(local, expression);
129                         continue;
130                     }
131                     if (flowInfo.isPotentiallyNull(local)) {
132                         scope.problemReporter().localVariablePotentialNullReference(local, expression);
133                     }
134                     break;
135                 default:
136                     // should not happen
137
}
138         }
139     }
140 }
141     
142     public String JavaDoc individualToString() {
143         
144         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("Finally flow context"); //$NON-NLS-1$
145
buffer.append("[finalAssignments count - ").append(assignCount).append(']'); //$NON-NLS-1$
146
buffer.append("[nullReferences count - ").append(nullCount).append(']'); //$NON-NLS-1$
147
return buffer.toString();
148     }
149     
150     public boolean isSubRoutine() {
151         return true;
152     }
153     
154     protected boolean recordFinalAssignment(
155         VariableBinding binding,
156         Reference finalAssignment) {
157         if (assignCount == 0) {
158             finalAssignments = new Reference[5];
159             finalVariables = new VariableBinding[5];
160         } else {
161             if (assignCount == finalAssignments.length)
162                 System.arraycopy(
163                     finalAssignments,
164                     0,
165                     (finalAssignments = new Reference[assignCount * 2]),
166                     0,
167                     assignCount);
168             System.arraycopy(
169                 finalVariables,
170                 0,
171                 (finalVariables = new VariableBinding[assignCount * 2]),
172                 0,
173                 assignCount);
174         }
175         finalAssignments[assignCount] = finalAssignment;
176         finalVariables[assignCount++] = binding;
177         return true;
178     }
179
180     public void recordUsingNullReference(Scope scope, LocalVariableBinding local,
181             Expression reference, int checkType, FlowInfo flowInfo) {
182         if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0 && !flowInfo.isDefinitelyUnknown(local)) {
183             if (deferNullDiagnostic) { // within an enclosing loop, be conservative
184
switch (checkType) {
185                     case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL:
186                     case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL:
187                     case CAN_ONLY_NULL | IN_COMPARISON_NULL:
188                     case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL:
189                     case CAN_ONLY_NULL | IN_ASSIGNMENT:
190                     case CAN_ONLY_NULL | IN_INSTANCEOF:
191                         if (flowInfo.cannotBeNull(local)) {
192                             if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
193                                 scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference);
194                             } else {
195                                 scope.problemReporter().localVariableNonNullComparedToNull(local, reference);
196                             }
197                             return;
198                         }
199                         if (flowInfo.canOnlyBeNull(local)) {
200                             switch(checkType & CONTEXT_MASK) {
201                                 case FlowContext.IN_COMPARISON_NULL:
202                                     scope.problemReporter().localVariableRedundantCheckOnNull(local, reference);
203                                     return;
204                                 case FlowContext.IN_COMPARISON_NON_NULL:
205                                     scope.problemReporter().localVariableNullComparedToNonNull(local, reference);
206                                     return;
207                                 case FlowContext.IN_ASSIGNMENT:
208                                     scope.problemReporter().localVariableRedundantNullAssignment(local, reference);
209                                     return;
210                                 case FlowContext.IN_INSTANCEOF:
211                                     scope.problemReporter().localVariableNullInstanceof(local, reference);
212                                     return;
213                             }
214                         }
215                         break;
216                     case MAY_NULL :
217                         if (flowInfo.cannotBeNull(local)) {
218                             return;
219                         }
220                         if (flowInfo.canOnlyBeNull(local)) {
221                             scope.problemReporter().localVariableNullReference(local, reference);
222                             return;
223                         }
224                         break;
225                     default:
226                         // never happens
227
}
228             }
229             else { // no enclosing loop, be as precise as possible right now
230
switch (checkType) {
231                     case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL:
232                     case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL:
233                         if (flowInfo.isDefinitelyNonNull(local)) {
234                             if (checkType == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
235                                 scope.problemReporter().localVariableRedundantCheckOnNonNull(local, reference);
236                             } else {
237                                 scope.problemReporter().localVariableNonNullComparedToNull(local, reference);
238                             }
239                             return;
240                         }
241                     case CAN_ONLY_NULL | IN_COMPARISON_NULL:
242                     case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL:
243                     case CAN_ONLY_NULL | IN_ASSIGNMENT:
244                     case CAN_ONLY_NULL | IN_INSTANCEOF:
245                         if (flowInfo.isDefinitelyNull(local)) {
246                             switch(checkType & CONTEXT_MASK) {
247                                 case FlowContext.IN_COMPARISON_NULL:
248                                     scope.problemReporter().localVariableRedundantCheckOnNull(local, reference);
249                                     return;
250                                 case FlowContext.IN_COMPARISON_NON_NULL:
251                                     scope.problemReporter().localVariableNullComparedToNonNull(local, reference);
252                                     return;
253                                 case FlowContext.IN_ASSIGNMENT:
254                                     scope.problemReporter().localVariableRedundantNullAssignment(local, reference);
255                                     return;
256                                 case FlowContext.IN_INSTANCEOF:
257                                     scope.problemReporter().localVariableNullInstanceof(local, reference);
258                                     return;
259                             }
260                         }
261                         break;
262                     case MAY_NULL :
263                         if (flowInfo.isDefinitelyNull(local)) {
264                             scope.problemReporter().localVariableNullReference(local, reference);
265                             return;
266                         }
267                         if (flowInfo.isPotentiallyNull(local)) {
268                             scope.problemReporter().localVariablePotentialNullReference(local, reference);
269                             return;
270                         }
271                         if (flowInfo.isDefinitelyNonNull(local)) {
272                             return; // shortcut: cannot be null
273
}
274                         break;
275                     default:
276                         // never happens
277
}
278             }
279             recordNullReference(local, reference, checkType);
280             // prepare to re-check with try/catch flow info
281
}
282     }
283     
284     void removeFinalAssignmentIfAny(Reference reference) {
285         for (int i = 0; i < assignCount; i++) {
286             if (finalAssignments[i] == reference) {
287                 finalAssignments[i] = null;
288                 finalVariables[i] = null;
289                 return;
290             }
291         }
292     }
293
294 protected void recordNullReference(LocalVariableBinding local,
295     Expression expression, int status) {
296     if (this.nullCount == 0) {
297         this.nullLocals = new LocalVariableBinding[5];
298         this.nullReferences = new Expression[5];
299         this.nullCheckTypes = new int[5];
300     }
301     else if (this.nullCount == this.nullLocals.length) {
302         int newLength = this.nullCount * 2;
303         System.arraycopy(this.nullLocals, 0,
304             this.nullLocals = new LocalVariableBinding[newLength], 0,
305             this.nullCount);
306         System.arraycopy(this.nullReferences, 0,
307             this.nullReferences = new Expression[newLength], 0,
308             this.nullCount);
309         System.arraycopy(this.nullCheckTypes, 0,
310             this.nullCheckTypes = new int[newLength], 0,
311             this.nullCount);
312     }
313     this.nullLocals[this.nullCount] = local;
314     this.nullReferences[this.nullCount] = expression;
315     this.nullCheckTypes[this.nullCount++] = status;
316 }
317 }
318
Popular Tags