ContractInferenceInterpreter#negateConstraint -> ValueConstraint#negate, used in BytecodeAnalysisConverter. Test01.java: checkTrueFail (IDEA-CR-21320)

This commit is contained in:
Tagir Valeev
2017-05-25 11:02:12 +07:00
parent c0d7e7a5f3
commit 68dd38bbca
5 changed files with 30 additions and 28 deletions

View File

@@ -420,16 +420,9 @@ public class BytecodeAnalysisConverter {
for (int i = 0; i < c1.arguments.length; i++) {
ValueConstraint left = c1.arguments[i];
ValueConstraint right = c2.arguments[i];
if(left == ValueConstraint.ANY_VALUE && right == ValueConstraint.ANY_VALUE) continue;
if(idx >= 0) return null;
if(left == ValueConstraint.NOT_NULL_VALUE && right == ValueConstraint.NULL_VALUE ||
left == ValueConstraint.NULL_VALUE && right == ValueConstraint.NOT_NULL_VALUE ||
left == ValueConstraint.TRUE_VALUE && right == ValueConstraint.FALSE_VALUE ||
left == ValueConstraint.FALSE_VALUE && right == ValueConstraint.TRUE_VALUE) {
idx = i;
} else {
return null;
}
if (left == ValueConstraint.ANY_VALUE && right == ValueConstraint.ANY_VALUE) continue;
if (idx >= 0 || left == right || left != right.negate()) return null;
idx = i;
}
return c1;
}).nonNull().findFirst().orElse(null);

View File

@@ -237,7 +237,7 @@ class ContractInferenceInterpreter {
}
} else {
ContainerUtil.addIfNotNull(result, contractWithConstraint(state, parameter, constraint, equality ? TRUE_VALUE : FALSE_VALUE));
ContainerUtil.addIfNotNull(result, contractWithConstraint(state, parameter, negateConstraint(constraint),
ContainerUtil.addIfNotNull(result, contractWithConstraint(state, parameter, constraint.negate(),
equality ? FALSE_VALUE : TRUE_VALUE));
}
}
@@ -263,9 +263,9 @@ class ContractInferenceInterpreter {
for (LighterASTNode operand : operands) {
List<PreContract> opResults = visitExpression(states, operand);
finalStates.addAll(ContainerUtil.filter(knownContracts(opResults), contract -> contract.returnValue == breakValue));
states = antecedentsReturning(opResults, negateConstraint(breakValue));
states = antecedentsReturning(opResults, breakValue.negate());
}
finalStates.addAll(toContracts(states, negateConstraint(breakValue)));
finalStates.addAll(toContracts(states, breakValue.negate()));
return finalStates;
}
@@ -368,17 +368,6 @@ class ContractInferenceInterpreter {
return NOT_NULL_VALUE;
}
static ValueConstraint negateConstraint(@NotNull ValueConstraint constraint) {
//noinspection EnumSwitchStatementWhichMissesCases
switch (constraint) {
case NULL_VALUE: return NOT_NULL_VALUE;
case NOT_NULL_VALUE: return NULL_VALUE;
case TRUE_VALUE: return FALSE_VALUE;
case FALSE_VALUE: return TRUE_VALUE;
}
return constraint;
}
private int resolveParameter(@Nullable LighterASTNode expr) {
if (expr != null && expr.getTokenType() == REFERENCE_EXPRESSION && findExpressionChild(myTree, expr) == null) {
String name = JavaLightTreeUtil.getNameIdentifierText(myTree, expr);
@@ -398,7 +387,7 @@ class ContractInferenceInterpreter {
static ValueConstraint[] withConstraint(ValueConstraint[] constraints, int index, ValueConstraint constraint) {
if (constraints[index] == constraint) return constraints;
ValueConstraint negated = negateConstraint(constraint);
ValueConstraint negated = constraint.negate();
if (negated != constraint && constraints[index] == negated) {
return null;
}

View File

@@ -159,6 +159,19 @@ public abstract class MethodContract {
return ContractValue.condition(left, RelationType.equivalence(!shouldUseNonEqComparison()), ContractValue.argument(argumentIndex));
}
/**
* @return negated constraint or this if the constraint cannot be negated
*/
public ValueConstraint negate() {
switch (this) {
case NULL_VALUE: return NOT_NULL_VALUE;
case NOT_NULL_VALUE: return NULL_VALUE;
case TRUE_VALUE: return FALSE_VALUE;
case FALSE_VALUE: return TRUE_VALUE;
default: return this;
}
}
@Override
public String toString() {
return myPresentableName;

View File

@@ -16,7 +16,6 @@
package com.intellij.codeInspection.dataFlow
import com.intellij.codeInsight.NullableNotNullManager
import com.intellij.codeInspection.dataFlow.ContractInferenceInterpreter.negateConstraint
import com.intellij.codeInspection.dataFlow.ContractInferenceInterpreter.withConstraint
import com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint.*
import com.intellij.codeInspection.dataFlow.instructions.MethodCallInstruction
@@ -84,7 +83,8 @@ internal data class DelegationContract(internal val expression: ExpressionRange,
}
}
}
val returnValue = if (negated) negateConstraint(targetContract.returnValue) else targetContract.returnValue
val returnValue = if (negated) targetContract.returnValue.negate()
else targetContract.returnValue
return answer?.let { StandardMethodContract(it, returnValue) }
}
@@ -123,7 +123,7 @@ internal data class NegatingContract(internal val negated: PreContract) : PreCon
private fun negateContract(c: StandardMethodContract): StandardMethodContract? {
val ret = c.returnValue
return if (ret == TRUE_VALUE || ret == FALSE_VALUE) StandardMethodContract(c.arguments, negateConstraint(ret)) else null
return if (ret == TRUE_VALUE || ret == FALSE_VALUE) StandardMethodContract(c.arguments, ret.negate()) else null
}
@Suppress("EqualsOrHashCode")