public static boolean areParenthesesNeeded(
     PsiParenthesizedExpression expression, boolean ignoreClarifyingParentheses) {
   final PsiElement parent = expression.getParent();
   if (!(parent instanceof PsiExpression)) {
     return false;
   }
   final PsiExpression child = expression.getExpression();
   if (child == null) {
     return true;
   }
   if (parent instanceof PsiArrayAccessExpression) {
     final PsiArrayAccessExpression arrayAccessExpression = (PsiArrayAccessExpression) parent;
     final PsiExpression indexExpression = arrayAccessExpression.getIndexExpression();
     if (expression == indexExpression) {
       return false;
     }
   }
   return areParenthesesNeeded(child, (PsiExpression) parent, ignoreClarifyingParentheses);
 }
 private static void removeParensFromParenthesizedExpression(
     @NotNull PsiParenthesizedExpression parenthesizedExpression,
     boolean ignoreClarifyingParentheses) {
   final PsiExpression body = parenthesizedExpression.getExpression();
   if (body == null) {
     parenthesizedExpression.delete();
     return;
   }
   final PsiElement parent = parenthesizedExpression.getParent();
   if (!(parent instanceof PsiExpression)
       || parent instanceof PsiParenthesizedExpression
       || parent instanceof PsiArrayInitializerExpression) {
     final PsiExpression newExpression = (PsiExpression) parenthesizedExpression.replace(body);
     removeParentheses(newExpression, ignoreClarifyingParentheses);
     return;
   } else if (parent instanceof PsiArrayAccessExpression) {
     final PsiArrayAccessExpression arrayAccessExpression = (PsiArrayAccessExpression) parent;
     if (parenthesizedExpression == arrayAccessExpression.getIndexExpression()) {
       // use addAfter() + delete() instead of replace() to
       // workaround automatic insertion of parentheses by psi
       final PsiExpression newExpression =
           (PsiExpression) parent.addAfter(body, parenthesizedExpression);
       parenthesizedExpression.delete();
       removeParentheses(newExpression, ignoreClarifyingParentheses);
       return;
     }
   }
   final PsiExpression parentExpression = (PsiExpression) parent;
   final int parentPrecedence = getPrecedence(parentExpression);
   final int childPrecedence = getPrecedence(body);
   if (parentPrecedence < childPrecedence) {
     final PsiElement bodyParent = body.getParent();
     final PsiParenthesizedExpression newParenthesizedExpression =
         (PsiParenthesizedExpression) parenthesizedExpression.replace(bodyParent);
     final PsiExpression expression = newParenthesizedExpression.getExpression();
     if (expression != null) {
       removeParentheses(expression, ignoreClarifyingParentheses);
     }
   } else if (parentPrecedence == childPrecedence) {
     if (parentExpression instanceof PsiPolyadicExpression
         && body instanceof PsiPolyadicExpression) {
       final PsiPolyadicExpression parentPolyadicExpression =
           (PsiPolyadicExpression) parentExpression;
       final IElementType parentOperator = parentPolyadicExpression.getOperationTokenType();
       final PsiPolyadicExpression bodyPolyadicExpression = (PsiPolyadicExpression) body;
       final IElementType bodyOperator = bodyPolyadicExpression.getOperationTokenType();
       final PsiType parentType = parentPolyadicExpression.getType();
       final PsiType bodyType = body.getType();
       if (parentType != null
           && parentType.equals(bodyType)
           && parentOperator.equals(bodyOperator)) {
         final PsiExpression[] parentOperands = parentPolyadicExpression.getOperands();
         if (PsiTreeUtil.isAncestor(parentOperands[0], body, true)
             || isCommutativeOperator(bodyOperator)) {
           // use addAfter() + delete() instead of replace() to
           // workaround automatic insertion of parentheses by psi
           final PsiExpression newExpression =
               (PsiExpression) parent.addAfter(body, parenthesizedExpression);
           parenthesizedExpression.delete();
           removeParentheses(newExpression, ignoreClarifyingParentheses);
           return;
         }
       }
       if (ignoreClarifyingParentheses) {
         if (parentOperator.equals(bodyOperator)) {
           removeParentheses(body, ignoreClarifyingParentheses);
         }
       } else {
         final PsiExpression newExpression = (PsiExpression) parenthesizedExpression.replace(body);
         removeParentheses(newExpression, ignoreClarifyingParentheses);
       }
     } else {
       final PsiExpression newExpression = (PsiExpression) parenthesizedExpression.replace(body);
       removeParentheses(newExpression, ignoreClarifyingParentheses);
     }
   } else {
     if (ignoreClarifyingParentheses
         && parent instanceof PsiPolyadicExpression
         && (body instanceof PsiPolyadicExpression || body instanceof PsiInstanceOfExpression)) {
       removeParentheses(body, ignoreClarifyingParentheses);
     } else {
       final PsiExpression newExpression = (PsiExpression) parenthesizedExpression.replace(body);
       removeParentheses(newExpression, ignoreClarifyingParentheses);
     }
   }
 }