public char @NotNull [] mergeToCharArray(char @NotNull [] text, int textLength, @NotNull List<? extends TextChange> changes) {
    int newLength = textLength;
    for (TextChange change : changes) {
      newLength += change.getText().length() - (change.getEnd() - change.getStart());
    }
    char[] data = new char[newLength];
    int oldEndOffset = textLength;
    int newEndOffset = data.length;
    for (int i = changes.size() - 1; i >= 0; i--) {
      TextChange change = changes.get(i);
      
      // Copy all unprocessed symbols from initial text that lay after the changed offset.
      int symbolsToMoveNumber = oldEndOffset - change.getEnd();
      System.arraycopy(text, change.getEnd(), data, newEndOffset - symbolsToMoveNumber, symbolsToMoveNumber);
      newEndOffset -= symbolsToMoveNumber;
      
      // Copy all change symbols.
      char[] changeSymbols = change.getChars();
      newEndOffset -= changeSymbols.length;
      System.arraycopy(changeSymbols, 0, data, newEndOffset, changeSymbols.length);
      oldEndOffset = change.getStart();
    }
    
    if (oldEndOffset > 0) {
      System.arraycopy(text, 0, data, 0, oldEndOffset);
    }
    
    return data;
  }
public char @NotNull [] mergeToCharArray(char @NotNull [] text, int textLength, @NotNull List<? extends TextChange> changes)