final void rawRemoveUpToWithoutNotifications(@Nullable TreeElement end, boolean invalidate) {
    if(this == end) return;

    CompositeElement parent = getTreeParent();
    TreeElement startPrev = getTreePrev();
    TreeElement endPrev = end != null ? end.getTreePrev() : null;

    assert end == null || end.getTreeParent() == parent : "Trying to remove non-child";

    if (end != null) {
      TreeElement element;
      for (element = this; element != end && element != null; element = element.getTreeNext());
      assert element == end : end + " is not successor of " + this +" in the .getTreeNext() chain";
    }
    if (parent != null){
      if (getTreePrev() == null) {
        parent.setFirstChildNode(end);
      }
      if (end == null) {
        parent.setLastChildNode(startPrev);
      }
    }
    if (startPrev != null){
      startPrev.setTreeNext(end);
    }
    if (end != null){
      end.setTreePrev(startPrev);
    }

    setTreePrev(null);
    if (endPrev != null){
      endPrev.setTreeNext(null);
    }

    if (parent != null){
      for(TreeElement element = this; element != null; element = element.getTreeNext()){
        element.setTreeParent(null);
        if (invalidate) {
          element.onInvalidated();
        }
      }
    }

    DebugUtil.checkTreeStructure(parent);
    DebugUtil.checkTreeStructure(this);
  }
final void rawRemoveUpToWithoutNotifications(@Nullable TreeElement end, boolean invalidate)