@Override
  public void invoke(@NotNull Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
    if (!EditorModificationUtil.requestWriting(editor)) {
      return;
    }

    int caretOffset = editor.getCaretModel().getOffset();
    if (editor.isViewer() || editor.getDocument().getRangeGuard(caretOffset, caretOffset) != null) {
      editor.getDocument().fireReadOnlyModificationAttempt();
      EditorModificationUtil.checkModificationAllowed(editor);
      return;
    }

    LookupManager.getInstance(project).hideActiveLookup();

    final CharSequence charsSequence = editor.getDocument().getCharsSequence();

    final CompletionData data = computeData(editor, charsSequence);

    final CompletionState completionState = getCompletionState(editor);

    String oldPrefix = completionState.oldPrefix;
    CompletionVariant lastProposedVariant = completionState.lastProposedVariant;
    boolean fromOtherFiles = completionState.fromOtherFiles;

    if (lastProposedVariant == null || oldPrefix == null ||
        !completionState.caretOffsets.equals(getCaretOffsets(editor)) ||
        completionState.lastModCount != editor.getDocument().getModificationStamp()) {
      //we are starting over
      oldPrefix = data.myPrefix;
      completionState.oldPrefix = oldPrefix;
      lastProposedVariant = null;
      fromOtherFiles = false;
    } else {
      data.startOffset = completionState.lastStartOffset;
    }

    CompletionVariant nextVariant = computeNextVariant(editor, oldPrefix, lastProposedVariant, data, file, fromOtherFiles, false);
    if (nextVariant == null) {
      insertStringForEachCaret(editor, oldPrefix, caretOffset - data.startOffset);
      editor.putUserData(KEY_STATE, null);
      return;
    }

    RangeMarker start = editor.getDocument().createRangeMarker(data.startOffset, data.startOffset);
    nextVariant.fastenBelts();
    try {
      insertStringForEachCaret(editor, nextVariant.variant, caretOffset - data.startOffset);
    }
    finally {
      nextVariant.unfastenBelts();
    }

    if (!start.isValid()) {
      editor.putUserData(KEY_STATE, null);
      return;
    }

    completionState.lastProposedVariant = nextVariant;
    completionState.lastStartOffset = start.getStartOffset();
    completionState.lastModCount = editor.getDocument().getModificationStamp();
    completionState.caretOffsets = getCaretOffsets(editor);
    completionState.fromOtherFiles = nextVariant.editor != editor;
    if (nextVariant.editor == editor) highlightWord(nextVariant, project);

    start.dispose();
  }
@Override
  public void invoke(@NotNull Project project, @NotNull final Editor editor, @NotNull PsiFile file)