use of com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint in project intellij-community by JetBrains.
the class ContractInferenceInterpreter method visitExpression.
@NotNull
private List<PreContract> visitExpression(final List<ValueConstraint[]> states, @Nullable LighterASTNode expr) {
if (expr == null)
return emptyList();
if (states.isEmpty())
return emptyList();
// too complex
if (states.size() > 300)
return emptyList();
IElementType type = expr.getTokenType();
if (type == POLYADIC_EXPRESSION || type == BINARY_EXPRESSION) {
return visitPolyadic(states, expr);
}
if (type == CONDITIONAL_EXPRESSION) {
List<LighterASTNode> children = getExpressionChildren(myTree, expr);
if (children.size() != 3)
return emptyList();
List<PreContract> conditionResults = visitExpression(states, children.get(0));
return ContainerUtil.concat(visitExpression(antecedentsReturning(conditionResults, TRUE_VALUE), children.get(1)), visitExpression(antecedentsReturning(conditionResults, FALSE_VALUE), children.get(2)));
}
if (type == PARENTH_EXPRESSION) {
return visitExpression(states, findExpressionChild(myTree, expr));
}
if (type == TYPE_CAST_EXPRESSION) {
return visitExpression(states, findExpressionChild(myTree, expr));
}
if (isNegationExpression(expr)) {
return ContainerUtil.mapNotNull(visitExpression(states, findExpressionChild(myTree, expr)), PreContract::negate);
}
if (type == INSTANCE_OF_EXPRESSION) {
final int parameter = resolveParameter(findExpressionChild(myTree, expr));
if (parameter >= 0) {
return asPreContracts(ContainerUtil.mapNotNull(states, state -> contractWithConstraint(state, parameter, NULL_VALUE, FALSE_VALUE)));
}
}
if (type == NEW_EXPRESSION || type == THIS_EXPRESSION) {
return asPreContracts(toContracts(states, NOT_NULL_VALUE));
}
if (type == METHOD_CALL_EXPRESSION) {
return singletonList(new MethodCallContract(ExpressionRange.create(expr, myBody.getStartOffset()), ContainerUtil.map(states, Arrays::asList)));
}
final ValueConstraint constraint = getLiteralConstraint(expr);
if (constraint != null) {
return asPreContracts(toContracts(states, constraint));
}
int paramIndex = resolveParameter(expr);
if (paramIndex >= 0) {
List<MethodContract> result = ContainerUtil.newArrayList();
for (ValueConstraint[] state : states) {
if (state[paramIndex] != ANY_VALUE) {
// the second 'o' reference in cases like: if (o != null) return o;
result.add(new MethodContract(state, state[paramIndex]));
} else if (JavaTokenType.BOOLEAN_KEYWORD == getPrimitiveParameterType(paramIndex)) {
// if (boolValue) ...
ContainerUtil.addIfNotNull(result, contractWithConstraint(state, paramIndex, TRUE_VALUE, TRUE_VALUE));
ContainerUtil.addIfNotNull(result, contractWithConstraint(state, paramIndex, FALSE_VALUE, FALSE_VALUE));
}
}
return asPreContracts(result);
}
return emptyList();
}
use of com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint in project intellij-community by JetBrains.
the class ContractInferenceInterpreter method visitEqualityComparison.
private List<MethodContract> visitEqualityComparison(List<ValueConstraint[]> states, LighterASTNode op1, LighterASTNode op2, boolean equality) {
int parameter = resolveParameter(op1);
ValueConstraint constraint = getLiteralConstraint(op2);
if (parameter < 0 || constraint == null) {
parameter = resolveParameter(op2);
constraint = getLiteralConstraint(op1);
}
if (parameter >= 0 && constraint != null) {
List<MethodContract> result = ContainerUtil.newArrayList();
for (ValueConstraint[] state : states) {
if (constraint == NOT_NULL_VALUE) {
if (getPrimitiveParameterType(parameter) == null) {
ContainerUtil.addIfNotNull(result, contractWithConstraint(state, parameter, NULL_VALUE, equality ? FALSE_VALUE : TRUE_VALUE));
}
} else {
ContainerUtil.addIfNotNull(result, contractWithConstraint(state, parameter, constraint, equality ? TRUE_VALUE : FALSE_VALUE));
ContainerUtil.addIfNotNull(result, contractWithConstraint(state, parameter, negateConstraint(constraint), equality ? FALSE_VALUE : TRUE_VALUE));
}
}
return result;
}
return emptyList();
}
use of com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint in project intellij-community by JetBrains.
the class ContractInferenceInterpreter method withConstraint.
@Nullable
static ValueConstraint[] withConstraint(ValueConstraint[] constraints, int index, ValueConstraint constraint) {
if (constraints[index] == constraint)
return constraints;
ValueConstraint negated = negateConstraint(constraint);
if (negated != constraint && constraints[index] == negated) {
return null;
}
ValueConstraint[] copy = constraints.clone();
copy[index] = constraint;
return copy;
}
use of com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint in project intellij-community by JetBrains.
the class ContractInferenceInterpreter method visitLogicalOperation.
private List<MethodContract> visitLogicalOperation(List<LighterASTNode> operands, boolean conjunction, List<ValueConstraint[]> states) {
ValueConstraint breakValue = conjunction ? FALSE_VALUE : TRUE_VALUE;
List<MethodContract> finalStates = ContainerUtil.newArrayList();
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));
}
finalStates.addAll(toContracts(states, negateConstraint(breakValue)));
return finalStates;
}
Aggregations