public static boolean areParenthesesNeeded(PsiExpression expression,
                                             PsiExpression parentExpression,
                                             boolean ignoreClarifyingParentheses) {
    if (parentExpression instanceof PsiParenthesizedExpression || parentExpression instanceof PsiArrayInitializerExpression) {
      return false;
    }
    if (parentExpression instanceof PsiArrayAccessExpression) {
      final PsiArrayAccessExpression arrayAccessExpression = (PsiArrayAccessExpression)parentExpression;
      return PsiTreeUtil.isAncestor(arrayAccessExpression.getArrayExpression(), expression, false);
    }
    final int parentPrecedence = getPrecedence(parentExpression);
    final int childPrecedence = getPrecedence(expression);
    if (parentPrecedence > childPrecedence) {
      if (ignoreClarifyingParentheses) {
        if (expression instanceof PsiPolyadicExpression) {
          return parentExpression instanceof PsiPolyadicExpression ||
                 parentExpression instanceof PsiConditionalExpression ||
                 parentExpression instanceof PsiInstanceOfExpression;
        }
        else return expression instanceof PsiInstanceOfExpression;
      }
      return false;
    }
    if (parentExpression instanceof PsiPolyadicExpression && expression instanceof PsiPolyadicExpression) {
      final PsiPolyadicExpression parentPolyadicExpression = (PsiPolyadicExpression)parentExpression;
      final PsiType parentType = parentPolyadicExpression.getType();
      if (parentType == null) {
        return true;
      }
      final PsiPolyadicExpression childPolyadicExpression = (PsiPolyadicExpression)expression;
      final PsiType childType = childPolyadicExpression.getType();
      if (!parentType.equals(childType)) {
        return true;
      }
      if (childType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
        return areStringParenthesesNeeded(childPolyadicExpression, parentPolyadicExpression, null);
      }
      else if (childType.equals(PsiTypes.booleanType())) {
        final PsiExpression[] operands = childPolyadicExpression.getOperands();
        for (PsiExpression operand : operands) {
          PsiType operandType = operand.getType();
          if (operandType != null && !PsiTypes.booleanType().equals(operandType)) {
            return true;
          }
        }
      }
      final IElementType parentOperator = parentPolyadicExpression.getOperationTokenType();
      final IElementType childOperator = childPolyadicExpression.getOperationTokenType();
      if (ignoreClarifyingParentheses) {
        if (!childOperator.equals(parentOperator)) {
          return true;
        }
      }
      final PsiExpression[] parentOperands = parentPolyadicExpression.getOperands();
      if (!PsiTreeUtil.isAncestor(parentOperands[0], expression, false)) {
        if (!isAssociativeOperation(parentPolyadicExpression) ||
            JavaTokenType.DIV == childOperator || JavaTokenType.PERC == childOperator) {
          return true;
        }
      }
    }
    else if (parentExpression instanceof PsiConditionalExpression && expression instanceof PsiConditionalExpression) {
      final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)parentExpression;
      final PsiExpression condition = conditionalExpression.getCondition();
      return PsiTreeUtil.isAncestor(condition, expression, true) || ignoreClarifyingParentheses;
    }
    else if (expression instanceof PsiLambdaExpression) { // jls-15.16
      if (parentExpression instanceof PsiTypeCastExpression) {
        return false;
      }
      else if (parentExpression instanceof PsiConditionalExpression) { // jls-15.25
        final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)parentExpression;
        return PsiTreeUtil.isAncestor(conditionalExpression.getCondition(), expression, true);
      }
    }
    return parentPrecedence < childPrecedence;
  }
public static boolean areParenthesesNeeded(PsiExpression expression,
                                             PsiExpression parentExpression,
                                             boolean ignoreClarifyingParentheses)