void truncate(int stringLength) {
      if (myStart + myLength > stringLength) {
        myLength = stringLength - myStart;
      }
      for (Iterator<NewlineGroup> itr = myChildren.iterator(); itr.hasNext(); ) {
        NewlineGroup child = itr.next();
        if (child.myStart <= stringLength) {
          child.truncate(stringLength);
        } else {
          itr.remove();
        }
      }
      myReplacements.removeIf(r -> r.myStart > stringLength);
      myTokens.removeIf(t -> t.getStart() > stringLength);
    }
Recursive reformatting of groups.
If the group's content would take you over the specified preferred line length, then the group is applied.

- This algorithm usually ensures that if a group is applied, then all the group's parents in the tree are also
  applied. This tends to produce a nice structured output with well-placed potential newlines.
- The formatter keeps track of the offset as a result of the reformat at each character in the text buffer, and
  applies them to the bytecode offsets afterwards, so that the line number mappings don't get messed up.
src/org/jetbrains/java/decompiler/util/TextBuffer.java