protected void process(
    @NotNull final Project project,
    @NotNull final Editor editor,
    @NotNull final PsiFile file,
    final int attempt,
    boolean afterCompletion) throws TooManyAttemptsException {

    if (attempt > MAX_ATTEMPTS) throw new TooManyAttemptsException();
    myAttempt = attempt;

    try {
      commit(editor);
      if (myFirstErrorOffset != Integer.MAX_VALUE) {
        editor.getCaretModel().moveToOffset(myFirstErrorOffset);
      }

      myFirstErrorOffset = Integer.MAX_VALUE;

      PsiElement atCaret = getStatementAtCaret(editor, file);
      if (atCaret == null) {
        processDefaultEnter(project, editor, file);
        return;
      }

      OrderedSet<PsiElement> queue = new OrderedSet<>();
      collectAllElements(atCaret, queue, collectChildrenRecursively(atCaret));
      queue.add(atCaret);

      for (PsiElement psiElement : queue) {
        for (Fixer fixer : myFixers) {
          fixer.apply(editor, this, psiElement);
          if (LookupManager.getInstance(project).getActiveLookup() != null) {
            return;
          }
          if (isUncommited(project) || !psiElement.isValid()) {
            moveCaretInsideBracesIfAny(editor, file);
            process(project, editor, file, attempt + 1, afterCompletion);
            return;
          }
        }
      }

      doEnter(atCaret, file, editor, afterCompletion);
    }
    catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }
protected void process(
    @NotNull final Project project,
    @NotNull final Editor editor,
    @NotNull final PsiFile file,
    final int attempt,
    boolean afterCompletion)