private static void forceNotNull(DataFlowRunner runner, DfaMemoryState memState, DfaValue arg) { if (arg instanceof DfaVariableValue) { DfaVariableValue var = (DfaVariableValue) arg; memState.setVarValue( var, runner.getFactory().createTypeValue(var.getVariableType(), Nullness.NOT_NULL)); } }
@Override public DfaInstructionState[] visitAssign( AssignInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) { DfaValue dfaSource = memState.pop(); DfaValue dfaDest = memState.pop(); if (dfaDest instanceof DfaVariableValue) { DfaVariableValue var = (DfaVariableValue) dfaDest; DfaValueFactory factory = runner.getFactory(); if (dfaSource instanceof DfaVariableValue && factory.getVarFactory().getAllQualifiedBy(var).contains(dfaSource)) { Nullness nullability = memState.isNotNull(dfaSource) ? Nullness.NOT_NULL : ((DfaVariableValue) dfaSource).getInherentNullability(); dfaSource = factory.createTypeValue(((DfaVariableValue) dfaSource).getVariableType(), nullability); } if (var.getInherentNullability() == Nullness.NOT_NULL) { checkNotNullable( memState, dfaSource, NullabilityProblem.assigningToNotNull, instruction.getRExpression()); } final PsiModifierListOwner psi = var.getPsiVariable(); if (!(psi instanceof PsiField) || !psi.hasModifierProperty(PsiModifier.VOLATILE)) { memState.setVarValue(var, dfaSource); } } else if (dfaDest instanceof DfaTypeValue && ((DfaTypeValue) dfaDest).isNotNull()) { checkNotNullable( memState, dfaSource, NullabilityProblem.assigningToNotNull, instruction.getRExpression()); } memState.push(dfaDest); return nextInstruction(instruction, runner, memState); }
@Nullable private static DfaInstructionState[] checkComparingWithConstant( BinopInstruction instruction, DataFlowRunner runner, DfaMemoryState memState, DfaVariableValue var, IElementType opSign, double comparedWith) { DfaConstValue knownConstantValue = memState.getConstantValue(var); Object knownValue = knownConstantValue == null ? null : knownConstantValue.getValue(); if (knownValue instanceof Number) { double knownDouble = ((Number) knownValue).doubleValue(); return checkComparisonWithKnownRange( instruction, runner, memState, opSign, comparedWith, knownDouble, knownDouble); } PsiType varType = var.getVariableType(); if (!(varType instanceof PsiPrimitiveType)) return null; if (varType == PsiType.FLOAT || varType == PsiType.DOUBLE) return null; double minValue = varType == PsiType.BYTE ? Byte.MIN_VALUE : varType == PsiType.SHORT ? Short.MIN_VALUE : varType == PsiType.INT ? Integer.MIN_VALUE : varType == PsiType.CHAR ? Character.MIN_VALUE : Long.MIN_VALUE; double maxValue = varType == PsiType.BYTE ? Byte.MAX_VALUE : varType == PsiType.SHORT ? Short.MAX_VALUE : varType == PsiType.INT ? Integer.MAX_VALUE : varType == PsiType.CHAR ? Character.MAX_VALUE : Long.MAX_VALUE; return checkComparisonWithKnownRange( instruction, runner, memState, opSign, comparedWith, minValue, maxValue); }