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)); } }
private boolean hardEquals( PsiModifierListOwner psiVar, PsiType varType, boolean negated, DfaVariableValue qualifier) { return psiVar == myVariable && Comparing.equal( TypeConversionUtil.erasure(varType), TypeConversionUtil.erasure(myVarType)) && negated == myIsNegated && (myQualifier == null ? qualifier == null : myQualifier.hardEquals( qualifier.getPsiVariable(), qualifier.getVariableType(), qualifier.isNegated(), qualifier.getQualifier())); }
public boolean isFlushableByCalls() { if (myVariable instanceof PsiLocalVariable || myVariable instanceof PsiParameter) return false; if (myVariable instanceof PsiVariable && myVariable.hasModifierProperty(PsiModifier.FINAL)) { return myQualifier != null && myQualifier.isFlushableByCalls(); } return true; }
@NotNull public DfaVariableValue createVariableValue( @NotNull PsiModifierListOwner myVariable, @Nullable PsiType varType, boolean isNegated, @Nullable DfaVariableValue qualifier) { Trinity<Boolean, String, DfaVariableValue> key = Trinity.create(isNegated, ((PsiNamedElement) myVariable).getName(), qualifier); for (DfaVariableValue aVar : myExistingVars.get(key)) { if (aVar.hardEquals(myVariable, varType, isNegated, qualifier)) return aVar; } DfaVariableValue result = new DfaVariableValue(myVariable, varType, isNegated, myFactory, qualifier); myExistingVars.putValue(key, result); while (qualifier != null) { qualifier.myDependents.add(result); qualifier = qualifier.getQualifier(); } return result; }
@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); }
public boolean containsCalls() { return myVariable instanceof PsiMethod || myQualifier != null && myQualifier.containsCalls(); }
@SuppressWarnings({"HardCodedStringLiteral"}) public String toString() { return (myIsNegated ? "!" : "") + ((PsiNamedElement) myVariable).getName() + (myQualifier == null ? "" : "|" + myQualifier.toString()); }