@Override public boolean applyCondition(DfaValue dfaCond) { if (dfaCond instanceof DfaUnknownValue) return true; if (dfaCond instanceof DfaUnboxedValue) { DfaVariableValue dfaVar = ((DfaUnboxedValue) dfaCond).getVariable(); boolean isNegated = dfaVar.isNegated(); DfaVariableValue dfaNormalVar = isNegated ? dfaVar.createNegated() : dfaVar; final DfaValue boxedTrue = myFactory.getBoxedFactory().createBoxed(myFactory.getConstFactory().getTrue()); return applyRelationCondition( myFactory .getRelationFactory() .createRelation(dfaNormalVar, boxedTrue, JavaTokenType.EQEQ, isNegated)); } if (dfaCond instanceof DfaVariableValue) { DfaVariableValue dfaVar = (DfaVariableValue) dfaCond; boolean isNegated = dfaVar.isNegated(); DfaVariableValue dfaNormalVar = isNegated ? dfaVar.createNegated() : dfaVar; DfaConstValue dfaTrue = myFactory.getConstFactory().getTrue(); return applyRelationCondition( myFactory .getRelationFactory() .createRelation(dfaNormalVar, dfaTrue, JavaTokenType.EQEQ, isNegated)); } if (dfaCond instanceof DfaConstValue) { return dfaCond == myFactory.getConstFactory().getTrue() || dfaCond != myFactory.getConstFactory().getFalse(); } if (!(dfaCond instanceof DfaRelationValue)) return true; return applyRelationCondition((DfaRelationValue) dfaCond); }
@Nullable private DfaRelationValue compareToNull(DfaValue dfaVar, boolean negated) { DfaConstValue dfaNull = myFactory.getConstFactory().getNull(); return myFactory .getRelationFactory() .createRelation(dfaVar, dfaNull, JavaTokenType.EQEQ, negated); }
@Override public void setVarValue(DfaVariableValue var, DfaValue value) { if (var == value) return; value = handleFlush(var, value); flushVariable(var); if (value instanceof DfaUnknownValue) { setVariableState(var, getVariableState(var).withNullable(false)); return; } setVariableState(var, getVariableState(var).withValue(value)); if (value instanceof DfaTypeValue) { setVariableState( var, getVariableState(var).withNullability(((DfaTypeValue) value).getNullness())); DfaRelationValue dfaInstanceof = myFactory .getRelationFactory() .createRelation(var, value, JavaTokenType.INSTANCEOF_KEYWORD, false); if (((DfaTypeValue) value).isNotNull()) { applyCondition(dfaInstanceof); } else { applyInstanceofOrNull(dfaInstanceof); } } else { DfaRelationValue dfaEqual = myFactory.getRelationFactory().createRelation(var, value, JavaTokenType.EQEQ, false); if (dfaEqual == null) return; applyCondition(dfaEqual); if (value instanceof DfaVariableValue) { setVariableState(var, getVariableState((DfaVariableValue) value)); } } if (getVariableState(var).isNotNull()) { applyCondition(compareToNull(var, true)); } }
protected boolean checkNotNullable( DfaMemoryState state, DfaValue value, NullabilityProblem problem, PsiElement anchor) { boolean notNullable = state.checkNotNullable(value); if (notNullable && problem != NullabilityProblem.passingNullableArgumentToNonAnnotatedParameter) { DfaValueFactory factory = ((DfaMemoryStateImpl) state).getFactory(); state.applyCondition( factory .getRelationFactory() .createRelation(value, factory.getConstFactory().getNull(), NE, false)); } return notNullable; }
@Nullable private DfaInstructionState[] handleRelationBinop( BinopInstruction instruction, DataFlowRunner runner, DfaMemoryState memState, DfaValue dfaRight, DfaValue dfaLeft) { DfaValueFactory factory = runner.getFactory(); final Instruction next = runner.getInstruction(instruction.getIndex() + 1); DfaRelationValue dfaRelation = factory .getRelationFactory() .createRelation(dfaLeft, dfaRight, instruction.getOperationSign(), false); if (dfaRelation == null) { return null; } myCanBeNullInInstanceof.add(instruction); ArrayList<DfaInstructionState> states = new ArrayList<DfaInstructionState>(); final DfaMemoryState trueCopy = memState.createCopy(); if (trueCopy.applyCondition(dfaRelation)) { trueCopy.push(factory.getConstFactory().getTrue()); instruction.setTrueReachable(); states.add(new DfaInstructionState(next, trueCopy)); } //noinspection UnnecessaryLocalVariable DfaMemoryState falseCopy = memState; if (falseCopy.applyCondition(dfaRelation.createNegated())) { falseCopy.push(factory.getConstFactory().getFalse()); instruction.setFalseReachable(); states.add(new DfaInstructionState(next, falseCopy)); if (instruction instanceof InstanceofInstruction && !falseCopy.isNull(dfaLeft)) { myUsefulInstanceofs.add((InstanceofInstruction) instruction); } } return states.toArray(new DfaInstructionState[states.size()]); }
@Override public DfaInstructionState[] visitTypeCast( TypeCastInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) { final DfaValueFactory factory = runner.getFactory(); DfaValue dfaExpr = factory.createValue(instruction.getCasted()); if (dfaExpr != null) { DfaTypeValue dfaType = (DfaTypeValue) factory.createTypeValue(instruction.getCastTo(), Nullness.UNKNOWN); DfaRelationValue dfaInstanceof = factory.getRelationFactory().createRelation(dfaExpr, dfaType, INSTANCEOF_KEYWORD, false); if (dfaInstanceof != null && !memState.applyInstanceofOrNull(dfaInstanceof)) { onInstructionProducesCCE(instruction); } } if (instruction.getCastTo() instanceof PsiPrimitiveType) { memState.push(runner.getFactory().getBoxedFactory().createUnboxed(memState.pop())); } return nextInstruction(instruction, runner, memState); }
private List<DfaMemoryState> addContractResults( DfaValue[] argValues, MethodContract contract, List<DfaMemoryState> states, MethodCallInstruction instruction, DfaValueFactory factory, Set<DfaMemoryState> finalStates) { DfaConstValue.Factory constFactory = factory.getConstFactory(); List<DfaMemoryState> falseStates = ContainerUtil.newArrayList(); for (int i = 0; i < argValues.length; i++) { DfaValue argValue = argValues[i]; MethodContract.ValueConstraint constraint = contract.arguments[i]; DfaConstValue expectedValue = constraint.getComparisonValue(factory); if (expectedValue == null) continue; boolean invertCondition = constraint.shouldUseNonEqComparison(); DfaValue condition = factory .getRelationFactory() .createRelation(argValue, expectedValue, EQEQ, invertCondition); if (condition == null) { if (!(argValue instanceof DfaConstValue)) { for (DfaMemoryState state : states) { falseStates.add(state.createCopy()); } continue; } condition = constFactory.createFromValue( (argValue == expectedValue) != invertCondition, PsiType.BOOLEAN, null); } List<DfaMemoryState> nextStates = ContainerUtil.newArrayList(); for (DfaMemoryState state : states) { boolean unknownVsNull = expectedValue == constFactory.getNull() && argValue instanceof DfaVariableValue && ((DfaMemoryStateImpl) state) .getVariableState((DfaVariableValue) argValue) .getNullability() == Nullness.UNKNOWN; DfaMemoryState falseCopy = state.createCopy(); if (state.applyCondition(condition)) { if (unknownVsNull && !invertCondition) { state.markEphemeral(); } nextStates.add(state); } if (falseCopy.applyCondition(condition.createNegated())) { if (unknownVsNull && invertCondition) { falseCopy.markEphemeral(); } falseStates.add(falseCopy); } } states = nextStates; } for (DfaMemoryState state : states) { state.push(getDfaContractReturnValue(contract, instruction, factory)); finalStates.add(state); } return falseStates; }