diff --git a/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java b/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java index a47a8ea74428..8e0f4694e5a4 100644 --- a/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java @@ -23,6 +23,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.registry.Registry; +import com.intellij.psi.impl.DebugUtil; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -48,6 +49,7 @@ public class TransactionGuardImpl extends TransactionGuard { private final Map myWriteSafeModalities = ContainerUtil.createConcurrentWeakMap(); private TransactionIdImpl myCurrentTransaction; private boolean myWritingAllowed; + private String myWritingAllowedTrace; public TransactionGuardImpl() { myWriteSafeModalities.put(ModalityState.NON_MODAL, true); @@ -58,7 +60,7 @@ public class TransactionGuardImpl extends TransactionGuard { ApplicationManager.getApplication().assertIsDispatchThread(); final boolean wasWritingAllowed = myWritingAllowed; - myWritingAllowed = true; + setWritingAllowed(true); myCurrentTransaction = new TransactionIdImpl(myCurrentTransaction); return new AccessToken() { @@ -70,13 +72,20 @@ public class TransactionGuardImpl extends TransactionGuard { pollQueueLater(); } - myWritingAllowed = wasWritingAllowed; + setWritingAllowed(wasWritingAllowed); myCurrentTransaction.myFinished = true; myCurrentTransaction = myCurrentTransaction.myParent; } }; } + private void setWritingAllowed(boolean value) { + myWritingAllowed = value; + if (value && ApplicationManager.getApplication().isUnitTestMode()) { + myWritingAllowedTrace = DebugUtil.currentStackTrace(); + } + } + @NotNull private Queue getQueue(@Nullable TransactionIdImpl transaction) { while (transaction != null && transaction.myFinished) { @@ -222,11 +231,11 @@ public class TransactionGuardImpl extends TransactionGuard { ApplicationManager.getApplication().assertIsDispatchThread(); final boolean prev = myWritingAllowed; - myWritingAllowed = allowWriting; + setWritingAllowed(allowWriting); return new AccessToken() { @Override public void finish() { - myWritingAllowed = prev; + setWritingAllowed(prev); } }; } @@ -289,11 +298,11 @@ public class TransactionGuardImpl extends TransactionGuard { public void run() { ApplicationManager.getApplication().assertIsDispatchThread(); final boolean prev = myWritingAllowed; - myWritingAllowed = true; + setWritingAllowed(true); try { runnable.run(); } finally { - myWritingAllowed = prev; + setWritingAllowed(prev); } } }; @@ -307,6 +316,7 @@ public class TransactionGuardImpl extends TransactionGuard { return Objects.toStringHelper(this) .add("currentTransaction", myCurrentTransaction) .add("writingAllowed", myWritingAllowed) + .add("writingAllowedTrace", myWritingAllowedTrace) .toString(); } @@ -335,7 +345,7 @@ public class TransactionGuardImpl extends TransactionGuard { @Override public String toString() { - return "Transaction " + myStartCounter; + return "Transaction " + myStartCounter + (myFinished ? "(finished)" : ""); } } } diff --git a/platform/platform-tests/testSrc/com/intellij/application/TransactionTest.groovy b/platform/platform-tests/testSrc/com/intellij/application/TransactionTest.groovy index c7e00091732e..61c383505f7f 100644 --- a/platform/platform-tests/testSrc/com/intellij/application/TransactionTest.groovy +++ b/platform/platform-tests/testSrc/com/intellij/application/TransactionTest.groovy @@ -89,7 +89,7 @@ class TransactionTest extends LightPlatformTestCase { Disposer.dispose(disposable) } if (!writeActionFailed) { - fail('write action should fail') + fail('write action should fail ' + guard.toString()) } }