public static boolean availableFor(@NotNull PsiFile psiFile, @NotNull Editor editor, int offset, @NotNull IntentionAction action) {
    if (!psiFile.isValid() || editor.isViewer()) return false;

    try {
      Project project = psiFile.getProject();
      action = IntentionActionDelegate.unwrap(action);

      if (action instanceof SuppressIntentionActionFromFix) {
        ThreeState shouldBeAppliedToInjectionHost = ((SuppressIntentionActionFromFix)action).isShouldBeAppliedToInjectionHost();
        if (editor instanceof EditorWindow && shouldBeAppliedToInjectionHost == ThreeState.YES) {
          return false;
        }
        if (!(editor instanceof EditorWindow) && shouldBeAppliedToInjectionHost == ThreeState.NO) {
          return false;
        }
      }

      if (action instanceof PsiElementBaseIntentionAction psiAction) {
        if (!psiAction.checkFile(psiFile)) {
          return false;
        }
        PsiElement leaf = psiFile.findElementAt(offset);
        if (leaf == null || !psiAction.isAvailable(project, editor, leaf)) {
          return false;
        }
      }
      else {
        if (ApplicationManager.getApplication().isDispatchThread()) {
          ModCommandAction modCommand = action.asModCommandAction();
          if (modCommand != null) {
            ActionContext actionContext = ActionContext.from(editor, psiFile);
            ThrowableComputable<Boolean, RuntimeException> computable =
              () -> ReadAction.nonBlocking(() -> modCommand.getPresentation(actionContext) != null)
                .expireWith(project)
                .executeSynchronously();
            return ProgressManager.getInstance().runProcessWithProgressSynchronously(
              computable, LangBundle.message("command.check.availability.for", modCommand.getFamilyName()), true, project);
          }
        }
        return action.isAvailable(project, editor, psiFile);
      }
    }
    catch (IndexNotReadyException e) {
      return false;
    }
    catch (IntentionPreviewUnsupportedOperationException e) {
      // check action availability can be invoked on a mock editor and may produce exceptions
      return false;
    }
    catch (ProcessCanceledException e) {
      throw e;
    }
    catch (Throwable e) {
      // avoid breaking highlighting when an exception is thrown from an intention
      LOG.error(e);
      return false;
    }
    return true;
  }
public static boolean availableFor(@NotNull PsiFile psiFile, @NotNull Editor editor, int offset, @NotNull IntentionAction action)