boolean (@Nullable PsiExpression condition, @NotNull PsiStatement context, List<? super PsiExpression> notUpdated) { if (condition == null) { return false; } if (PsiUtil.isConstantExpression(condition) || ExpressionUtils.isNullLiteral(condition)) { return true; } if (condition instanceof PsiInstanceOfExpression instanceOfExpression) { final PsiExpression operand = instanceOfExpression.getOperand(); return isConditionNotUpdated(operand, context, notUpdated); } else if (condition instanceof PsiParenthesizedExpression) { // catch stuff like "while ((x)) { ... }" final PsiExpression expression = ((PsiParenthesizedExpression)condition).getExpression(); return isConditionNotUpdated(expression, context, notUpdated); } else if (condition instanceof PsiPolyadicExpression polyadicExpression) { // while (value != x) { ... } // while (value != (x + y)) { ... } // while (b1 && b2) { ... } for (PsiExpression operand : polyadicExpression.getOperands()) { if (!isConditionNotUpdated(operand, context, notUpdated)) { return false; } } return true; } else if (condition instanceof PsiReferenceExpression referenceExpression) { final PsiElement element = referenceExpression.resolve(); if (element instanceof PsiField field) { final PsiType type = field.getType(); if (field.hasModifierProperty(PsiModifier.FINAL) && type.getArrayDimensions() == 0) { if (field.hasModifierProperty(PsiModifier.STATIC)) { return true; } final PsiExpression qualifier = referenceExpression.getQualifierExpression(); if (qualifier == null) { return true; } else if (isConditionNotUpdated(qualifier, context, notUpdated)) { return true; } } } else if (element instanceof PsiLocalVariable || element instanceof PsiParameter) { final PsiVariable variable = (PsiVariable)element; boolean isFinal = variable.hasModifierProperty(PsiModifier.FINAL); final PsiType type = variable.getType(); boolean arrayUpdated = type instanceof PsiArrayType && VariableAccessUtils.arrayContentsAreAssigned(variable, context); if ((isFinal || !VariableAccessUtils.variableIsAssigned(variable, context)) && !arrayUpdated) { if (!isFinal) { notUpdated.add(referenceExpression); } return true; } } } else if (condition instanceof PsiPrefixExpression prefixExpression) { if (!PsiUtil.isIncrementDecrementOperation(prefixExpression)) { final PsiExpression operand = prefixExpression.getOperand(); return isConditionNotUpdated(operand, context, notUpdated); } } else if (condition instanceof PsiArrayAccessExpression accessExpression) { // Actually the contents of the array could change nevertheless // if it is accessed through a different reference like this: // int[] local_ints = new int[]{1, 2}; // int[] other_ints = local_ints; // while (local_ints[0] > 0) { other_ints[0]--; } // // Keep this check? final PsiExpression indexExpression = accessExpression.getIndexExpression(); return isConditionNotUpdated(indexExpression, context, notUpdated) && isConditionNotUpdated(accessExpression.getArrayExpression(), context, notUpdated); } else if (condition instanceof PsiConditionalExpression conditionalExpression) { final PsiExpression thenExpression = conditionalExpression.getThenExpression(); final PsiExpression elseExpression = conditionalExpression.getElseExpression(); if (thenExpression == null || elseExpression == null) { return false; } return isConditionNotUpdated(conditionalExpression.getCondition(), context, notUpdated) && isConditionNotUpdated(thenExpression, context, notUpdated) && isConditionNotUpdated(elseExpression, context, notUpdated); } else if (condition instanceof PsiMethodCallExpression) { PsiExpression qualifier = ((PsiMethodCallExpression)condition).getMethodExpression().getQualifierExpression(); if (!isConditionNotUpdated(qualifier, context, notUpdated)) return false; for (PsiExpression arg : ((PsiMethodCallExpression)condition).getArgumentList().getExpressions()) { if (!isConditionNotUpdated(arg, context, notUpdated)) return false; } return true; } else if (condition instanceof PsiTypeCastExpression) { return isConditionNotUpdated(((PsiTypeCastExpression)condition).getOperand(), context, notUpdated); } else if (condition instanceof PsiThisExpression || condition instanceof PsiClassObjectAccessExpression) { return true; } return false; }