public void setLength(int position) {
    myStringBuilder.setLength(position);
    if (myLineToOffsetMapping != null) {
      Map<Integer, Integer> newMap = new HashMap<>();
      for (Map.Entry<Integer, Integer> entry : myLineToOffsetMapping.entrySet()) {
        if (entry.getValue() <= position) {
          newMap.put(entry.getKey(), entry.getValue());
        }
      }
      myLineToOffsetMapping = newMap;
    }
    myRootGroup.truncate(position);
    assert currentGroupExists();
  }
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