code: @Nullable
    static String renderValue(ExpressionInfo expr) {
      Object value = expr.getValue();
  
      if (value == null) return "null";
      if ("".equals(value)) return "\"\""; // value.equals() might throw exception, so we use "".equals() instead
  
      String str;
  
      try {
        str = doRenderValue(expr);
      } catch (Exception e) {
        return String.format("%s (renderer threw %s)",
            javaLangObjectToString(value), e.getClass().getSimpleName());
      }
  
      if (value instanceof Throwable) {
        Throwable throwable = (Throwable) value;
        genericStackTraceFilter.filter(throwable);
        StringWriter stackTrace = new StringWriter();
        throwable.printStackTrace(new PrintWriter(stackTrace));
        return stackTrace.toString();
      }
  
      if (str == null || "".equals(str)) {
        return javaLangObjectToString(value);
      }
  
      // only print enum values that add valuable information
      if (value instanceof Enum) {
        String text = expr.getText().trim();
        int index = text.lastIndexOf('.');
        String potentialEnumConstantNameInText = text.substring(index + 1);
        if (str.equals(potentialEnumConstantNameInText)) return null;
      }
  
      return str;
    }
docs: Returns a string representation of a value, or <tt>null</tt> if
  the value should not be shown (because it does not add any valuable
  information). Note that the method may also change rendered values
  of child expression.
  
  @param expr the expression whose value is to be rendered
  @return a string representation of the value