@Override
  public void handleInsert(final @NotNull InsertionContext context, final @NotNull T item) {
    final char completionChar = context.getCompletionChar();
    final Editor editor = context.getEditor();
    if (completionChar != myLeftParenthesis && !editor.getSettings().isInsertParenthesesAutomatically()) return;
    final Document document = editor.getDocument();
    context.commitDocument();
    PsiElement lParen = findExistingLeftParenthesis(context);

    final boolean putCaretInside = completionChar == myLeftParenthesis || placeCaretInsideParentheses(context, item);

    if (completionChar == myLeftParenthesis) {
      context.setAddCompletionChar(false);
    }

    if (lParen != null) {
      int lparenthOffset = lParen.getTextRange().getStartOffset();
      if (mySpaceBeforeParentheses && lparenthOffset == context.getTailOffset()) {
        document.insertString(context.getTailOffset(), " ");
        lparenthOffset++;
      }

      if (completionChar == myLeftParenthesis || completionChar == '\t') {
        editor.getCaretModel().moveToOffset(lparenthOffset + 1);
      } else {
        editor.getCaretModel().moveToOffset(context.getTailOffset());
      }

      context.setTailOffset(lparenthOffset + 1);

      PsiElement list = lParen.getParent();
      PsiElement last = list.getLastChild();
      if (isToken(last, String.valueOf(myRightParenthesis))) {
        int rparenthOffset = last.getTextRange().getStartOffset();
        context.setTailOffset(rparenthOffset + 1);
        if (!putCaretInside) {
          for (int i = lparenthOffset + 1; i < rparenthOffset; i++) {
            if (!Character.isWhitespace(document.getCharsSequence().charAt(i))) {
              return;
            }
          }
          editor.getCaretModel().moveToOffset(context.getTailOffset());
        }
        else if (mySpaceBetweenParentheses && document.getCharsSequence().charAt(lparenthOffset) == ' ') {
          editor.getCaretModel().moveToOffset(lparenthOffset + 2);
        }
        else {
          editor.getCaretModel().moveToOffset(lparenthOffset + 1);
        }
        return;
      }
    } else {
      document.insertString(context.getTailOffset(), getSpace(mySpaceBeforeParentheses) + myLeftParenthesis + getSpace(mySpaceBetweenParentheses));
      editor.getCaretModel().moveToOffset(context.getTailOffset());
    }

    if (!myMayInsertRightParenthesis) return;

    if (context.getCompletionChar() == myLeftParenthesis) {
      //todo use BraceMatchingUtil.isPairedBracesAllowedBeforeTypeInFileType
      int tail = context.getTailOffset();
      if (tail < document.getTextLength() && StringUtil.isJavaIdentifierPart(document.getCharsSequence().charAt(tail))) {
        return;
      }
    }

    document.insertString(context.getTailOffset(), getSpace(mySpaceBetweenParentheses) + myRightParenthesis);
    if (!putCaretInside) {
      editor.getCaretModel().moveToOffset(context.getTailOffset());
    }
    else if (!mySpaceBetweenParentheses) {
      final int rangeStart = context.getStartOffset();
      final int rangeEnd = Math.max(editor.getCaretModel().getOffset(), context.getStartOffset());

      TabOutScopesTracker.getInstance().registerScopeRange(editor, rangeStart, rangeEnd);
    }
  }
@Override
  public void handleInsert(final @NotNull InsertionContext context, final @NotNull T item)