@Override
    public void documentChanged(@NotNull DocumentEvent event) {
      String docText = event.getDocument().getText();
      if (myText.equals(docText)) return;
      if (event.isWholeTextReplaced()) {
        myRanges.clear();
        myRanges.add(new RangeHighlightingData(0, docText.length(), false));
      }
      else {
        int offset = event.getOffset();
        if (event.getNewLength() >= event.getOldLength()) {
          if (myRanges.isEmpty()) {
            myRanges.add(new RangeHighlightingData(0, 0, false));
          }
          int insertedLen = event.getNewLength() - event.getOldLength();
          for (RangeHighlightingData data : myRanges) {
            if (data.textRange.contains(offset) || data == myRanges.get(myRanges.size() - 1) && data.textRange.getEndOffset() <= offset) {
              data.updateRange(data.textRange.grown(insertedLen));
            }
            else if (data.textRange.getStartOffset() > offset) {
              data.updateRange(data.textRange.shiftRight(insertedLen));
            }
          }
        }
        else {
          int deletedLen = event.getOldLength() - event.getNewLength();
          TextRange deletedRange = new TextRange(offset, offset + deletedLen);
          int delta = 0;
          Iterator<RangeHighlightingData> rangeIterator = myRanges.iterator();
          while(rangeIterator.hasNext()) {
            RangeHighlightingData data =rangeIterator.next();
            int cutoutStart = Math.max(deletedRange.getStartOffset(), data.textRange.getStartOffset());
            int cutoutEnd = Math.min(deletedRange.getEndOffset(), data.textRange.getEndOffset());
            if (cutoutStart < cutoutEnd) {
              int shrinkSize = cutoutEnd - cutoutStart;
              if (shrinkSize == data.textRange.getLength()) {
                rangeIterator.remove();
              }
              else {
                data.updateRange(data.textRange.grown(-shrinkSize));
              }
              data.updateRange(data.textRange.shiftLeft(delta));
              delta += shrinkSize;
            }
            else {
              data.updateRange(data.textRange.shiftLeft(delta));
            }
          }
        }
      }
      myText = docText;
    }
@Override
    public void documentChanged(@NotNull DocumentEvent event)