public static boolean isAssociativeOperation(PsiPolyadicExpression expression) {
   final IElementType tokenType = expression.getOperationTokenType();
   final PsiType type = expression.getType();
   final PsiPrimitiveType primitiveType;
   if (type instanceof PsiClassType) {
     primitiveType = PsiPrimitiveType.getUnboxedType(type);
     if (primitiveType == null) {
       return false;
     }
   } else if (type instanceof PsiPrimitiveType) {
     primitiveType = (PsiPrimitiveType) type;
   } else {
     return false;
   }
   if (JavaTokenType.PLUS == tokenType || JavaTokenType.ASTERISK == tokenType) {
     return !PsiType.FLOAT.equals(primitiveType) && !PsiType.DOUBLE.equals(primitiveType);
   } else if (JavaTokenType.EQEQ == tokenType || JavaTokenType.NE == tokenType) {
     return PsiType.BOOLEAN.equals(primitiveType);
   } else if (JavaTokenType.AND == tokenType
       || JavaTokenType.OR == tokenType
       || JavaTokenType.XOR == tokenType) {
     return true;
   } else if (JavaTokenType.OROR == tokenType || JavaTokenType.ANDAND == tokenType) {
     return true;
   }
   return false;
 }
  @Override
  public boolean satisfiedBy(PsiElement element) {
    final PsiJavaToken token;
    if (element instanceof PsiJavaToken) {
      token = (PsiJavaToken) element;
    } else {
      final PsiElement prevSibling = element.getPrevSibling();
      if (prevSibling instanceof PsiJavaToken) {
        token = (PsiJavaToken) prevSibling;
      } else {
        return false;
      }
    }

    final PsiElement parent = element.getParent();
    if (!(parent instanceof PsiPolyadicExpression)) {
      return false;
    }
    final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression) parent;
    final PsiType type = polyadicExpression.getType();
    if (type == null || type.equalsToText("java.lang.String")) {
      // handled by JoinConcatenatedStringLiteralsIntention
      return false;
    }
    final PsiPolyadicExpression subexpression = getSubexpression(polyadicExpression, token);
    if (subexpression == null) {
      return false;
    }
    if (!isPartOfLargerExpression(polyadicExpression)) {
      // handled by ConstantExpressionIntention
      return false;
    }
    if (!PsiUtil.isConstantExpression(subexpression)) {
      return false;
    }
    final Object value = ExpressionUtils.computeConstantExpression(subexpression);
    return value != null;
  }
 private static boolean isInConcatenationContext(PsiElement element) {
   final PsiElement parent = element.getParent();
   if (parent instanceof PsiPolyadicExpression) {
     final PsiPolyadicExpression parentExpression = (PsiPolyadicExpression) parent;
     final PsiType parentType = parentExpression.getType();
     if (parentType == null) {
       return false;
     }
     final String parentTypeText = parentType.getCanonicalText();
     return JAVA_LANG_STRING.equals(parentTypeText);
   } else if (parent instanceof PsiAssignmentExpression) {
     final PsiAssignmentExpression parentExpression = (PsiAssignmentExpression) parent;
     final IElementType tokenType = parentExpression.getOperationTokenType();
     if (!JavaTokenType.PLUSEQ.equals(tokenType)) {
       return false;
     }
     final PsiType parentType = parentExpression.getType();
     if (parentType == null) {
       return false;
     }
     final String parentTypeText = parentType.getCanonicalText();
     return JAVA_LANG_STRING.equals(parentTypeText);
   } else if (parent instanceof PsiExpressionList) {
     final PsiElement grandParent = parent.getParent();
     if (!(grandParent instanceof PsiMethodCallExpression)) {
       return false;
     }
     final PsiMethodCallExpression methodCall = (PsiMethodCallExpression) grandParent;
     final PsiReferenceExpression methodExpression = methodCall.getMethodExpression();
     final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
     final PsiType type;
     if (qualifierExpression == null) {
       // to use the intention inside the source of
       // String and StringBuffer
       type = methodExpression.getType();
     } else {
       type = qualifierExpression.getType();
     }
     if (type == null) {
       return false;
     }
     final String className = type.getCanonicalText();
     if (CommonClassNames.JAVA_LANG_STRING_BUFFER.equals(className)
         || CommonClassNames.JAVA_LANG_STRING_BUILDER.equals(className)) {
       @NonNls final String methodName = methodExpression.getReferenceName();
       if (!"append".equals(methodName) && !"insert".equals(methodName)) {
         return false;
       }
       final PsiElement method = methodExpression.resolve();
       return method != null;
     } else if (JAVA_LANG_STRING.equals(className)) {
       @NonNls final String methodName = methodExpression.getReferenceName();
       if (!"indexOf".equals(methodName)
           && !"lastIndexOf".equals(methodName)
           && !"replace".equals(methodName)) {
         return false;
       }
       final PsiElement method = methodExpression.resolve();
       return method != null;
     }
   }
   return false;
 }
 public static boolean areParenthesesNeeded(
     PsiExpression expression,
     PsiExpression parentExpression,
     boolean ignoreClarifyingParentheses) {
   if (parentExpression instanceof PsiParenthesizedExpression
       || parentExpression instanceof PsiArrayInitializerExpression) {
     return false;
   }
   final int parentPrecedence = getPrecedence(parentExpression);
   final int childPrecedence = getPrecedence(expression);
   if (parentPrecedence > childPrecedence) {
     if (ignoreClarifyingParentheses) {
       if (expression instanceof PsiPolyadicExpression) {
         if (parentExpression instanceof PsiPolyadicExpression
             || parentExpression instanceof PsiConditionalExpression
             || parentExpression instanceof PsiInstanceOfExpression) {
           return true;
         }
       } else if (expression instanceof PsiInstanceOfExpression) {
         return true;
       }
     }
     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)
         && !PsiTreeUtil.isAncestor(
             parentPolyadicExpression.getOperands()[0], childPolyadicExpression, true)) {
       final PsiExpression[] operands = childPolyadicExpression.getOperands();
       for (PsiExpression operand : operands) {
         if (!childType.equals(operand.getType())) {
           return true;
         }
       }
     } else if (childType.equals(PsiType.BOOLEAN)) {
       final PsiExpression[] operands = childPolyadicExpression.getOperands();
       for (PsiExpression operand : operands) {
         if (!PsiType.BOOLEAN.equals(operand.getType())) {
           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);
   }
   return parentPrecedence < childPrecedence;
 }
 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);
     }
   }
 }