1 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 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 46 public void complainOnDeferredChecks(FlowInfo flowInfo, BlockScope scope) { 47 48 for (int i = 0; i < this.assignCount; i++) { 50 VariableBinding variable = this.finalVariables[i]; 51 if (variable == null) continue; 52 53 boolean complained = false; if (variable instanceof FieldBinding) { 55 if (flowInfo.isPotentiallyAssigned((FieldBinding)variable)) { 57 complained = true; 58 scope.problemReporter().duplicateInitializationOfBlankFinalField((FieldBinding)variable, finalAssignments[i]); 59 } 60 } else { 61 if (flowInfo.isPotentiallyAssigned((LocalVariableBinding) variable)) { 63 complained = true; 64 scope.problemReporter().duplicateInitializationOfFinalLocal( 65 (LocalVariableBinding) variable, 66 this.finalAssignments[i]); 67 } 68 } 69 if (complained) { 72 FlowContext currentContext = this.parent; 73 while (currentContext != null) { 74 currentContext.removeFinalAssignmentIfAny(this.finalAssignments[i]); 76 currentContext = currentContext.parent; 78 } 79 } 80 } 81 82 if (this.deferNullDiagnostic) { 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 { for (int i = 0; i < this.nullCount; i++) { 91 Expression expression = this.nullReferences[i]; 92 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 } 138 } 139 } 140 } 141 142 public String individualToString() { 143 144 StringBuffer buffer = new StringBuffer ("Finally flow context"); buffer.append("[finalAssignments count - ").append(assignCount).append(']'); buffer.append("[nullReferences count - ").append(nullCount).append(']'); 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) { 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 } 228 } 229 else { 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; } 274 break; 275 default: 276 } 278 } 279 recordNullReference(local, reference, checkType); 280 } 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 |