@Override
  public void update(@NotNull PresentationData presentation) {
    SmartTodoItemPointer todoItemPointer = getValue();
    assert todoItemPointer != null;
    TodoItem todoItem = todoItemPointer.getTodoItem();
    RangeMarker myRangeMarker = todoItemPointer.getRangeMarker();
    if (!todoItem.getFile().isValid() || !myRangeMarker.isValid() || myRangeMarker.getStartOffset() == myRangeMarker.getEndOffset()) {
      myRangeMarker.dispose();
      setValue(null);
      return;
    }

    @NotNull List<HighlightedRegion> myHighlightedRegions = ((TodoItemNodePresentationData) presentation).getHighlightedRegions();
    @NotNull List<HighlightedRegionProvider> myAdditionalLines = ((TodoItemNodePresentationData) presentation).getAdditionalLines();
    myHighlightedRegions.clear();
    myAdditionalLines.clear();

    // Update name

    Document document = todoItemPointer.getDocument();
    CharSequence chars = document.getCharsSequence();
    int startOffset = myRangeMarker.getStartOffset();
    int endOffset = myRangeMarker.getEndOffset();
    int lineNumber = document.getLineNumber(startOffset);
    int lineStartOffset = document.getLineStartOffset(lineNumber);
    int columnNumber = startOffset - lineStartOffset;

    // skip all white space characters

    while (lineStartOffset < document.getTextLength() && (chars.charAt(lineStartOffset) == '\t' || chars.charAt(lineStartOffset) == ' ')) {
      lineStartOffset++;
    }

    int lineEndOffset = document.getLineEndOffset(lineNumber);

    String lineColumnPrefix = "(" + (lineNumber + 1) + ", " + (columnNumber + 1) + ") ";

    String highlightedText = chars.subSequence(lineStartOffset, Math.min(lineEndOffset, chars.length())).toString();

    String newName = lineColumnPrefix + highlightedText;

    // Update icon

    TodoPattern pattern = todoItem.getPattern();
    Icon newIcon =
      pattern != null ? pattern.getAttributes().getIcon() : IconManager.getInstance().getPlatformIcon(PlatformIcons.TodoDefault);

    // Update highlighted regions

    myHighlightedRegions.clear();
    EditorHighlighter highlighter = myBuilder.getHighlighter(todoItem.getFile(), document);
    collectHighlights(myHighlightedRegions, highlighter, lineStartOffset, lineEndOffset, lineColumnPrefix.length());
    TextAttributes attributes =
      pattern != null ? pattern.getAttributes().getTextAttributes() : TodoAttributesUtil.getDefaultColorSchemeTextAttributes();
    myHighlightedRegions.add(new HighlightedRegion(
      lineColumnPrefix.length() + startOffset - lineStartOffset,
      lineColumnPrefix.length() + endOffset - lineStartOffset,
      attributes
    ));

    //

    presentation.setPresentableText(newName);
    presentation.setIcon(newIcon);

    for (RangeMarker additionalMarker : todoItemPointer.getAdditionalRangeMarkers()) {
      if (!additionalMarker.isValid()) break;
      ArrayList<HighlightedRegion> highlights = new ArrayList<>();
      int lineNum = document.getLineNumber(additionalMarker.getStartOffset());
      int lineStart = document.getLineStartOffset(lineNum);
      int lineEnd = document.getLineEndOffset(lineNum);
      int lineStartNonWs = CharArrayUtil.shiftForward(chars, lineStart, " \t");
      if (lineStartNonWs > additionalMarker.getStartOffset() || lineEnd < additionalMarker.getEndOffset()) {
        // can happen for an invalid (obsolete) node, tree implementation can call this method for such a node
        break;
      }
      collectHighlights(highlights, highlighter, lineStartNonWs, lineEnd, 0);
      highlights.add(new HighlightedRegion(
        additionalMarker.getStartOffset() - lineStartNonWs,
        additionalMarker.getEndOffset() - lineStartNonWs,
        attributes
      ));
      myAdditionalLines.add(new AdditionalTodoLine(document.getText(new TextRange(lineStartNonWs, lineEnd)), highlights));
    }
  }
@Override
  public void update(@NotNull PresentationData presentation)