From 367d5a99e58b33cf76267f2899fa4521f291c54a Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 16 Aug 2016 13:35:41 +0200 Subject: [PATCH] make actions not require transactions by default (fixes IDEA-146640 and numerous exceptions) --- .../openapi/application/TransactionGuard.java | 6 ++---- .../com/intellij/openapi/actionSystem/AnAction.java | 8 +++++++- .../codeInsight/actions/CodeInsightAction.java | 6 +++++- .../refactoring/actions/BaseRefactoringAction.java | 5 +++++ .../openapi/editor/actionSystem/EditorAction.java | 5 ----- .../src/com/intellij/openapi/ui/DialogWrapper.java | 12 +++--------- .../openapi/ui/impl/DialogWrapperPeerImpl.java | 5 ----- 7 files changed, 22 insertions(+), 25 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java b/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java index a94dfd7adfdc..8f183710f6fc 100644 --- a/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java +++ b/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java @@ -55,11 +55,9 @@ import org.jetbrains.annotations.Nullable; *

FAQ

* * Q: When should transactions be used? - * A: Whenever the code inside isn't prepared to model being modified from the outside world. Which is, almost always. AnAction-s - * are wrapped into transactions by default. It only makes sense to opt out (by overriding AnAction#startInTransaction), if your actions + * A: Whenever the code inside isn't prepared to model being modified from the outside world. Which is, almost always. Well known base AnAction + * classes that work with PSI are wrapped into transactions by default. It only makes sense to opt out (by overriding AnAction#startInTransaction), if your actions * don't modify the PSI/document/VFS model in any way, and can be invoked in a dialog that's shown from invokeLater. - * Example: editor actions in dialogs like "Enter Password", which doesn't care about model and can be requested to be shown from background threads - * in any modality state. *

* * Q: I've got "Write access is allowed from model transactions only" diff --git a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java index 0478f98236af..57d5ed9094c4 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java @@ -319,8 +319,14 @@ public abstract class AnAction implements PossiblyDumbAware { return this instanceof DumbAware; } + /** + * @return whether this action should be wrapped into a single transaction. PSI/VFS-related actions + * that can show progresses or modal dialogs should return true. The default value is false, to prevent + * transaction-related assertions from actions in harmless dialogs like "Enter password" shown inside invokeLater. + * @see com.intellij.openapi.application.TransactionGuard + */ public boolean startInTransaction() { - return true; + return false; } public interface TransparentUpdate { diff --git a/platform/lang-api/src/com/intellij/codeInsight/actions/CodeInsightAction.java b/platform/lang-api/src/com/intellij/codeInsight/actions/CodeInsightAction.java index d32873f26133..a17df5d15cf9 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/actions/CodeInsightAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/actions/CodeInsightAction.java @@ -23,7 +23,6 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.actionSystem.DocCommandGroupId; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiUtilBase; import org.jetbrains.annotations.NotNull; @@ -42,6 +41,11 @@ public abstract class CodeInsightAction extends AnAction { } } + @Override + public boolean startInTransaction() { + return true; + } + @Nullable protected Editor getEditor(@NotNull DataContext dataContext, @NotNull Project project, boolean forUpdate) { return CommonDataKeys.EDITOR.getData(dataContext); diff --git a/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java index b3624bcfe022..7fbad12a03b0 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java +++ b/platform/lang-impl/src/com/intellij/refactoring/actions/BaseRefactoringAction.java @@ -55,6 +55,11 @@ public abstract class BaseRefactoringAction extends AnAction { protected abstract boolean isEnabledOnElements(@NotNull PsiElement[] elements); + @Override + public boolean startInTransaction() { + return true; + } + protected boolean isAvailableOnElementInEditorAndFile(@NotNull PsiElement element, @NotNull Editor editor, @NotNull PsiFile file, @NotNull DataContext context) { return true; } diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java index c3d1fa5db9ca..a6a92aa498af 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java @@ -44,11 +44,6 @@ public abstract class EditorAction extends AnAction implements DumbAware { setEnabledInModalContext(true); } - @Override - public boolean startInTransaction() { - return false; - } - public final EditorActionHandler setupHandler(@NotNull EditorActionHandler newHandler) { ensureHandlersLoaded(); EditorActionHandler tmp = myHandler; diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index 898e9b7298bd..347182a0047c 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -747,7 +747,7 @@ public abstract class DialogWrapper { final char mnemonic = (char)eachInfo.getMnemonic(); JRootPane rootPane = getPeer().getRootPane(); if (rootPane != null) { - new NoTransactionAction() { + new DumbAwareAction() { @Override public void actionPerformed(AnActionEvent e) { final JBOptionButton buttonToActivate = eachInfo.getButton(); @@ -1275,7 +1275,7 @@ public abstract class DialogWrapper { myPeer.setContentPane(root); final CustomShortcutSet sc = new CustomShortcutSet(SHOW_OPTION_KEYSTROKE); - final AnAction toggleShowOptions = new NoTransactionAction() { + final AnAction toggleShowOptions = new DumbAwareAction() { @Override public void actionPerformed(@NotNull AnActionEvent e) { expandNextOptionButton(); @@ -1335,7 +1335,7 @@ public abstract class DialogWrapper { } private static void installEnterHook(JComponent root, Disposable disposable) { - new NoTransactionAction() { + new DumbAwareAction() { @Override public void actionPerformed(AnActionEvent e) { final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); @@ -2171,10 +2171,4 @@ public abstract class DialogWrapper { public enum DialogStyle {NO_STYLE, COMPACT} - private static abstract class NoTransactionAction extends DumbAwareAction { - @Override - public boolean startInTransaction() { - return false; - } - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java index e15b6351e343..66fc9d009eb8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java @@ -479,11 +479,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra private class AnCancelAction extends AnAction implements DumbAware { - @Override - public boolean startInTransaction() { - return false; - } - @Override public void update(AnActionEvent e) { Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();