@Override
  public void beforeCompletion(@NotNull final CompletionInitializationContext context) {
    final PsiFile file = context.getFile();

    if (file instanceof PsiJavaFile) {
      JavaCompletionUtil.initOffsets(file, context.getOffsetMap());

      autoImport(file, context.getStartOffset() - 1, context.getEditor());

      if (context.getCompletionType() == CompletionType.BASIC) {
        if (semicolonNeeded(context.getEditor(), file, context.getStartOffset())) {
          context.setDummyIdentifier(CompletionInitializationContext.DUMMY_IDENTIFIER.trim() + ";");
          return;
        }

        final PsiJavaCodeReferenceElement ref =
            PsiTreeUtil.findElementOfClassAtOffset(
                file, context.getStartOffset(), PsiJavaCodeReferenceElement.class, false);
        if (ref != null && !(ref instanceof PsiReferenceExpression)) {
          if (ref.getParent() instanceof PsiTypeElement) {
            context.setDummyIdentifier(
                CompletionInitializationContext.DUMMY_IDENTIFIER.trim() + ";");
          }

          if (JavaSmartCompletionContributor.AFTER_NEW.accepts(ref)) {
            final PsiReferenceParameterList paramList = ref.getParameterList();
            if (paramList != null && paramList.getTextLength() > 0) {
              context
                  .getOffsetMap()
                  .addOffset(
                      ConstructorInsertHandler.PARAM_LIST_START,
                      paramList.getTextRange().getStartOffset());
              context
                  .getOffsetMap()
                  .addOffset(
                      ConstructorInsertHandler.PARAM_LIST_END,
                      paramList.getTextRange().getEndOffset());
            }
          }

          return;
        }

        final PsiElement element = file.findElementAt(context.getStartOffset());

        if (psiElement().inside(PsiAnnotation.class).accepts(element)) {
          return;
        }

        context.setDummyIdentifier(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED);
      }
    }
  }
  private void insertDummyIdentifier(
      final CompletionInitializationContext initContext,
      final boolean hasModifiers,
      final int invocationCount) {
    final PsiFile originalFile = initContext.getFile();
    InjectedLanguageManager manager =
        InjectedLanguageManager.getInstance(originalFile.getProject());
    final PsiFile hostFile = manager.getTopLevelFile(originalFile);
    final Editor hostEditor = InjectedLanguageUtil.getTopLevelEditor(initContext.getEditor());
    final OffsetMap hostMap =
        translateOffsetMapToHost(initContext, originalFile, hostFile, hostEditor);

    final PsiFile[] hostCopy = {null};
    DocumentUtil.writeInRunUndoTransparentAction(
        new Runnable() {
          @Override
          public void run() {
            hostCopy[0] =
                createFileCopy(
                    hostFile, initContext.getStartOffset(), initContext.getSelectionEndOffset());
          }
        });

    final Document copyDocument = hostCopy[0].getViewProvider().getDocument();
    assert copyDocument != null : "no document";
    final OffsetTranslator translator =
        new OffsetTranslator(hostEditor.getDocument(), initContext.getFile(), copyDocument);

    CompletionAssertions.checkEditorValid(initContext.getEditor());
    CommandProcessor.getInstance()
        .runUndoTransparentAction(
            new Runnable() {
              @Override
              public void run() {
                ApplicationManager.getApplication()
                    .runWriteAction(
                        new Runnable() {
                          @Override
                          public void run() {
                            String dummyIdentifier = initContext.getDummyIdentifier();
                            if (StringUtil.isEmpty(dummyIdentifier)) return;

                            int startOffset =
                                hostMap.getOffset(CompletionInitializationContext.START_OFFSET);
                            int endOffset =
                                hostMap.getOffset(
                                    CompletionInitializationContext.SELECTION_END_OFFSET);
                            copyDocument.replaceString(startOffset, endOffset, dummyIdentifier);
                          }
                        });
              }
            });
    CompletionAssertions.checkEditorValid(initContext.getEditor());

    final Project project = originalFile.getProject();

    if (!synchronous) {
      if (CompletionServiceImpl.isPhase(CompletionPhase.NoCompletion.getClass())
          || !CompletionServiceImpl.assertPhase(CompletionPhase.CommittingDocuments.class)) {
        Disposer.dispose(translator);
        return;
      }

      final CompletionPhase.CommittingDocuments phase =
          (CompletionPhase.CommittingDocuments) CompletionServiceImpl.getCompletionPhase();

      CompletionAutoPopupHandler.runLaterWithCommitted(
          project,
          copyDocument,
          new Runnable() {
            @Override
            public void run() {
              if (phase.checkExpired()) {
                Disposer.dispose(translator);
                return;
              }
              doComplete(
                  initContext, hasModifiers, invocationCount, hostCopy[0], hostMap, translator);
            }
          });
    } else {
      PsiDocumentManager.getInstance(project).commitDocument(copyDocument);

      doComplete(initContext, hasModifiers, invocationCount, hostCopy[0], hostMap, translator);
    }
  }
  private void doComplete(
      CompletionInitializationContext initContext,
      boolean hasModifiers,
      int invocationCount,
      PsiFile hostCopy,
      OffsetMap hostMap,
      OffsetTranslator translator) {
    final Editor editor = initContext.getEditor();
    CompletionAssertions.checkEditorValid(editor);

    CompletionContext context =
        createCompletionContext(
            hostCopy,
            hostMap.getOffset(CompletionInitializationContext.START_OFFSET),
            hostMap,
            initContext.getFile());
    LookupImpl lookup = obtainLookup(editor);
    CompletionParameters parameters = createCompletionParameters(invocationCount, context, editor);

    CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
    if (phase instanceof CompletionPhase.CommittingDocuments) {
      if (phase.indicator != null) {
        phase.indicator.closeAndFinish(false);
      }
      ((CompletionPhase.CommittingDocuments) phase).replaced = true;
    } else {
      CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
    }

    final Semaphore freezeSemaphore = new Semaphore();
    freezeSemaphore.down();
    final CompletionProgressIndicator indicator =
        new CompletionProgressIndicator(
            editor,
            parameters,
            this,
            freezeSemaphore,
            initContext.getOffsetMap(),
            hasModifiers,
            lookup);
    Disposer.register(indicator, hostMap);
    Disposer.register(indicator, context.getOffsetMap());
    Disposer.register(indicator, translator);

    CompletionServiceImpl.setCompletionPhase(
        synchronous
            ? new CompletionPhase.Synchronous(indicator)
            : new CompletionPhase.BgCalculation(indicator));

    final AtomicReference<LookupElement[]> data = indicator.startCompletion(initContext);

    if (!synchronous) {
      return;
    }

    if (freezeSemaphore.waitFor(2000)) {
      final LookupElement[] allItems = data.get();
      if (allItems != null
          && !indicator.isRunning()
          && !indicator
              .isCanceled()) { // the completion is really finished, now we may auto-insert or show
        // lookup
        completionFinished(
            initContext.getStartOffset(),
            initContext.getSelectionEndOffset(),
            indicator,
            allItems,
            hasModifiers);
        checkNotSync(indicator, allItems);
        return;
      }
    }

    CompletionServiceImpl.setCompletionPhase(new CompletionPhase.BgCalculation(indicator));
    indicator.showLookup();
  }