private void filter(Throwable throwable, Set<Throwable> seen) {
    if (!seen.add(throwable)) {
      return;
    }

    List<StackTraceElement> filteredTrace = new ArrayList<>();

    for (StackTraceElement elem : throwable.getStackTrace()) {
      if (isInitializerOrFixtureMethod(elem)) {
        filteredTrace.add(elem);
        break;
      }
      if (checkForAndAddPrettyPrintedFeatureMethod(elem, filteredTrace)) break;
      if (isFilteredClass(elem)) continue;
      if (checkForAndAddPrettyPrintedClosureInvocation(elem, filteredTrace)) continue;
      if (isGeneratedMethod(elem)) continue;
      filteredTrace.add(elem);
    }

    throwable.setStackTrace(filteredTrace.toArray(STACK_TRACE_ELEMENTS));

    if (throwable.getCause() != null) filter(throwable.getCause(), seen);

    for (Throwable suppressed : throwable.getSuppressed()) {
      filter(suppressed, seen);
    }
  }
Filters an exception's stack trace. Removes internal Groovy and Spock methods, and
restores the original names of feature methods (as specified in source code).
Stack trace elements below a feature/fixture method invocation are truncated.

@author Peter Niederwieser
spock-core/src/main/java/org/spockframework/runtime/StackTraceFilter.java