mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-07-29 14:12:46 +07:00
API to execute typed handler postprocessing in a separate command
This allows to undo the formatting separately from the typing which has triggered the formatting (IDEA-126243)
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
class Foo {
|
||||
void m() {
|
||||
if (true) {
|
||||
System.out.println();
|
||||
}<caret>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class Foo {
|
||||
void m() {
|
||||
if (true) {
|
||||
System.out.println();
|
||||
}<caret>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class Foo {
|
||||
void m() {
|
||||
if (true) {
|
||||
System.out.println();
|
||||
<caret>
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,10 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.java.codeInsight;
|
||||
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
|
||||
@@ -29,6 +18,11 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class JavaTypingTest extends LightPlatformCodeInsightFixtureTestCase {
|
||||
public void testIndentRBrace() {
|
||||
doTest('}');
|
||||
doTestUndo();
|
||||
}
|
||||
|
||||
public void testMulticaretIndentLBrace() {
|
||||
doTest('{');
|
||||
}
|
||||
@@ -144,6 +138,12 @@ public class JavaTypingTest extends LightPlatformCodeInsightFixtureTestCase {
|
||||
myFixture.checkResultByFile(getTestName(true) + "_after.java");
|
||||
}
|
||||
|
||||
private void doTestUndo() {
|
||||
TextEditor fileEditor = TextEditorProvider.getInstance().getTextEditor(myFixture.getEditor());
|
||||
UndoManager.getInstance(getProject()).undo(fileEditor);
|
||||
myFixture.checkResultByFile(getTestName(true) + "_afterUndo.java");
|
||||
}
|
||||
|
||||
private void doMultiTypeTest(char c) {
|
||||
myFixture.configureByFile(getTestName(true) + "_before.java");
|
||||
List<Integer> whereToType = findWhereToType(myFixture.getEditor().getDocument().getImmutableCharSequence());
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.command;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -28,7 +14,7 @@ public abstract class CommandProcessorEx extends CommandProcessor {
|
||||
public abstract void leaveModal();
|
||||
|
||||
@Nullable
|
||||
public abstract Object startCommand(@NotNull Project project, @Nls String name, Object groupId, @NotNull UndoConfirmationPolicy undoConfirmationPolicy);
|
||||
public abstract Object startCommand(@Nullable Project project, @Nls String name, @Nullable Object groupId, @NotNull UndoConfirmationPolicy undoConfirmationPolicy);
|
||||
|
||||
public abstract void finishCommand(Project project, final Object command, Throwable throwable);
|
||||
public abstract void finishCommand(@Nullable Project project, @NotNull final Object command, @Nullable Throwable throwable);
|
||||
}
|
||||
|
||||
@@ -147,12 +147,12 @@ public class CoreCommandProcessor extends CommandProcessorEx {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object startCommand(@NotNull final Project project,
|
||||
public Object startCommand(@Nullable final Project project,
|
||||
@Nls final String name,
|
||||
final Object groupId,
|
||||
@Nullable final Object groupId,
|
||||
@NotNull final UndoConfirmationPolicy undoConfirmationPolicy) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
if (project.isDisposed()) return null;
|
||||
if (project != null && project.isDisposed()) return null;
|
||||
|
||||
if (CommandLog.LOG.isDebugEnabled()) {
|
||||
CommandLog.LOG.debug("startCommand: name = " + name + ", groupId = " + groupId);
|
||||
@@ -169,7 +169,7 @@ public class CoreCommandProcessor extends CommandProcessorEx {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishCommand(final Project project, final Object command, final Throwable throwable) {
|
||||
public void finishCommand(@Nullable final Project project, @NotNull final Object command, @Nullable Throwable throwable) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
CommandLog.LOG.assertTrue(myCurrentCommand != null, "no current command in progress");
|
||||
fireCommandFinished();
|
||||
|
||||
@@ -19,10 +19,13 @@ import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.actionSystem.ActionPlan;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
|
||||
import com.intellij.openapi.editor.actionSystem.TypedActionHandler;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
|
||||
import com.intellij.openapi.editor.impl.DefaultRawTypedHandler;
|
||||
import com.intellij.openapi.editor.impl.EditorActionManagerImpl;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypes;
|
||||
@@ -626,6 +629,9 @@ public class TypedHandler extends TypedActionHandlerBase {
|
||||
);
|
||||
}
|
||||
if (element.getNode() != null && isBrace) {
|
||||
DefaultRawTypedHandler handler = ((EditorActionManagerImpl) EditorActionManager.getInstance()).getDefaultRawTypedHandler();
|
||||
handler.beginUndoablePostProcessing(project);
|
||||
|
||||
final int finalLBraceOffset = lBraceOffset;
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
try{
|
||||
|
||||
+1
-62
@@ -1,26 +1,9 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.editor.actionSystem;
|
||||
|
||||
import com.intellij.codeInsight.hint.HintManager;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.UndoConfirmationPolicy;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -34,14 +17,12 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @see EditorActionManager#getTypedAction()
|
||||
*/
|
||||
public class TypedAction {
|
||||
@NotNull
|
||||
private TypedActionHandler myRawHandler;
|
||||
private TypedActionHandler myHandler;
|
||||
private boolean myHandlersLoaded;
|
||||
|
||||
public TypedAction() {
|
||||
myHandler = new Handler();
|
||||
myRawHandler = new DefaultRawHandler();
|
||||
}
|
||||
|
||||
private void ensureHandlersLoaded() {
|
||||
@@ -123,7 +104,6 @@ public class TypedAction {
|
||||
* @see #getHandler()
|
||||
* @see #setupHandler(TypedActionHandler)
|
||||
*/
|
||||
@NotNull
|
||||
public TypedActionHandler setupRawHandler(@NotNull TypedActionHandler handler) {
|
||||
TypedActionHandler tmp = myRawHandler;
|
||||
myRawHandler = handler;
|
||||
@@ -141,45 +121,4 @@ public class TypedAction {
|
||||
Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
FreezeLogger.getInstance().runUnderPerformanceMonitor(project, () -> myRawHandler.execute(editor, charTyped, dataContext));
|
||||
}
|
||||
|
||||
private class DefaultRawHandler implements TypedActionHandlerEx {
|
||||
@Override
|
||||
public void beforeExecute(@NotNull Editor editor, char c, @NotNull DataContext context, @NotNull ActionPlan plan) {
|
||||
if (editor.isViewer() || !editor.getDocument().isWritable()) return;
|
||||
|
||||
TypedActionHandler handler = getHandler();
|
||||
|
||||
if (handler instanceof TypedActionHandlerEx) {
|
||||
((TypedActionHandlerEx)handler).beforeExecute(editor, c, context, plan);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull final Editor editor, final char charTyped, @NotNull final DataContext dataContext) {
|
||||
CommandProcessor.getInstance().executeCommand(
|
||||
CommonDataKeys.PROJECT.getData(dataContext), () -> {
|
||||
if (!EditorModificationUtil.requestWriting(editor)) {
|
||||
HintManager.getInstance().showInformationHint(editor, "File is not writable");
|
||||
return;
|
||||
}
|
||||
ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(editor.getDocument(), editor.getProject()) {
|
||||
@Override
|
||||
public void run() {
|
||||
Document doc = editor.getDocument();
|
||||
doc.startGuardedBlockChecking();
|
||||
try {
|
||||
getHandler().execute(editor, charTyped, dataContext);
|
||||
}
|
||||
catch (ReadOnlyFragmentModificationException e) {
|
||||
EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e);
|
||||
}
|
||||
finally {
|
||||
doc.stopGuardedBlockChecking();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
"", editor.getDocument(), UndoConfirmationPolicy.DEFAULT, editor.getDocument());
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-16
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.command.impl;
|
||||
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
@@ -23,10 +9,11 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ExceptionUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class CommandProcessorImpl extends CoreCommandProcessor {
|
||||
@Override
|
||||
public void finishCommand(final Project project, final Object command, final Throwable throwable) {
|
||||
public void finishCommand(@Nullable Project project, @NotNull final Object command, @Nullable final Throwable throwable) {
|
||||
if (myCurrentCommand != command) return;
|
||||
final boolean failed;
|
||||
try {
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.codeInsight.hint.HintManager;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.CommandProcessorEx;
|
||||
import com.intellij.openapi.command.UndoConfirmationPolicy;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.actionSystem.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DefaultRawTypedHandler implements TypedActionHandlerEx {
|
||||
private final TypedAction myAction;
|
||||
private Object myCurrentCommandToken;
|
||||
|
||||
public DefaultRawTypedHandler(TypedAction action) {
|
||||
myAction = action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeExecute(@NotNull Editor editor, char c, @NotNull DataContext context, @NotNull ActionPlan plan) {
|
||||
if (editor.isViewer() || !editor.getDocument().isWritable()) return;
|
||||
|
||||
TypedActionHandler handler = myAction.getHandler();
|
||||
|
||||
if (handler instanceof TypedActionHandlerEx) {
|
||||
((TypedActionHandlerEx)handler).beforeExecute(editor, c, context, plan);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull final Editor editor, final char charTyped, @NotNull final DataContext dataContext) {
|
||||
CommandProcessorEx commandProcessorEx = (CommandProcessorEx)CommandProcessor.getInstance();
|
||||
Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
myCurrentCommandToken = commandProcessorEx.startCommand(project, "", editor.getDocument(), UndoConfirmationPolicy.DEFAULT);
|
||||
try {
|
||||
if (!EditorModificationUtil.requestWriting(editor)) {
|
||||
HintManager.getInstance().showInformationHint(editor, "File is not writable");
|
||||
return;
|
||||
}
|
||||
ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(editor.getDocument(), editor.getProject()) {
|
||||
@Override
|
||||
public void run() {
|
||||
Document doc = editor.getDocument();
|
||||
doc.startGuardedBlockChecking();
|
||||
try {
|
||||
myAction.getHandler().execute(editor, charTyped, dataContext);
|
||||
}
|
||||
catch (ReadOnlyFragmentModificationException e) {
|
||||
EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e);
|
||||
}
|
||||
finally {
|
||||
doc.stopGuardedBlockChecking();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
finally {
|
||||
commandProcessorEx.finishCommand(project, myCurrentCommandToken, null);
|
||||
myCurrentCommandToken = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void beginUndoablePostProcessing(Project project) {
|
||||
if (myCurrentCommandToken == null) {
|
||||
throw new IllegalStateException("Not in a typed action at this time");
|
||||
}
|
||||
CommandProcessorEx commandProcessorEx = (CommandProcessorEx)CommandProcessor.getInstance();
|
||||
commandProcessorEx.finishCommand(project, myCurrentCommandToken, null);
|
||||
myCurrentCommandToken = commandProcessorEx.startCommand(project, "", null, UndoConfirmationPolicy.DEFAULT);
|
||||
}
|
||||
}
|
||||
+8
-15
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
@@ -26,11 +12,14 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EditorActionManagerImpl extends EditorActionManager {
|
||||
private final TypedAction myTypedAction = new TypedAction();
|
||||
private final DefaultRawTypedHandler myDefaultRawTypedHandler;
|
||||
private ReadonlyFragmentModificationHandler myReadonlyFragmentsHandler = new DefaultReadOnlyFragmentModificationHandler();
|
||||
private final ActionManager myActionManager;
|
||||
|
||||
public EditorActionManagerImpl(ActionManager actionManager) {
|
||||
myActionManager = actionManager;
|
||||
myDefaultRawTypedHandler = new DefaultRawTypedHandler(myTypedAction);
|
||||
myTypedAction.setupRawHandler(myDefaultRawTypedHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,5 +75,9 @@ public class EditorActionManagerImpl extends EditorActionManager {
|
||||
EditorBundle.message("guarded.block.modification.attempt.error.title"));
|
||||
}
|
||||
}
|
||||
|
||||
public DefaultRawTypedHandler getDefaultRawTypedHandler() {
|
||||
return myDefaultRawTypedHandler;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user