private static boolean mergeUpdate(@NotNull List<? extends DocumentUpdate> updates, int eventOffset, int eventOldLength, int eventNewLength) {
      if (updates.isEmpty()) return false;
      final int MERGE_MARGIN = 5;
      DocumentUpdate a = updates.get(updates.size() - 1);
      if (eventOffset < a.offset) {
        // a not sorted update, ignore as it will be merged after sorting all updates
        return false;
      }
      if (a.offset == eventOffset) {
        if (a.newLength > eventOldLength) {
          a.newLength += eventNewLength - eventOldLength;
        } else {
          a.oldLength += eventOldLength - a.newLength;
          a.newLength = eventNewLength;
        }
      } else if (a.offset + a.newLength > eventOffset) {
        if (a.offset + a.newLength < eventOffset + eventOldLength) {
          a.oldLength = eventOldLength + eventOffset - (a.offset + a.oldLength);
        }
        a.newLength += eventNewLength - eventOldLength;
      } else if (a.offset + a.newLength + MERGE_MARGIN >= eventOffset) {
        int offsetDiff = eventOffset - a.offset - a.newLength;
        a.oldLength += offsetDiff + eventOldLength;
        a.newLength += offsetDiff + eventNewLength;
      }
      else {
        return false;
      }
      return true;
    }
private static boolean mergeUpdate(@NotNull List<? extends DocumentUpdate> updates, int eventOffset, int eventOldLength, int eventNewLength)