<s> package org . eclipse . jdt . internal . compiler . flow ; import org . eclipse . jdt . internal . compiler . ast . ASTNode ; import org . eclipse . jdt . internal . compiler . ast . Expression ; import org . eclipse . jdt . internal . compiler . ast . Reference ; import org . eclipse . jdt . internal . compiler . lookup . BlockScope ; import org . eclipse . jdt . internal . compiler . lookup . FieldBinding ; import org . eclipse . jdt . internal . compiler . lookup . LocalVariableBinding ; import org . eclipse . jdt . internal . compiler . lookup . Scope ; import org . eclipse . jdt . internal . compiler . lookup . TypeIds ; import org . eclipse . jdt . internal . compiler . lookup . VariableBinding ; public class FinallyFlowContext extends FlowContext { Reference [ ] finalAssignments ; VariableBinding [ ] finalVariables ; int assignCount ; LocalVariableBinding [ ] nullLocals ; Expression [ ] nullReferences ; int [ ] nullCheckTypes ; int nullCount ; public FinallyFlowContext ( FlowContext parent , ASTNode associatedNode ) { super ( parent , associatedNode ) ; } public void complainOnDeferredChecks ( FlowInfo flowInfo , BlockScope scope ) { for ( int i = 0 ; i < this . assignCount ; i ++ ) { VariableBinding variable = this . finalVariables [ i ] ; if ( variable == null ) continue ; boolean complained = false ; if ( variable instanceof FieldBinding ) { if ( flowInfo . isPotentiallyAssigned ( ( FieldBinding ) variable ) ) { complained = true ; scope . problemReporter ( ) . duplicateInitializationOfBlankFinalField ( ( FieldBinding ) variable , this . finalAssignments [ i ] ) ; } } else { if ( flowInfo . isPotentiallyAssigned ( ( LocalVariableBinding ) variable ) ) { complained = true ; scope . problemReporter ( ) . duplicateInitializationOfFinalLocal ( ( LocalVariableBinding ) variable , this . finalAssignments [ i ] ) ; } } if ( complained ) { FlowContext currentContext = this . parent ; while ( currentContext != null ) { currentContext . removeFinalAssignmentIfAny ( this . finalAssignments [ i ] ) ; currentContext = currentContext . parent ; } } } if ( ( this . tagBits & FlowContext . DEFER_NULL_DIAGNOSTIC ) != 0 ) { for ( int i = 0 ; i < this . nullCount ; i ++ ) { this . parent . recordUsingNullReference ( scope , this . nullLocals [ i ] , this . nullReferences [ i ] , this . nullCheckTypes [ i ] , flowInfo ) ; } } else { for ( int i = 0 ; i < this . nullCount ; i ++ ) { Expression expression = this . nullReferences [ i ] ; LocalVariableBinding local = this . nullLocals [ i ] ; switch ( this . nullCheckTypes [ i ] ) { case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL : case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL : if ( flowInfo . isDefinitelyNonNull ( local ) ) { if ( this . nullCheckTypes [ i ] == ( CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL ) ) { if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableRedundantCheckOnNonNull ( local , expression ) ; } } else { if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableNonNullComparedToNull ( local , expression ) ; } } continue ; } case CAN_ONLY_NULL | IN_COMPARISON_NULL : case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL : case CAN_ONLY_NULL | IN_ASSIGNMENT : case CAN_ONLY_NULL | IN_INSTANCEOF : if ( flowInfo . isDefinitelyNull ( local ) ) { switch ( this . nullCheckTypes [ i ] & CONTEXT_MASK ) { case FlowContext . IN_COMPARISON_NULL : if ( ( ( this . nullCheckTypes [ i ] & CHECK_MASK ) == CAN_ONLY_NULL ) && ( expression . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariableNullReference ( local , expression ) ; continue ; } if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableRedundantCheckOnNull ( local , expression ) ; } continue ; case FlowContext . IN_COMPARISON_NON_NULL : if ( ( ( this . nullCheckTypes [ i ] & CHECK_MASK ) == CAN_ONLY_NULL ) && ( expression . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariableNullReference ( local , expression ) ; continue ; } if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableNullComparedToNonNull ( local , expression ) ; } continue ; case FlowContext . IN_ASSIGNMENT : scope . problemReporter ( ) . localVariableRedundantNullAssignment ( local , expression ) ; continue ; case FlowContext . IN_INSTANCEOF : scope . problemReporter ( ) . localVariableNullInstanceof ( local , expression ) ; continue ; } } else if ( flowInfo . isPotentiallyNull ( local ) ) { switch ( this . nullCheckTypes [ i ] & CONTEXT_MASK ) { case FlowContext . IN_COMPARISON_NULL : this . nullReferences [ i ] = null ; if ( ( ( this . nullCheckTypes [ i ] & CHECK_MASK ) == CAN_ONLY_NULL ) && ( expression . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariablePotentialNullReference ( local , expression ) ; continue ; } break ; case FlowContext . IN_COMPARISON_NON_NULL : this . nullReferences [ i ] = null ; if ( ( ( this . nullCheckTypes [ i ] & CHECK_MASK ) == CAN_ONLY_NULL ) && ( expression . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariablePotentialNullReference ( local , expression ) ; continue ; } break ; } } break ; case MAY_NULL : if ( flowInfo . isDefinitelyNull ( local ) ) { scope . problemReporter ( ) . localVariableNullReference ( local , expression ) ; continue ; } if ( flowInfo . isPotentiallyNull ( local ) ) { scope . problemReporter ( ) . localVariablePotentialNullReference ( local , expression ) ; } break ; default : } } } } public String individualToString ( ) { StringBuffer buffer = new StringBuffer ( "" ) ; buffer . append ( "" ) . append ( this . assignCount ) . append ( ']' ) ; buffer . append ( "" ) . append ( this . nullCount ) . append ( ']' ) ; return buffer . toString ( ) ; } public boolean isSubRoutine ( ) { return true ; } protected boolean recordFinalAssignment ( VariableBinding binding , Reference finalAssignment ) { if ( this . assignCount == 0 ) { this . finalAssignments = new Reference [ 5 ] ; this . finalVariables = new VariableBinding [ 5 ] ; } else { if ( this . assignCount == this . finalAssignments . length ) System . arraycopy ( this . finalAssignments , 0 , ( this . finalAssignments = new Reference [ this . assignCount * 2 ] ) , 0 , this . assignCount ) ; System . arraycopy ( this . finalVariables , 0 , ( this . finalVariables = new VariableBinding [ this . assignCount * 2 ] ) , 0 , this . assignCount ) ; } this . finalAssignments [ this . assignCount ] = finalAssignment ; this . finalVariables [ this . assignCount ++ ] = binding ; return true ; } public void recordUsingNullReference ( Scope scope , LocalVariableBinding local , Expression reference , int checkType , FlowInfo flowInfo ) { if ( ( flowInfo . tagBits & FlowInfo . UNREACHABLE ) == 0 && ! flowInfo . isDefinitelyUnknown ( local ) ) { if ( ( this . tagBits & FlowContext . DEFER_NULL_DIAGNOSTIC ) != 0 ) { switch ( checkType ) { case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL : case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL : case CAN_ONLY_NULL | IN_COMPARISON_NULL : case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL : case CAN_ONLY_NULL | IN_ASSIGNMENT : case CAN_ONLY_NULL | IN_INSTANCEOF : if ( flowInfo . cannotBeNull ( local ) ) { if ( checkType == ( CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL ) ) { if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableRedundantCheckOnNonNull ( local , reference ) ; } if ( ! flowInfo . isMarkedAsNullOrNonNullInAssertExpression ( local ) ) { flowInfo . initsWhenFalse ( ) . setReachMode ( FlowInfo . UNREACHABLE_BY_NULLANALYSIS ) ; } } else if ( checkType == ( CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL ) ) { if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableNonNullComparedToNull ( local , reference ) ; } if ( ! flowInfo . isMarkedAsNullOrNonNullInAssertExpression ( local ) ) { flowInfo . initsWhenTrue ( ) . setReachMode ( FlowInfo . UNREACHABLE_BY_NULLANALYSIS ) ; } } return ; } if ( flowInfo . canOnlyBeNull ( local ) ) { switch ( checkType & CONTEXT_MASK ) { case FlowContext . IN_COMPARISON_NULL : if ( ( ( checkType & CHECK_MASK ) == CAN_ONLY_NULL ) && ( reference . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariableNullReference ( local , reference ) ; return ; } if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableRedundantCheckOnNull ( local , reference ) ; } if ( ! flowInfo . isMarkedAsNullOrNonNullInAssertExpression ( local ) ) { flowInfo . initsWhenFalse ( ) . setReachMode ( FlowInfo . UNREACHABLE_BY_NULLANALYSIS ) ; } return ; case FlowContext . IN_COMPARISON_NON_NULL : if ( ( ( checkType & CHECK_MASK ) == CAN_ONLY_NULL ) && ( reference . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariableNullReference ( local , reference ) ; return ; } if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableNullComparedToNonNull ( local , reference ) ; } if ( ! flowInfo . isMarkedAsNullOrNonNullInAssertExpression ( local ) ) { flowInfo . initsWhenTrue ( ) . setReachMode ( FlowInfo . UNREACHABLE_BY_NULLANALYSIS ) ; } return ; case FlowContext . IN_ASSIGNMENT : scope . problemReporter ( ) . localVariableRedundantNullAssignment ( local , reference ) ; return ; case FlowContext . IN_INSTANCEOF : scope . problemReporter ( ) . localVariableNullInstanceof ( local , reference ) ; return ; } } else if ( flowInfo . isPotentiallyNull ( local ) ) { switch ( checkType & CONTEXT_MASK ) { case FlowContext . IN_COMPARISON_NULL : if ( ( ( checkType & CHECK_MASK ) == CAN_ONLY_NULL ) && ( reference . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariablePotentialNullReference ( local , reference ) ; return ; } break ; case FlowContext . IN_COMPARISON_NON_NULL : if ( ( ( checkType & CHECK_MASK ) == CAN_ONLY_NULL ) && ( reference . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariablePotentialNullReference ( local , reference ) ; return ; } break ; } } break ; case MAY_NULL : if ( flowInfo . cannotBeNull ( local ) ) { return ; } if ( flowInfo . canOnlyBeNull ( local ) ) { scope . problemReporter ( ) . localVariableNullReference ( local , reference ) ; return ; } break ; default : } } else { switch ( checkType ) { case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL : case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL : if ( flowInfo . isDefinitelyNonNull ( local ) ) { if ( checkType == ( CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL ) ) { if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableRedundantCheckOnNonNull ( local , reference ) ; } if ( ! flowInfo . isMarkedAsNullOrNonNullInAssertExpression ( local ) ) { flowInfo . initsWhenFalse ( ) . setReachMode ( FlowInfo . UNREACHABLE_BY_NULLANALYSIS ) ; } } else { if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableNonNullComparedToNull ( local , reference ) ; } if ( ! flowInfo . isMarkedAsNullOrNonNullInAssertExpression ( local ) ) { flowInfo . initsWhenTrue ( ) . setReachMode ( FlowInfo . UNREACHABLE_BY_NULLANALYSIS ) ; } } return ; } case CAN_ONLY_NULL | IN_COMPARISON_NULL : case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL : case CAN_ONLY_NULL | IN_ASSIGNMENT : case CAN_ONLY_NULL | IN_INSTANCEOF : if ( flowInfo . isDefinitelyNull ( local ) ) { switch ( checkType & CONTEXT_MASK ) { case FlowContext . IN_COMPARISON_NULL : if ( ( ( checkType & CHECK_MASK ) == CAN_ONLY_NULL ) && ( reference . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariableNullReference ( local , reference ) ; return ; } if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableRedundantCheckOnNull ( local , reference ) ; } if ( ! flowInfo . isMarkedAsNullOrNonNullInAssertExpression ( local ) ) { flowInfo . initsWhenFalse ( ) . setReachMode ( FlowInfo . UNREACHABLE_BY_NULLANALYSIS ) ; } return ; case FlowContext . IN_COMPARISON_NON_NULL : if ( ( ( checkType & CHECK_MASK ) == CAN_ONLY_NULL ) && ( reference . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariableNullReference ( local , reference ) ; return ; } if ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) { scope . problemReporter ( ) . localVariableNullComparedToNonNull ( local , reference ) ; } if ( ! flowInfo . isMarkedAsNullOrNonNullInAssertExpression ( local ) ) { flowInfo . initsWhenTrue ( ) . setReachMode ( FlowInfo . UNREACHABLE_BY_NULLANALYSIS ) ; } return ; case FlowContext . IN_ASSIGNMENT : scope . problemReporter ( ) . localVariableRedundantNullAssignment ( local , reference ) ; return ; case FlowContext . IN_INSTANCEOF : scope . problemReporter ( ) . localVariableNullInstanceof ( local , reference ) ; return ; } } else if ( flowInfo . isPotentiallyNull ( local ) ) { switch ( checkType & CONTEXT_MASK ) { case FlowContext . IN_COMPARISON_NULL : if ( ( ( checkType & CHECK_MASK ) == CAN_ONLY_NULL ) && ( reference . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariablePotentialNullReference ( local , reference ) ; return ; } break ; case FlowContext . IN_COMPARISON_NON_NULL : if ( ( ( checkType & CHECK_MASK ) == CAN_ONLY_NULL ) && ( reference . implicitConversion & TypeIds . UNBOXING ) != 0 ) { scope . problemReporter ( ) . localVariablePotentialNullReference ( local , reference ) ; return ; } break ; } } break ; case MAY_NULL : if ( flowInfo . isDefinitelyNull ( local ) ) { scope . problemReporter ( ) . localVariableNullReference ( local , reference ) ; return ; } if ( flowInfo . isPotentiallyNull ( local ) ) { scope . problemReporter ( ) . localVariablePotentialNullReference ( local , reference ) ; return ; } if ( flowInfo . isDefinitelyNonNull ( local ) ) { return ; } break ; default : } } if ( ( ( this . tagBits & FlowContext . HIDE_NULL_COMPARISON_WARNING ) == 0 ) || checkType == MAY_NULL || ( checkType & CONTEXT_MASK ) == FlowContext . IN_ASSIGNMENT || ( checkType & CONTEXT_MASK ) == FlowContext . IN_INSTANCEOF ) { recordNullReference ( local , reference , checkType ) ; } } } void removeFinalAssignmentIfAny ( Reference reference ) { for ( int i = 0 ; i < this . assignCount ; i ++ ) { if ( this . finalAssignments [ i ] == reference ) { this . finalAssignments [ i ] = null ; this . finalVariables [ i ] = null ; return ; } } } protected void recordNullReference ( LocalVariableBinding local , Expression expression , int status ) { if ( this . nullCount == 0 ) { this . nullLocals = new LocalVariableBinding [ 5 ] ; this . nullReferences = new Expression [ 5 ] ; this . nullCheckTypes = new int [ 5 ] ; } else if ( this . nullCount == this . nullLocals . length ) { int newLength = this . nullCount * 2 ; System . arraycopy ( this . nullLocals , 0 , this . nullLocals = new LocalVariableBinding [ newLength ] , 0 , this . nullCount ) ; System . arraycopy ( this . nullReferences , 0 , this . nullReferences = new Expression [ newLength ] , 0 , this . nullCount ) ; System . arraycopy ( this . nullCheckTypes , 0 , this . nullCheckTypes = new int [ newLength ] , 0 , this . nullCount ) ; } this . nullLocals [ this . nullCount ] = local ; this . nullReferences [ this . nullCount ] = expression ; this . nullCheckTypes [ this . nullCount ++ ] = status ; } } </s>