wrap writing editor actions into transactions

This commit is contained in:
peter
2016-03-16 13:03:13 +01:00
parent c40d71f3af
commit 86d8247ef9
12 changed files with 126 additions and 41 deletions
@@ -21,6 +21,8 @@ import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.TransactionKind;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -90,10 +92,9 @@ public class EndHandler extends EditorActionHandler {
// documents). Hence, we check that and don't finish processing in case we have such a situation. AtomicBoolean is used
// here just as a boolean value holder due to requirement to declare variable used from inner class as final.
final AtomicBoolean stopProcessing = new AtomicBoolean(true);
PsiDocumentManager.getInstance(project).commitAllDocuments();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
TransactionGuard.syncTransaction(TransactionKind.TEXT_EDITING, () -> {
PsiDocumentManager.getInstance(project).commitAllDocuments();
ApplicationManager.getApplication().runWriteAction(() -> {
CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
final String lineIndent = styleManager.getLineIndent(file, caretOffset);
if (lineIndent != null) {
@@ -115,16 +116,7 @@ public class EndHandler extends EditorActionHandler {
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
editor.getSelectionModel().removeSelection();
}
private int calcColumnNumber(final String lineIndent, final int tabSize) {
int result = 0;
for (char c : lineIndent.toCharArray()) {
if (c == ' ') result++;
if (c == '\t') result += tabSize;
}
return result;
}
});
});
if (stopProcessing.get()) {
return;
@@ -137,4 +129,14 @@ public class EndHandler extends EditorActionHandler {
myOriginalHandler.execute(editor, caret, dataContext);
}
}
private int calcColumnNumber(final String lineIndent, final int tabSize) {
int result = 0;
for (char c : lineIndent.toCharArray()) {
if (c == ' ') result++;
if (c == '\t') result += tabSize;
}
return result;
}
}
@@ -20,8 +20,12 @@ import com.intellij.lang.*;
import com.intellij.lang.documentation.CodeDocumentationProvider;
import com.intellij.lang.documentation.CompositeDocumentationProvider;
import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.TransactionKind;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
@@ -56,6 +60,12 @@ public class FixDocCommentAction extends EditorAction {
}
private static final class MyHandler extends EditorActionHandler {
@Override
public AccessToken startTransaction(@NotNull Editor editor) {
return TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.TEXT_EDITING);
}
@Override
public void execute(Editor editor, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
@@ -21,7 +21,10 @@ import com.intellij.ide.PasteProvider;
import com.intellij.lang.LanguageFormatting;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.TransactionKind;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -71,6 +74,11 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser
myOriginalHandler = originalAction;
}
@Override
public AccessToken startTransaction(@NotNull Editor editor) {
return TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.TEXT_EDITING);
}
@Override
public void doExecute(final Editor editor, Caret caret, final DataContext dataContext) {
assert caret == null : "Invocation of 'paste' operation for specific caret is not supported";
@@ -20,9 +20,13 @@ import com.intellij.codeInsight.completion.CompletionProgressIndicator;
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.TransactionKind;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import org.jetbrains.annotations.NotNull;
public class BackspaceHandler extends EditorActionHandler {
private final EditorActionHandler myOriginalHandler;
@@ -31,6 +35,11 @@ public class BackspaceHandler extends EditorActionHandler {
myOriginalHandler = originalHandler;
}
@Override
public AccessToken startTransaction(@NotNull Editor editor) {
return TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.TEXT_EDITING);
}
@Override
public void doExecute(final Editor editor, Caret caret, final DataContext dataContext){
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
@@ -26,11 +26,12 @@ import com.intellij.codeInsight.template.impl.*;
import com.intellij.codeInsight.template.impl.editorActions.ExpandLiveTemplateCustomAction;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.TransactionKind;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.util.containers.ContainerUtil;
@@ -52,6 +53,11 @@ public abstract class ChooseItemAction extends EditorAction {
this.finishingChar = finishingChar;
}
@Override
public AccessToken startTransaction(@NotNull Editor editor) {
return TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.TEXT_EDITING);
}
@Override
public void execute(@NotNull final Editor editor, final DataContext dataContext) {
final LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
@@ -28,6 +28,9 @@ import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.TransactionKind;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
@@ -43,6 +46,12 @@ public class NextVariableAction extends EditorAction {
}
private static class Handler extends EditorActionHandler {
@Override
public AccessToken startTransaction(@NotNull Editor editor) {
return TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.TEXT_EDITING);
}
@Override
protected void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
@@ -28,6 +28,9 @@ import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.TransactionKind;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
@@ -43,6 +46,12 @@ public class PreviousVariableAction extends EditorAction {
}
private static class Handler extends EditorActionHandler {
@Override
public AccessToken startTransaction(@NotNull Editor editor) {
return TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.TEXT_EDITING);
}
@Override
protected void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
final TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
@@ -16,13 +16,15 @@
package com.intellij.codeInsight.template.impl.editorActions;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.TransactionKind;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
public class EscapeHandler extends EditorActionHandler {
private final EditorActionHandler myOriginalHandler;
@@ -37,7 +39,7 @@ public class EscapeHandler extends EditorActionHandler {
final TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
if (templateState != null && !templateState.isFinished()) {
CommandProcessor.getInstance().setCurrentCommandName(CodeInsightBundle.message("finish.template.command"));
templateState.gotoEnd(true);
TransactionGuard.syncTransaction(TransactionKind.TEXT_EDITING, () -> templateState.gotoEnd(true));
return;
}
}
@@ -16,6 +16,7 @@
package com.intellij.openapi.editor.actionSystem;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.editor.Editor;
@@ -92,26 +93,23 @@ public abstract class EditorAction extends AnAction implements DumbAware {
if (editor == null) return;
final EditorActionHandler handler = getHandler();
Runnable command = new Runnable() {
@Override
public void run() {
handler.execute(editor, null, getProjectAwareDataContext(editor, dataContext));
Runnable command = () -> handler.execute(editor, null, getProjectAwareDataContext(editor, dataContext));
try (AccessToken ignored = handler.startTransaction(editor)) {
if (!handler.executeInCommand(editor, dataContext)) {
command.run();
return;
}
};
if (!handler.executeInCommand(editor, dataContext)) {
command.run();
return;
String commandName = getTemplatePresentation().getText();
if (commandName == null) commandName = "";
CommandProcessor.getInstance().executeCommand(editor.getProject(),
command,
commandName,
handler.getCommandGroupId(editor),
UndoConfirmationPolicy.DEFAULT,
editor.getDocument());
}
String commandName = getTemplatePresentation().getText();
if (commandName == null) commandName = "";
CommandProcessor.getInstance().executeCommand(editor.getProject(),
command,
commandName,
handler.getCommandGroupId(editor),
UndoConfirmationPolicy.DEFAULT,
editor.getDocument());
}
public void update(Editor editor, Presentation presentation, DataContext dataContext) {
@@ -18,6 +18,9 @@ package com.intellij.openapi.editor.actionSystem;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.TransactionKind;
import com.intellij.openapi.application.WrapInTransaction;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.CaretAction;
import com.intellij.openapi.editor.Editor;
@@ -180,6 +183,15 @@ public abstract class EditorActionHandler {
return true;
}
/**
* @return the transaction access token that this action should be executed inside, or null if no transaction is required.
* @see com.intellij.openapi.application.TransactionGuard#startSynchronousTransaction(TransactionKind)
*/
@Nullable
public AccessToken startTransaction(@NotNull Editor editor) {
return null;
}
public boolean runForAllCarets() {
return myRunForEachCaret;
}
@@ -17,11 +17,15 @@ package com.intellij.openapi.editor.actionSystem;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.TransactionKind;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.textarea.TextComponentEditor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -38,6 +42,12 @@ public abstract class EditorWriteActionHandler extends EditorActionHandler {
super(runForEachCaret);
}
@Override
public AccessToken startTransaction(@NotNull Editor editor) {
if (editor instanceof TextComponentEditor) return null;
return TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.TEXT_EDITING);
}
@Override
public void doExecute(final Editor editor, @Nullable final Caret caret, final DataContext dataContext) {
if (editor.isViewer()) return;
@@ -16,13 +16,17 @@
package com.intellij.openapi.editor.actions;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.TransactionKind;
import com.intellij.openapi.editor.DocumentRunnable;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.textarea.TextComponentEditor;
import com.intellij.openapi.ide.KillRingTransferable;
import org.jetbrains.annotations.NotNull;
/**
* Stands for emacs <a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/Other-Kill-Commands.html">kill-ring-save</a> command.
@@ -48,6 +52,12 @@ public class KillRingSaveAction extends TextComponentEditorAction {
myRemove = remove;
}
@Override
public AccessToken startTransaction(@NotNull Editor editor) {
if (editor instanceof TextComponentEditor || !myRemove) return null;
return TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.TEXT_EDITING);
}
@Override
public void execute(final Editor editor, final DataContext dataContext) {
SelectionModel selectionModel = editor.getSelectionModel();