@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);
      }
    }
  }
  void duringCompletion(CompletionInitializationContext initContext) {
    if (isAutopopupCompletion()) {
      if (shouldFocusLookup(myParameters)) {
        myLookup.setFocused(true);
      } else if (FeatureUsageTracker.getInstance()
          .isToBeAdvertisedInLookup(
              CodeCompletionFeatures.EDITING_COMPLETION_CONTROL_ENTER, getProject())) {
        myLookup.addAdvertisement(
            "Press "
                + CompletionContributor.getActionShortcut(
                    IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_ALWAYS)
                + " to choose the first suggestion");
      }
      if (!myEditor.isOneLineMode()
          && FeatureUsageTracker.getInstance()
              .isToBeAdvertisedInLookup(
                  CodeCompletionFeatures.EDITING_COMPLETION_CONTROL_ARROWS, getProject())) {
        myLookup.addAdvertisement(
            CompletionContributor.getActionShortcut(IdeActions.ACTION_LOOKUP_DOWN)
                + " and "
                + CompletionContributor.getActionShortcut(IdeActions.ACTION_LOOKUP_UP)
                + " will move caret down and up in the editor");
      }
    }

    ProgressManager.checkCanceled();

    if (!initContext
        .getOffsetMap()
        .wasModified(CompletionInitializationContext.IDENTIFIER_END_OFFSET)) {
      try {
        final int selectionEndOffset = initContext.getSelectionEndOffset();
        final PsiReference reference = initContext.getFile().findReferenceAt(selectionEndOffset);
        if (reference != null) {
          initContext.setReplacementOffset(findReplacementOffset(selectionEndOffset, reference));
        }
      } catch (IndexNotReadyException ignored) {
      }
    }

    for (CompletionContributor contributor :
        CompletionContributor.forLanguage(initContext.getPositionLanguage())) {
      ProgressManager.checkCanceled();
      if (DumbService.getInstance(initContext.getProject()).isDumb()
          && !DumbService.isDumbAware(contributor)) {
        continue;
      }

      contributor.duringCompletion(initContext);
    }
  }
 private static OffsetMap translateOffsetMapToHost(
     CompletionInitializationContext initContext,
     PsiFile context,
     PsiFile hostFile,
     Editor hostEditor) {
   final InjectedLanguageManager injectedLanguageManager =
       InjectedLanguageManager.getInstance(hostFile.getProject());
   final OffsetMap hostMap = new OffsetMap(hostEditor.getDocument());
   final OffsetMap original = initContext.getOffsetMap();
   for (final OffsetKey key : original.getAllOffsets()) {
     hostMap.addOffset(
         key, injectedLanguageManager.injectedToHost(context, original.getOffset(key)));
   }
   return hostMap;
 }
  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();
  }