CauseItem[] (@NotNull PsiExpression expression, @NotNull MemoryStateChange history, boolean value) { if (BoolUtils.isNegation(expression)) { PsiExpression negated = BoolUtils.getNegated(expression); if (negated != null) { MemoryStateChange negatedPush = history.findExpressionPush(negated); if (negatedPush != null) { CauseItem cause = new CauseItem( JavaAnalysisBundle.message("dfa.find.cause.value.x.is.always.the.same", negated.getText(), !value), negated); cause.addChildren(findConstantValueCause(negated, negatedPush, !value)); return new CauseItem[]{cause}; } } } if (expression instanceof PsiPolyadicExpression) { IElementType tokenType = ((PsiPolyadicExpression)expression).getOperationTokenType(); boolean and = tokenType.equals(JavaTokenType.ANDAND); if (and || tokenType.equals(JavaTokenType.OROR)) { if (value != and) { MemoryStateChange push = history; if (history.myInstruction instanceof ResultOfInstruction) { MemoryStateChange previous = history.getPrevious(); if (previous != null) { previous = previous.getNonMerge(); } if (previous != null && previous.myInstruction instanceof GotoInstruction) { previous = previous.getPrevious(); } if (previous != null) { push = previous; } } if (push.myInstruction instanceof PushValueInstruction pushValueInstruction && pushValueInstruction.getValue().isConst(value) && pushValueInstruction.getDfaAnchor() instanceof JavaExpressionAnchor anchor && anchor.getExpression() == expression) { push = push.getPrevious(); } if (push != null) { push = push.getNonMerge(); } if (push != null && push.myInstruction instanceof ConditionalGotoInstruction) { push = push.getPrevious(); } if (push != null && push.myInstruction instanceof ExpressionPushingInstruction instruction && instruction.getDfaAnchor() instanceof JavaExpressionAnchor anchor) { PsiExpression operand = anchor.getExpression(); if (expression.equals(PsiUtil.skipParenthesizedExprUp(operand.getParent()))) { int i = IntStreamEx.ofIndices(((PsiPolyadicExpression)expression).getOperands(), e -> PsiTreeUtil.isAncestor(e, operand, false)) .findFirst().orElse(-1); if (i >= 0) { CauseItem cause = new CauseItem( JavaAnalysisBundle.message("dfa.find.cause.operand.of.boolean.expression.is.the.same", i + 1, and ? 0 : 1, value), operand); cause.addChildren(findConstantValueCause(operand, push, value)); return new CauseItem[]{cause}; } } } return new CauseItem[0]; } PsiExpression[] operands = ((PsiPolyadicExpression)expression).getOperands(); List<CauseItem> operandCauses = new ArrayList<>(); for (int i = 0; i < operands.length; i++) { PsiExpression operand = operands[i]; operand = PsiUtil.skipParenthesizedExprDown(operand); MemoryStateChange push = history.findExpressionPush(operand); if (push != null && ((push.myInstruction instanceof ConditionalGotoInstruction gotoInstruction && gotoInstruction.isTarget(DfTypes.booleanValue(value), history.myInstruction)) || push.myTopOfStack.getDfType().isConst(value))) { int andVal = and ? 1 : 0; CauseItem cause = new CauseItem( JavaAnalysisBundle.message("dfa.find.cause.operand.of.boolean.expression.is.the.same", i + 1, andVal == 1 ? 0 : 1, value), operand); cause.addChildren(findBooleanResultCauses(operand, push, value)); operandCauses.add(cause); } } if (operandCauses.size() == operands.length) { return operandCauses.toArray(new CauseItem[0]); } } } if (expression instanceof PsiBinaryExpression binOp) { RelationType relationType = DfaPsiUtil.getRelationByToken(binOp.getOperationTokenType()); if (relationType != null) { if (!value) { relationType = relationType.getNegated(); } PsiExpression leftOperand = PsiUtil.skipParenthesizedExprDown(binOp.getLOperand()); PsiExpression rightOperand = PsiUtil.skipParenthesizedExprDown(binOp.getROperand()); MemoryStateChange leftChange = history.findExpressionPush(leftOperand); MemoryStateChange rightChange = history.findExpressionPush(rightOperand); if (leftChange != null && rightChange != null) { DfaValue leftValue = leftChange.myTopOfStack; DfaValue rightValue = rightChange.myTopOfStack; CauseItem[] causes = findRelationCause(relationType, leftChange, rightChange); if (causes.length > 0) { return causes; } if (leftValue == rightValue && (leftValue instanceof DfaVariableValue || leftValue.getDfType() instanceof DfConstantType)) { List<CauseItem> constCauses = new ArrayList<>(); CauseItem leftCause = constantInitializerCause(leftValue, leftChange.getExpression()); CauseItem rightCause = constantInitializerCause(rightValue, rightChange.getExpression()); ContainerUtil.addAllNotNull(constCauses, leftCause, rightCause); if (constCauses.isEmpty()) { return new CauseItem[]{ new CauseItem(JavaAnalysisBundle.message("dfa.find.cause.comparison.arguments.are.the.same"), binOp.getOperationSign())}; } return constCauses.toArray(new CauseItem[0]); } if (leftValue != rightValue && relationType.isInequality() && leftValue.getDfType() instanceof DfConstantType && rightValue.getDfType() instanceof DfConstantType) { CauseItem causeItem = new CauseItem(JavaAnalysisBundle.message("dfa.find.cause.comparison.arguments.are.different.constants"), binOp.getOperationSign()); causeItem.addChildren(constantInitializerCause(leftValue, leftChange.getExpression()), constantInitializerCause(rightValue, rightChange.getExpression())); return new CauseItem[]{causeItem}; } } } } if (expression instanceof PsiInstanceOfExpression instanceOfExpression) { PsiExpression operand = instanceOfExpression.getOperand(); MemoryStateChange operandHistory = history.findExpressionPush(operand); if (operandHistory != null) { DfaValue operandValue = operandHistory.myTopOfStack; if (!value) { FactDefinition<DfaNullability> nullability = operandHistory.findFact(operandValue, FactExtractor.nullability()); if (nullability.myFact == DfaNullability.NULL) { CauseItem causeItem = new CauseItem( JavaAnalysisBundle.message("dfa.find.cause.value.x.is.always.the.same", operand.getText(), "null"), operand); causeItem.addChildren(findConstantValueCause(operand, operandHistory, null)); return new CauseItem[]{causeItem}; } } PsiTypeElement typeElement = instanceOfExpression.getCheckType(); if (typeElement != null) { PsiType type = typeElement.getType(); CauseItem causeItem = findTypeCause(operandHistory, type, value); if (causeItem != null) return new CauseItem[]{causeItem}; } } } if (expression instanceof PsiMethodCallExpression) { return new CauseItem[]{fromCallContract(history, (PsiMethodCallExpression)expression, ContractReturnValue.returnBoolean(value))}; } return new CauseItem[0]; }