public void process() throws DiffTooBigException {
      if (!loadContents()) return;

      List<LineFragment> lineFragments = computeFragments();

      List<Pair<TodoItem, LineFragment>> changedTodoItems = new ArrayList<>();
      StepIntersection.processIntersections(
        myNewTodoItems, lineFragments,
        TODO_ITEM_CONVERTOR, new RightLineFragmentConvertor(myAfterContent),
        (todoItem, lineFragment) -> changedTodoItems.add(Pair.create(todoItem, lineFragment)));

      if (changedTodoItems.isEmpty()) return;

      final List<TodoItem> oldTodoItems = computeOldTodoItems();

      if (oldTodoItems.isEmpty()) {
        for (Pair<TodoItem, LineFragment> pair : changedTodoItems) {
          myAddedOrEditedTodos.add(pair.first);
        }
        return;
      }

      LineFragment lastLineFragment = null;
      HashSet<String> oldTodoTexts = new HashSet<>();
      for (Pair<TodoItem, LineFragment> pair : changedTodoItems) {
        TodoItem todoItem = pair.first;
        LineFragment lineFragment = pair.second;

        if (lineFragment != lastLineFragment) {
          oldTodoTexts.clear();
          StepIntersection.processElementIntersections(
            lineFragment, oldTodoItems,
            new LeftLineFragmentConvertor(myBeforeContent), TODO_ITEM_CONVERTOR,
            (fragment, oldTodoItem) -> oldTodoTexts.add(getTodoText(oldTodoItem, myBeforeContent)));
          lastLineFragment = lineFragment;
        }

        final String text = getTodoText(todoItem, myAfterContent);
        if (!oldTodoTexts.contains(text)) {
          myAddedOrEditedTodos.add(todoItem);
        }
        else if (TODO_ITEM_CONVERTOR.convert(todoItem).getEndOffset() >= lineFragment.getStartOffset2()) {
          myInChangedTodos.add(todoItem);
        }
      }
      myInChangedTodos.removeAll(myAddedOrEditedTodos);
    }
public void process()