public FlowInfo analyseCode( BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) { switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD: // reading a field if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); } // check if reading a final blank field FieldBinding fieldBinding = (FieldBinding) this.binding; if (fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) { FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck( fieldBinding.declaringClass.original(), flowInfo); if (!fieldInits.isDefinitelyAssigned(fieldBinding)) { currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); } } if (!fieldBinding.isStatic()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682 currentScope.resetEnclosingMethodStaticFlag(); } break; case Binding.LOCAL: // reading a local variable LocalVariableBinding localBinding; if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) { currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); } if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { localBinding.useFlag = LocalVariableBinding.USED; } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) { localBinding.useFlag = LocalVariableBinding.FAKE_USED; } } if (valueRequired) { manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); } return flowInfo; }
public FlowInfo analyseAssignment( BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) { boolean isReachable = (flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0; // compound assignment extra work if (isCompound) { // check the variable part is initialized if blank final switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD: // reading a field FieldBinding fieldBinding = (FieldBinding) this.binding; if (fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) { FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck( fieldBinding.declaringClass.original(), flowInfo); if (!fieldInits.isDefinitelyAssigned(fieldBinding)) { currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); } } if (!fieldBinding.isStatic()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682 currentScope.resetEnclosingMethodStaticFlag(); } manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); break; case Binding.LOCAL: // reading a local variable // check if assigning a final blank field LocalVariableBinding localBinding; if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) { currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); // we could improve error msg here telling "cannot use compound assignment on final // local variable" } if (localBinding.useFlag != LocalVariableBinding.USED) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682 // access from compound assignment does not prevent "unused" warning, unless unboxing is // involved: if (isReachable && (this.implicitConversion & TypeIds.UNBOXING) != 0) { localBinding.useFlag = LocalVariableBinding.USED; } else { // use values < 0 to count the number of compound uses: if (localBinding.useFlag <= LocalVariableBinding.UNUSED) localBinding.useFlag--; } } } } if (assignment.expression != null) { flowInfo = assignment .expression .analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); } switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.FIELD: // assigning to a field manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/); // check if assigning a final field FieldBinding fieldBinding = (FieldBinding) this.binding; if (fieldBinding.isFinal()) { // inside a context where allowed if (!isCompound && fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) { if (flowInfo.isPotentiallyAssigned(fieldBinding)) { currentScope .problemReporter() .duplicateInitializationOfBlankFinalField(fieldBinding, this); } else { flowContext.recordSettingFinal(fieldBinding, this, flowInfo); } flowInfo.markAsDefinitelyAssigned(fieldBinding); } else { currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this); } } if (!fieldBinding.isStatic()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682 currentScope.resetEnclosingMethodStaticFlag(); } break; case Binding.LOCAL: // assigning to a local variable LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; if (!flowInfo.isDefinitelyAssigned(localBinding)) { // for local variable debug attributes this.bits |= ASTNode.FirstAssignmentToLocal; } else { this.bits &= ~ASTNode.FirstAssignmentToLocal; } if (localBinding.isFinal()) { if ((this.bits & ASTNode.DepthMASK) == 0) { // tolerate assignment to final local in unreachable code (45674) if ((isReachable && isCompound) || !localBinding.isBlankFinal()) { currentScope.problemReporter().cannotAssignToFinalLocal(localBinding, this); } else if (flowInfo.isPotentiallyAssigned(localBinding)) { currentScope .problemReporter() .duplicateInitializationOfFinalLocal(localBinding, this); } else { flowContext.recordSettingFinal(localBinding, this, flowInfo); } } else { currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this); } } else /* avoid double diagnostic */ if ((localBinding.tagBits & TagBits.IsArgument) != 0) { currentScope.problemReporter().parameterAssignment(localBinding, this); } flowInfo.markAsDefinitelyAssigned(localBinding); } manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); return flowInfo; }