void (@NotNull TextChange change) { if (myChanges.isEmpty()) { myChanges.add(new ChangeEntry(new TextChangeImpl(change.getText(), change.getStart(), change.getEnd()), change.getStart())); return; } // There is a big chance that the document is processed sequentially from start to end, hence, it makes sense // to check if given change lays beyond other registered changes and register it quickly in case of success. ChangeEntry last = myChanges.get(myChanges.size() - 1); if (last.clientStartOffset + last.change.getText().length() < change.getStart()) { int clientShift = last.clientStartOffset - last.change.getStart() + last.change.getDiff(); myChanges.add(new ChangeEntry( new TextChangeImpl(change.getText(), change.getStart() - clientShift, change.getEnd() - clientShift), change.getStart() )); return; } int insertionIndex = doStore(change); if (insertionIndex < 0) { return; } mergeIfNecessary(insertionIndex); }