@NotNull
  public static String getNegatedExpressionText(@Nullable PsiExpression expression,
                                                int precedence,
                                                CommentTracker tracker) {
    if (expression == null) {
      return "";
    }
    if (expression instanceof PsiMethodCallExpression) {
      String smartNegation = findSmartMethodNegation(expression);
      if (smartNegation != null) return smartNegation;
    }
    if (expression instanceof PsiParenthesizedExpression parenthesizedExpression) {
      PsiExpression operand = parenthesizedExpression.getExpression();
      if (operand != null) {
        return '(' + getNegatedExpressionText(operand, tracker) + ')';
      }
    }
    if (expression instanceof PsiAssignmentExpression && expression.getParent() instanceof PsiExpressionStatement) {
      String newOp = null;
      IElementType tokenType = ((PsiAssignmentExpression)expression).getOperationTokenType();
      if (tokenType == JavaTokenType.ANDEQ) {
        newOp = "|=";
      }
      else if (tokenType == JavaTokenType.OREQ) {
        newOp = "&=";
      }
      if (newOp != null) {
        return tracker.text(((PsiAssignmentExpression)expression).getLExpression()) +
               newOp +
               getNegatedExpressionText(((PsiAssignmentExpression)expression).getRExpression());
      }
    }
    if (expression instanceof PsiConditionalExpression conditionalExpression) {
      final boolean needParenthesis = ParenthesesUtils.getPrecedence(conditionalExpression) >= precedence;
      final String text = tracker.text(conditionalExpression.getCondition()) +
                          '?' + getNegatedExpressionText(conditionalExpression.getThenExpression(), tracker) +
                          ':' + getNegatedExpressionText(conditionalExpression.getElseExpression(), tracker);
      return needParenthesis ? "(" + text + ")" : text;
    }
    if (isNegation(expression)) {
      final PsiExpression negated = getNegated(expression);
      if (negated != null) {
        return ParenthesesUtils.getText(tracker.markUnchanged(negated), precedence);
      }
    }
    if (expression instanceof PsiPolyadicExpression polyadicExpression) {
      final IElementType tokenType = polyadicExpression.getOperationTokenType();
      final PsiExpression[] operands = polyadicExpression.getOperands();
      if (ComparisonUtils.isComparison(polyadicExpression)) {
        final String negatedComparison = ComparisonUtils.getNegatedComparison(tokenType);
        final StringBuilder result = new StringBuilder();
        final boolean isEven = (operands.length & 1) != 1;
        for (int i = 0, length = operands.length; i < length; i++) {
          final PsiExpression operand = operands[i];
          if (TypeUtils.hasFloatingPointType(operand) && !ComparisonUtils.isEqualityComparison(polyadicExpression)) {
            // preserve semantics for NaNs
            return "!(" + polyadicExpression.getText() + ')';
          }
          if (i > 0) {
            if (isEven && (i & 1) != 1) {
              final PsiJavaToken token = polyadicExpression.getTokenBeforeOperand(operand);
              if (token != null) {
                result.append(token.getText());
              }
            }
            else {
              result.append(negatedComparison);
            }
          }
          result.append(tracker.text(operand));
        }
        return result.toString();
      }
      if(tokenType.equals(JavaTokenType.ANDAND) || tokenType.equals(JavaTokenType.OROR)) {
        final String targetToken;
        final int newPrecedence;
        if (tokenType.equals(JavaTokenType.ANDAND)) {
          targetToken = "||";
          newPrecedence = ParenthesesUtils.OR_PRECEDENCE;
        }
        else {
          targetToken = "&&";
          newPrecedence = ParenthesesUtils.AND_PRECEDENCE;
        }
        final Function<PsiElement, String> replacer = child -> {
          if (child instanceof PsiExpression) {
            return getNegatedExpressionText((PsiExpression)child, newPrecedence, tracker);
          }
          return child instanceof PsiJavaToken ? targetToken : tracker.text(child);
        };
        final String join = StringUtil.join(polyadicExpression.getChildren(), replacer, "");
        return (newPrecedence > precedence) ? '(' + join + ')' : join;
      }
    }
    if (expression instanceof PsiLiteralExpression) {
      Object value = ((PsiLiteralExpression)expression).getValue();
      if (value instanceof Boolean) {
        return String.valueOf(!((Boolean)value));
      }
    }
    return '!' + ParenthesesUtils.getText(tracker.markUnchanged(expression), ParenthesesUtils.PREFIX_PRECEDENCE);
  }
@NotNull
  public static String getNegatedExpressionText(@Nullable PsiExpression expression,
                                                int precedence,
                                                CommentTracker tracker)