@ApiStatus.Internal
    public static void scheduleAsyncCompletion(@NotNull Editor _editor,
                                               @NotNull CompletionType completionType,
                                               @Nullable Condition<? super PsiFile> condition,
                                               @NotNull Project project,
                                               @Nullable CompletionProgressIndicator prevIndicator) {
      LOG.trace("Schedule async completion");
      Editor topLevelEditor = InjectedLanguageEditorUtil.getTopLevelEditor(_editor);
      int offset = topLevelEditor.getCaretModel().getOffset();

      CommittingDocuments phase = getCompletionPhase(prevIndicator, topLevelEditor, _editor.getUserData(AUTO_POPUP_TYPED_EVENT));

      boolean autopopup = prevIndicator == null || prevIndicator.isAutopopupCompletion();

      ReadAction
        .nonBlocking(() -> {
          if (phase.isExpired()) {
            LOG.trace("Phase is expired");
            return null;
          }

          LOG.trace("Start non-blocking read action :: phase=" + phase.replaced);
          // retrieve the injected file from scratch since our typing might have destroyed the old one completely
          PsiFile topLevelFile = PsiDocumentManager.getInstance(project).getPsiFile(topLevelEditor.getDocument());
          Editor completionEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(topLevelEditor, topLevelFile, offset);
          PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(completionEditor.getDocument());
          if (file == null ||
              autopopup && shouldSkipAutoPopup(completionEditor, file) ||
              condition != null && !condition.value(file)) {
            LOG.trace("File is null or should skip auto popup or condition is not met :: file=" + file + ", condition=" + condition);
            return null;
          }

          loadContributorsOutsideEdt(completionEditor, file);

          return completionEditor;
        })
        .withDocumentsCommitted(project)
        .expireWith(phase)
        .finishOnUiThread(ModalityState.current(), completionEditor -> {
          LOG.trace("Finish on UI thread :: completionEditor=" + completionEditor);
          if (completionEditor != null && !phase.isExpired()) {
            LOG.trace("Starting completion phase :: completionEditor=" + completionEditor);
            phase.requestCompleted();
            int time = prevIndicator == null ? 0 : prevIndicator.getInvocationCount();
            CodeCompletionHandlerBase handler = CodeCompletionHandlerBase.createHandler(completionType, false, autopopup, false);
            handler.invokeCompletion(project, completionEditor, time, false);
          }
          else if (phase == CompletionServiceImpl.getCompletionPhase()) {
            LOG.trace("Setting NoCompletion phase :: completionEditor=" + completionEditor + ", isExpired=" + phase.isExpired());
            phase.decrementRequestCount();
            if (phase.isExpired()) {
              CompletionServiceImpl.setCompletionPhase(NoCompletion);
            }
          }
        })
        .submit(ourExecutor);
    }
@ApiStatus.Internal
    public static void scheduleAsyncCompletion(@NotNull Editor _editor,
                                               @NotNull CompletionType completionType,
                                               @Nullable Condition<? super PsiFile> condition,
                                               @NotNull Project project,
                                               @Nullable CompletionProgressIndicator prevIndicator)