private @Nullable TreeElement removeElementsForRange(@NotNull TreeElement startLeaf,
                                             int startLeafOffset,
                                             @NotNull TextRange rangeToRemove,
                                             @NotNull CharTable charTable) {
    TreeElement updatedStartLeaf = null;
    TreeElement currentLeaf = startLeaf;
    // leaf offset is in terms of RangeToRemove, i.e. it's start is position in original code and length is a length of artificial text
    int leafOffset = startLeafOffset;
    if (rangeToRemove.getEndOffset() > startLeafOffset + startLeaf.getTextLength()) {
      leafOffset += startLeaf.getTextLength();
      updatedStartLeaf = cutPartOfLeaf(startLeaf, startLeafOffset, rangeToRemove, charTable);
      currentLeaf = findNextSuitableElement(updatedStartLeaf);
    }

    while (currentLeaf != null && rangeToRemove.containsRange(leafOffset, leafOffset + currentLeaf.getTextLength())) {
      TreeElement leafToRemove = currentLeaf;
      leafOffset += currentLeaf.getTextLength();
      currentLeaf = findNextSuitableElement(currentLeaf);
      leafToRemove.rawRemove();
    }
    TreeElement leafAfterCompletelyRemoved = currentLeaf;

    TreeElement updatedLastLeaf = null;
    if (currentLeaf != null && leafOffset < rangeToRemove.getEndOffset()) {
      updatedLastLeaf = cutPartOfLeaf(currentLeaf, leafOffset, rangeToRemove, charTable);
    }

    return updatedStartLeaf != null ? updatedStartLeaf :
           updatedLastLeaf != null ? updatedLastLeaf :
           leafAfterCompletelyRemoved;
  }
private @Nullable TreeElement removeElementsForRange(@NotNull TreeElement startLeaf,
                                             int startLeafOffset,
                                             @NotNull TextRange rangeToRemove,
                                             @NotNull CharTable charTable)