Search in sources :

Example 1 with ValueConstraint

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();
}
Also used : Arrays(java.util.Arrays) JavaTokenType(com.intellij.psi.JavaTokenType) IElementType(com.intellij.psi.tree.IElementType) Collections.emptyList(java.util.Collections.emptyList) JavaElementType(com.intellij.psi.impl.source.tree.JavaElementType) ContainerUtil(com.intellij.util.containers.ContainerUtil) JavaLightTreeUtil(com.intellij.psi.impl.source.JavaLightTreeUtil) JavaLightTreeUtil.getExpressionChildren(com.intellij.psi.impl.source.JavaLightTreeUtil.getExpressionChildren) ArrayList(java.util.ArrayList) Collections.singletonList(java.util.Collections.singletonList) Nullable(org.jetbrains.annotations.Nullable) List(java.util.List) ElementType(com.intellij.psi.impl.source.tree.ElementType) JavaLightTreeUtil.findExpressionChild(com.intellij.psi.impl.source.JavaLightTreeUtil.findExpressionChild) ValueConstraint(com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint) LightTreeUtil.firstChildOfType(com.intellij.psi.impl.source.tree.LightTreeUtil.firstChildOfType) LighterAST(com.intellij.lang.LighterAST) LighterASTNode(com.intellij.lang.LighterASTNode) LightTreeUtil.getChildrenOfType(com.intellij.psi.impl.source.tree.LightTreeUtil.getChildrenOfType) NotNull(org.jetbrains.annotations.NotNull) LighterASTNode(com.intellij.lang.LighterASTNode) ValueConstraint(com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint) ValueConstraint(com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint) IElementType(com.intellij.psi.tree.IElementType) Arrays(java.util.Arrays) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with ValueConstraint

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();
}
Also used : ValueConstraint(com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint) ValueConstraint(com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint)

Example 3 with ValueConstraint

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;
}
Also used : ValueConstraint(com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint) Nullable(org.jetbrains.annotations.Nullable)

Example 4 with ValueConstraint

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;
}
Also used : Arrays(java.util.Arrays) JavaTokenType(com.intellij.psi.JavaTokenType) IElementType(com.intellij.psi.tree.IElementType) Collections.emptyList(java.util.Collections.emptyList) JavaElementType(com.intellij.psi.impl.source.tree.JavaElementType) ContainerUtil(com.intellij.util.containers.ContainerUtil) JavaLightTreeUtil(com.intellij.psi.impl.source.JavaLightTreeUtil) JavaLightTreeUtil.getExpressionChildren(com.intellij.psi.impl.source.JavaLightTreeUtil.getExpressionChildren) ArrayList(java.util.ArrayList) Collections.singletonList(java.util.Collections.singletonList) Nullable(org.jetbrains.annotations.Nullable) List(java.util.List) ElementType(com.intellij.psi.impl.source.tree.ElementType) JavaLightTreeUtil.findExpressionChild(com.intellij.psi.impl.source.JavaLightTreeUtil.findExpressionChild) ValueConstraint(com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint) LightTreeUtil.firstChildOfType(com.intellij.psi.impl.source.tree.LightTreeUtil.firstChildOfType) LighterAST(com.intellij.lang.LighterAST) LighterASTNode(com.intellij.lang.LighterASTNode) LightTreeUtil.getChildrenOfType(com.intellij.psi.impl.source.tree.LightTreeUtil.getChildrenOfType) NotNull(org.jetbrains.annotations.NotNull) LighterASTNode(com.intellij.lang.LighterASTNode) ValueConstraint(com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint)

Aggregations

ValueConstraint (com.intellij.codeInspection.dataFlow.MethodContract.ValueConstraint)4 Nullable (org.jetbrains.annotations.Nullable)3 LighterAST (com.intellij.lang.LighterAST)2 LighterASTNode (com.intellij.lang.LighterASTNode)2 JavaTokenType (com.intellij.psi.JavaTokenType)2 JavaLightTreeUtil (com.intellij.psi.impl.source.JavaLightTreeUtil)2 JavaLightTreeUtil.findExpressionChild (com.intellij.psi.impl.source.JavaLightTreeUtil.findExpressionChild)2 JavaLightTreeUtil.getExpressionChildren (com.intellij.psi.impl.source.JavaLightTreeUtil.getExpressionChildren)2 ElementType (com.intellij.psi.impl.source.tree.ElementType)2 JavaElementType (com.intellij.psi.impl.source.tree.JavaElementType)2 LightTreeUtil.firstChildOfType (com.intellij.psi.impl.source.tree.LightTreeUtil.firstChildOfType)2 LightTreeUtil.getChildrenOfType (com.intellij.psi.impl.source.tree.LightTreeUtil.getChildrenOfType)2 IElementType (com.intellij.psi.tree.IElementType)2 ContainerUtil (com.intellij.util.containers.ContainerUtil)2 ArrayList (java.util.ArrayList)2 Arrays (java.util.Arrays)2 Collections.emptyList (java.util.Collections.emptyList)2 Collections.singletonList (java.util.Collections.singletonList)2 List (java.util.List)2 NotNull (org.jetbrains.annotations.NotNull)2