@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;
  }
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
spock-core/src/main/java/org/spockframework/runtime/ExpressionInfoValueRenderer.java