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;
 }
 private static boolean polyadicExpressionsAreEquivalent(
     @NotNull PsiPolyadicExpression polyadicExpression1,
     @NotNull PsiPolyadicExpression polyadicExpression2) {
   final IElementType tokenType1 = polyadicExpression1.getOperationTokenType();
   final IElementType tokenType2 = polyadicExpression2.getOperationTokenType();
   if (!tokenType1.equals(tokenType2)) {
     return false;
   }
   final PsiExpression[] operands1 = polyadicExpression1.getOperands();
   final PsiExpression[] operands2 = polyadicExpression2.getOperands();
   if (operands1.length != operands2.length) {
     return false;
   }
   for (int i = 0, length = operands1.length; i < length; i++) {
     if (!expressionsAreEquivalent(operands1[i], operands2[i])) {
       return false;
     }
   }
   return true;
 }
 public static boolean areParenthesesNeeded(PsiJavaToken sign, PsiExpression rhs) {
   if (rhs instanceof PsiPolyadicExpression) {
     final PsiPolyadicExpression binaryExpression = (PsiPolyadicExpression) rhs;
     final int precedence1 = getPrecedenceForOperator(binaryExpression.getOperationTokenType());
     final IElementType signTokenType = sign.getTokenType();
     final IElementType newOperatorToken = tokenMap.get(signTokenType);
     final int precedence2 = getPrecedenceForOperator(newOperatorToken);
     return precedence1 >= precedence2 || !isCommutativeOperator(newOperatorToken);
   } else {
     return rhs instanceof PsiConditionalExpression;
   }
 }
 @Nullable
 private String evaluate(PsiExpression expression, Map<String, Computable<String>> arguments) {
   if (expression instanceof PsiPolyadicExpression) {
     PsiPolyadicExpression binaryExpression = (PsiPolyadicExpression) expression;
     if (binaryExpression.getOperationTokenType() == JavaTokenType.PLUS) {
       String r = "";
       for (PsiExpression op : binaryExpression.getOperands()) {
         String lhs = evaluate(op, arguments);
         if (lhs == null) return null;
         r += lhs;
       }
       return r;
     }
   } else if (expression instanceof PsiLiteralExpression) {
     final Object value = ((PsiLiteralExpression) expression).getValue();
     if (value instanceof String) {
       return (String) value;
     }
   } else if (expression instanceof PsiReferenceExpression) {
     final PsiElement result = ((PsiReferenceExpression) expression).resolve();
     if (result instanceof PsiParameter) {
       final String name = ((PsiParameter) result).getName();
       final Computable<String> arg = arguments.get(name);
       return arg == null ? null : arg.compute();
     }
     if (result instanceof PsiVariable) {
       final PsiExpression initializer = ((PsiVariable) result).getInitializer();
       if (initializer != null) {
         return evaluate(initializer, arguments);
       }
     }
   } else if (expression instanceof PsiMethodCallExpression) {
     final PsiMethodCallExpression methodCall = (PsiMethodCallExpression) expression;
     final String callText = methodCall.getMethodExpression().getText();
     if (callText.equals("getTestName")) {
       final PsiExpression[] psiExpressions = methodCall.getArgumentList().getExpressions();
       if (psiExpressions.length == 1) {
         if ("true".equals(psiExpressions[0].getText()) && !StringUtil.isEmpty(myTestName)) {
           return UsefulTestCase.lowercaseFirstLetter(myTestName, true);
         }
         return myTestName;
       }
     }
   }
   if (expression != null) {
     myLogMessages.add("Failed to evaluate " + expression.getText());
   }
   return null;
 }
 public static int getPrecedence(PsiExpression expression) {
   if (expression instanceof PsiThisExpression
       || expression instanceof PsiLiteralExpression
       || expression instanceof PsiSuperExpression
       || expression instanceof PsiClassObjectAccessExpression
       || expression instanceof PsiArrayAccessExpression
       || expression instanceof PsiArrayInitializerExpression) {
     return LITERAL_PRECEDENCE;
   }
   if (expression instanceof PsiReferenceExpression) {
     final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) expression;
     if (referenceExpression.getQualifier() != null) {
       return METHOD_CALL_PRECEDENCE;
     } else {
       return LITERAL_PRECEDENCE;
     }
   }
   if (expression instanceof PsiMethodCallExpression || expression instanceof PsiNewExpression) {
     return METHOD_CALL_PRECEDENCE;
   }
   if (expression instanceof PsiTypeCastExpression) {
     return TYPE_CAST_PRECEDENCE;
   }
   if (expression instanceof PsiPrefixExpression) {
     return PREFIX_PRECEDENCE;
   }
   if (expression instanceof PsiPostfixExpression) {
     return POSTFIX_PRECEDENCE;
   }
   if (expression instanceof PsiPolyadicExpression) {
     final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression) expression;
     return getPrecedenceForOperator(polyadicExpression.getOperationTokenType());
   }
   if (expression instanceof PsiInstanceOfExpression) {
     return RELATIONAL_PRECEDENCE;
   }
   if (expression instanceof PsiConditionalExpression) {
     return CONDITIONAL_PRECEDENCE;
   }
   if (expression instanceof PsiAssignmentExpression) {
     return ASSIGNMENT_PRECEDENCE;
   }
   if (expression instanceof PsiParenthesizedExpression) {
     return PARENTHESIZED_PRECEDENCE;
   }
   return -1;
 }
 @Nullable
 private static PsiReferenceExpression getReferenceFromInstanceofExpression(
     PsiExpression expression) {
   if (expression instanceof PsiParenthesizedExpression) {
     final PsiParenthesizedExpression parenthesizedExpression =
         (PsiParenthesizedExpression) expression;
     return getReferenceFromInstanceofExpression(parenthesizedExpression.getExpression());
   } else if (expression instanceof PsiInstanceOfExpression) {
     final PsiInstanceOfExpression instanceOfExpression = (PsiInstanceOfExpression) expression;
     final PsiExpression operand =
         ParenthesesUtils.stripParentheses(instanceOfExpression.getOperand());
     if (!(operand instanceof PsiReferenceExpression)) {
       return null;
     }
     return (PsiReferenceExpression) operand;
   } else if (expression instanceof PsiPolyadicExpression) {
     final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression) expression;
     final IElementType tokenType = polyadicExpression.getOperationTokenType();
     if (JavaTokenType.OROR != tokenType) {
       return null;
     }
     final PsiExpression[] operands = polyadicExpression.getOperands();
     final PsiReferenceExpression referenceExpression =
         getReferenceFromInstanceofExpression(operands[0]);
     if (referenceExpression == null) {
       return null;
     }
     for (int i = 1, operandsLength = operands.length; i < operandsLength; i++) {
       if (!referencesEqual(
           referenceExpression, getReferenceFromInstanceofExpression(operands[i]))) {
         return null;
       }
     }
     return referenceExpression;
   } else {
     return null;
   }
 }
 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);
     }
   }
 }