public static boolean isConversionToStringNecessary(PsiExpression expression, boolean throwable, @Nullable PsiType type) {
    final PsiElement parent = ParenthesesUtils.getParentSkipParentheses(expression);
    if (parent instanceof PsiPolyadicExpression polyadicExpression) {
      if (!TypeUtils.typeEquals(JAVA_LANG_STRING, polyadicExpression.getType())) {
        return true;
      }
      final PsiExpression[] operands = polyadicExpression.getOperands();
      boolean expressionSeen = false;
      for (int i = 0, length = operands.length; i < length; i++) {
        final PsiExpression operand = operands[i];
        if (PsiTreeUtil.isAncestor(operand, expression, false)) {
          if (i > 0) return true;
          expressionSeen = true;
        }
        else if ((!expressionSeen || i == 1) && TypeUtils.isJavaLangString(operand.getType())) {
          return false;
        }
      }
      return true;
    }
    else if (parent instanceof PsiExpressionList expressionList) {
      final PsiElement grandParent = expressionList.getParent();
      if (!(grandParent instanceof PsiMethodCallExpression methodCallExpression)) {
        return true;
      }
      final PsiReferenceExpression methodExpression1 = methodCallExpression.getMethodExpression();
      @NonNls final String name = methodExpression1.getReferenceName();
      final PsiExpression[] expressions = expressionList.getExpressions();
      if ("insert".equals(name)) {
        if (expressions.length < 2 || !expression.equals(PsiUtil.skipParenthesizedExprDown(expressions[1]))) {
          return true;
        }
        return !isCallToMethodIn(methodCallExpression, JAVA_LANG_STRING_BUILDER, JAVA_LANG_STRING_BUFFER);
      } else if ("append".equals(name)) {
        if (expression.equals(PsiUtil.skipParenthesizedExprDown(expressions[0])) &&
            isCallToMethodIn(methodCallExpression, JAVA_LANG_STRING_BUILDER, JAVA_LANG_STRING_BUFFER)) {
          if (expressions.length == 1) {
            return false;
          }
          if (expressions.length == 3) {
            return !InheritanceUtil.isInheritor(type, JAVA_LANG_CHAR_SEQUENCE);
          }
        }
        return true;
      } else if ("print".equals(name) || "println".equals(name)) {
        return !isCallToMethodIn(methodCallExpression, JAVA_IO_PRINT_STREAM, JAVA_IO_PRINT_WRITER);
      } else if ("trace".equals(name) || "debug".equals(name) || "info".equals(name) || "warn".equals(name) || "error".equals(name)) {
        if (!isCallToMethodIn(methodCallExpression, "org.slf4j.Logger")) {
          return true;
        }
        int l = 1;
        for (int i = 0; i < expressions.length; i++) {
          final PsiExpression expression1 = expressions[i];
          if (i == 0 && TypeUtils.expressionHasTypeOrSubtype(expression1, "org.slf4j.Marker")) {
            l = 2;
          }
          if (expression1 == expression) {
            if (i < l || (throwable && i == expressions.length - 1)) {
              return true;
            }
          }
        }
      }
      else if (FormatUtils.isFormatCall(methodCallExpression)) {
        return isConversionToStringNecessary(expression, methodCallExpression);
      }
      else {
        return true;
      }
    }
    else {
      return true;
    }
    return false;
  }
public static boolean isConversionToStringNecessary(PsiExpression expression, boolean throwable, @Nullable PsiType type)