mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
transactions: minor javadoc updates, store transaction start stack trace for easier diagnostics
This commit is contained in:
@@ -53,11 +53,12 @@ import org.jetbrains.annotations.NotNull;
|
||||
* {@link #submitMergeableTransaction(TransactionKind, Runnable)} call.<p/>
|
||||
*
|
||||
* Q: I've got <b>"Nested transactions are not allowed"</b> exception, what do I do?<br/>
|
||||
* A: First, find the place in the stack where the outer transaction is started. Then, see if there is any Swing event pumping
|
||||
* in between two transactions (e.g. a dialog is shown). If not, one of two transactions is superfluous, remove it. If there
|
||||
* is event pumping, check if the client code (e.g. the one showing the dialog) is prepared to the nested model modifications
|
||||
* of the specified kinds. For example, refactoring dialogs might be prepared to {@link TransactionKind#TEXT_EDITING} kind
|
||||
* (for text field editing inside the dialogs) but not
|
||||
* A: First, identify the place in the stack where the outer transaction is started (the exception attachment should contain it).
|
||||
* Then, see if there is any Swing event pumping
|
||||
* in between two transactions (e.g. a dialog is shown). If not, one of the two involved transactions is superfluous, remove it. If there
|
||||
* is event pumping present, check if the client code (e.g. the one showing the dialog) is prepared to such nested model modifications.
|
||||
* For example, refactoring dialogs might be prepared to {@link TransactionKind#TEXT_EDITING} kind
|
||||
* (for text field editing inside the dialogs) but not to
|
||||
* other model changes, e.g. root changes. The outer transaction code might then specify which kinds it's prepared to (by using
|
||||
* {@link #acceptNestedTransactions(TransactionKind...)}), and the inner transaction code should have the very same transaction kind
|
||||
* (by using {@link #submitMergeableTransaction(TransactionKind, Runnable)} or {@link #startSynchronousTransaction(TransactionKind)}).
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.intellij.openapi.application;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Add this annotation to actions (AnAction inheritors) to make them run inside a transaction.
|
||||
* Add this annotation to actions (AnAction inheritors) to make them run inside a synchronous transaction.
|
||||
*
|
||||
* @see TransactionGuard
|
||||
* @since 146.*
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package com.intellij.openapi.application;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Attachment;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.psi.impl.DebugUtil;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -33,7 +35,7 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.application.TransactionGuardImpl");
|
||||
private final Queue<Runnable> myQueue = new LinkedBlockingQueue<Runnable>();
|
||||
private final Set<TransactionKind> myMergeableKinds = ContainerUtil.newHashSet();
|
||||
private boolean myInsideTransaction;
|
||||
private String myTransactionStartTrace;
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@@ -42,15 +44,16 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
if (kind != TransactionKind.NO_MERGE && myMergeableKinds.contains(kind)) {
|
||||
return AccessToken.EMPTY_ACCESS_TOKEN;
|
||||
}
|
||||
if (myInsideTransaction) {
|
||||
LOG.error("Nested transactions are not allowed");
|
||||
if (myTransactionStartTrace != null) {
|
||||
LOG.error("Nested transactions are not allowed, see FAQ in TransactionGuard class javadoc. Transaction start trace is in attachment.",
|
||||
new Attachment("trace.txt", myTransactionStartTrace));
|
||||
//throw new IllegalStateException("Nested transactions are not allowed");
|
||||
}
|
||||
myInsideTransaction = true;
|
||||
myTransactionStartTrace = DebugUtil.currentStackTrace();
|
||||
return new AccessToken() {
|
||||
@Override
|
||||
public void finish() {
|
||||
myInsideTransaction = false;
|
||||
myTransactionStartTrace = null;
|
||||
if (!myQueue.isEmpty()) {
|
||||
pollQueueLater();
|
||||
}
|
||||
@@ -64,7 +67,7 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
app.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myInsideTransaction) return;
|
||||
if (isInsideTransaction()) return;
|
||||
|
||||
Runnable next = myQueue.poll();
|
||||
if (next != null) {
|
||||
@@ -87,7 +90,7 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
@Override
|
||||
public boolean isInsideTransaction() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
return myInsideTransaction;
|
||||
return myTransactionStartTrace != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,7 +98,7 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myInsideTransaction || kind != TransactionKind.NO_MERGE && myMergeableKinds.contains(kind)) {
|
||||
if (!isInsideTransaction() || kind != TransactionKind.NO_MERGE && myMergeableKinds.contains(kind)) {
|
||||
runSyncTransaction(kind, transaction);
|
||||
}
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user