static <T> void lookForInjectedFileInOtherThread(@NotNull Project project,
                                                   @NotNull Editor editor,
                                                   @NotNull BiFunction<? super PsiFile, ? super Editor, ? extends T> backgroundProcessor,
                                                   @NotNull TriConsumer<? super PsiFile, ? super Editor, ? super T> edtProcessor) {
    ThreadingAssertions.assertEventDispatchThread();
    assert !(editor instanceof EditorWindow) : editor;
    if (!isValidEditor(editor)) return;

    int offsetBefore = editor.getCaretModel().getOffset();

    ReadAction
      .nonBlocking(() -> {
        PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
        if (psiFile == null) return null;
        if (psiFile instanceof PsiCompiledFile) {
          psiFile = ((PsiCompiledFile)psiFile).getDecompiledPsiFile();
        }
        if (psiFile instanceof PsiBinaryFile && BinaryFileTypeDecompilers.getInstance().forFileType(psiFile.getFileType()) == null) {
          return null;
        }
        PsiFile newFile = getInjectedFileIfAny(offsetBefore, psiFile);
        Editor newEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, newFile);
        T result = backgroundProcessor.apply(newFile, newEditor);
        return Trinity.create(newFile, newEditor, result);
      })
      .withDocumentsCommitted(project)
      .expireWhen(() -> !isValidEditor(editor))
      .coalesceBy(BackgroundHighlightingUtil.class, editor)
      .finishOnUiThread(ModalityState.stateForComponent(editor.getComponent()), t -> {
        if (t == null) return;
        PsiFile foundFile = t.getFirst();
        if (foundFile == null) return;
        if (foundFile.isValid() && offsetBefore == editor.getCaretModel().getOffset()) {
          Editor newEditor = t.getSecond();
          T result = t.getThird();
          edtProcessor.accept(foundFile, newEditor, result);
        }
        else {
          lookForInjectedFileInOtherThread(project, editor, backgroundProcessor, edtProcessor);
        }
      })
      .submit(AppExecutorUtil.getAppExecutorService());
  }
static <T> void lookForInjectedFileInOtherThread(@NotNull Project project,
                                                   @NotNull Editor editor,
                                                   @NotNull BiFunction<? super PsiFile, ? super Editor, ? extends T> backgroundProcessor,
                                                   @NotNull TriConsumer<? super PsiFile, ? super Editor, ? super T> edtProcessor)