public static <T, E extends Throwable> T computeAndWait(@NotNull ThrowableComputable<T, E> action, ModalityState modalityState) throws E {
    Application application = ApplicationManager.getApplication();
    if (application.isWriteIntentLockAcquired()) {
      return ApplicationManager.getApplication().runWriteAction(action);
    }

    if (SwingUtilities.isEventDispatchThread()) {
      return application.runWriteIntentReadAction(() -> application.runWriteAction(action));
    }

    if (application.isReadAccessAllowed()) {
      LOG.error("Must not start write action from within read action in the other thread - deadlock is coming");
    }

    AtomicReference<T> result = new AtomicReference<>();
    AtomicReference<Throwable> exception = new AtomicReference<>();
    WriteThread.invokeAndWait(() -> {
      try {
        result.set(compute(action));
      }
      catch (Throwable e) {
        exception.set(e);
      }
    }, modalityState);

    Throwable t = exception.get();
    if (t != null) {
      t.addSuppressed(new RuntimeException()); // preserve the calling thread stacktrace
      ExceptionUtil.rethrowUnchecked(t);
      //noinspection unchecked
      throw (E)t;
    }

    return result.get();
  }
public static <T, E extends Throwable> T computeAndWait(@NotNull ThrowableComputable<T, E> action, ModalityState modalityState)