@Override
  public void handleInsert(final @NotNull InsertionContext context, final @NotNull JavaPsiClassReferenceElement item) {
    int offset = context.getTailOffset() - 1;
    final PsiFile file = context.getFile();
    PsiImportStatementBase importStatement = PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiImportStatementBase.class, false);
    if (importStatement != null) {
      PsiJavaCodeReferenceElement ref = findJavaReference(file, offset);
      String qname = item.getQualifiedName();
      if (qname != null && (ref == null || !qname.equals(ref.getCanonicalText()))) {
        AllClassesGetter.INSERT_FQN.handleInsert(context, item);
      }
      if (importStatement instanceof PsiImportStaticStatement) {
        context.setAddCompletionChar(false);
        EditorModificationUtilEx.insertStringAtCaret(context.getEditor(), ".");
      }
      return;
    }

    PsiElement position = file.findElementAt(offset);
    PsiJavaCodeReferenceElement ref = position != null && position.getParent() instanceof PsiJavaCodeReferenceElement ?
                                      (PsiJavaCodeReferenceElement) position.getParent() : null;
    PsiClass psiClass = item.getObject();
    SmartPsiElementPointer<PsiClass> classPointer = SmartPointerManager.createPointer(psiClass);
    final Project project = context.getProject();

    final Editor editor = context.getEditor();
    final char c = context.getCompletionChar();
    if (c == '#') {
      context.setLaterRunnable(() -> new CodeCompletionHandlerBase(CompletionType.BASIC).invokeCompletion(project, editor));
    } else if (c == '.' && PsiTreeUtil.getParentOfType(position, PsiParameterList.class) == null) {
      AutoPopupController.getInstance(context.getProject()).autoPopupMemberLookup(context.getEditor(), null);
    }

    String qname = psiClass.getQualifiedName();
    if (qname != null && PsiTreeUtil.getParentOfType(position, PsiDocComment.class, false) != null &&
        (ref == null || !ref.isQualified()) &&
        shouldInsertFqnInJavadoc(item, file)) {
      context.getDocument().replaceString(context.getStartOffset(), context.getTailOffset(), qname);
      return;
    }

    if (ref != null && PsiTreeUtil.getParentOfType(position, PsiDocTag.class) != null && ref.isReferenceTo(psiClass)) {
      return;
    }

    OffsetKey refEnd = context.trackOffset(context.getTailOffset(), true);

    boolean fillTypeArgs = context.getCompletionChar() == '<';
    if (fillTypeArgs) {
      context.setAddCompletionChar(false);
    }

    PsiClass finalPsiClass = psiClass;
    DumbService.getInstance(project).runWithAlternativeResolveEnabled(() -> PsiTypeLookupItem.addImportForItem(context, finalPsiClass));
    if (!context.getOffsetMap().containsOffset(refEnd)) {
      return;
    }

    context.setTailOffset(context.getOffset(refEnd));
    refEnd = context.trackOffset(context.getTailOffset(), false);

    context.commitDocument();

    // Restore elements after commit
    position = file.findElementAt(context.getTailOffset() - 1);
    ref = position != null && position.getParent() instanceof PsiJavaCodeReferenceElement ?
          (PsiJavaCodeReferenceElement)position.getParent() : null;

    if (c == '!' || c == '?') {
      context.setAddCompletionChar(false);
      if (ref != null && !(ref instanceof PsiReferenceExpression) &&
          !ref.textContains('@') && !(ref.getParent() instanceof PsiAnnotation)) {
        NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
        String annoName = c == '!' ? manager.getDefaultNotNull() : manager.getDefaultNullable();
        PsiClass cls = JavaPsiFacade.getInstance(project).findClass(annoName, file.getResolveScope());
        if (cls != null) {
          PsiJavaCodeReferenceElement newRef =
            JavaPsiFacade.getElementFactory(project).createReferenceFromText('@' + annoName + ' ' + ref.getText(), ref);
          JavaCodeStyleManager.getInstance(project).shortenClassReferences(ref.replace(newRef));
        }
      }
    }

    if (ref != null && PsiUtil.isAvailable(JavaFeature.PATTERNS, ref) && psiClass.getTypeParameters().length > 0) {
      PsiExpression instanceOfOperand = JavaCompletionUtil.getInstanceOfOperand(ref);
      if (instanceOfOperand != null) {
        PsiClassType origType = JavaPsiFacade.getElementFactory(project).createType(psiClass);
        PsiType generified = DfaPsiUtil.tryGenerify(instanceOfOperand, origType);
        if (generified != null && generified != origType) {
          String completeTypeText = generified.getCanonicalText();
          PsiJavaCodeReferenceElement newRef =
            JavaPsiFacade.getElementFactory(project).createReferenceFromText(completeTypeText, ref);
          PsiElement resultingRef = JavaCodeStyleManager.getInstance(project).shortenClassReferences(ref.replace(newRef));
          context.getEditor().getCaretModel().moveToOffset(resultingRef.getTextRange().getEndOffset());
          return;
        }
      }
    }

    psiClass = classPointer.dereference();

    if (item.getUserData(JavaChainLookupElement.CHAIN_QUALIFIER) == null &&
        shouldInsertParentheses(file.findElementAt(context.getTailOffset() - 1))) {
      if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) {
        overwriteTopmostReference(context);
        context.commitDocument();
      }
      if (psiClass != null && ConstructorInsertHandler.insertParentheses(context, item, psiClass, false)) {
        fillTypeArgs |= psiClass.hasTypeParameters() && PsiUtil.isAvailable(JavaFeature.GENERICS, file);
      }
    }
    else if (insertingAnnotation(context, item)) {
      if (psiClass != null && shouldHaveAnnotationParameters(psiClass)) {
        JavaCompletionUtil.insertParentheses(context, item, false, true);
      }
      if (context.getCompletionChar() == Lookup.NORMAL_SELECT_CHAR || context.getCompletionChar() == Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
        CharSequence text = context.getDocument().getCharsSequence();
        int tail = context.getTailOffset();
        if (text.length() > tail && Character.isLetter(text.charAt(tail))) {
          context.getDocument().insertString(tail, " ");
        }
      }
    }

    if (fillTypeArgs && context.getCompletionChar() != '(') {
      JavaCompletionUtil.promptTypeArgs(context, context.getOffset(refEnd));
    }
    else if (context.getCompletionChar() == Lookup.COMPLETE_STATEMENT_SELECT_CHAR &&
             psiClass != null && psiClass.getTypeParameters().length == 1 &&
             PsiUtil.isAvailable(JavaFeature.GENERICS, file)) {
      wrapFollowingTypeInGenerics(context, context.getOffset(refEnd));
    }
  }
@Override
  public void handleInsert(final @NotNull InsertionContext context, final @NotNull JavaPsiClassReferenceElement item)