From 80357763e6f097e6cdbada55661d9013b5ad74e0 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 9 Feb 2017 20:06:28 +0300 Subject: [PATCH] IDEA-167094 Can't remove first char in user input --- .../execution/impl/ConsoleViewImpl.java | 12 ++-- .../execution/impl/ConsoleViewImplTest.java | 64 +++++++++++++++++-- .../testFramework/EditorTestUtil.java | 7 +- 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index 16179a4149d6..781978b1e408 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -597,7 +597,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo StringBuilder textToSend = new StringBuilder(); // compute text input from the console contents: // all range markers beginning from the caret offset backwards, marked as user input and not marked as already sent - for (RangeMarker marker = findTokenMarker(myEditor.getCaretModel().getOffset()); + for (RangeMarker marker = findTokenMarker(myEditor.getCaretModel().getOffset()-1); marker != null; marker = ((RangeMarkerImpl)marker).findRangeMarkerBefore()) { ConsoleViewContentType tokenType = getTokenType(marker); @@ -1127,11 +1127,12 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo } } + // finds range marker the [offset..offset+1) belongs to private RangeMarker findTokenMarker(int offset) { RangeMarker[] marker = new RangeMarker[1]; MarkupModelEx model = (MarkupModelEx)DocumentMarkupModel.forDocument(myEditor.getDocument(), getProject(), true); model.processRangeHighlightersOverlappingWith(offset, offset, m->{ - if (getTokenType(m) == null) return true; + if (getTokenType(m) == null || m.getStartOffset() > offset || offset + 1 > m.getEndOffset()) return true; marker[0] = m; return false; }); @@ -1166,8 +1167,8 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo flushDeferredText(); SelectionModel selectionModel = editor.getSelectionModel(); - int start = selectionModel.hasSelection() ? selectionModel.getSelectionStart() : editor.getCaretModel().getOffset(); - RangeMarker marker = findTokenMarker(start); + int lastOffset = selectionModel.hasSelection() ? selectionModel.getSelectionStart() : editor.getCaretModel().getOffset() - 1; + RangeMarker marker = findTokenMarker(lastOffset); if (getTokenType(marker) != ConsoleViewContentType.USER_INPUT) { print(text, ConsoleViewContentType.USER_INPUT); moveScrollRemoveSelection(editor, editor.getDocument().getTextLength()); @@ -1179,7 +1180,8 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo replaceUserText(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd(), textToUse); } else { - insertUserText(start, textToUse); + int typeOffset = selectionModel.hasSelection() ? selectionModel.getSelectionStart() : editor.getCaretModel().getOffset(); + insertUserText(typeOffset, textToUse); } } diff --git a/platform/platform-tests/testSrc/com/intellij/execution/impl/ConsoleViewImplTest.java b/platform/platform-tests/testSrc/com/intellij/execution/impl/ConsoleViewImplTest.java index 9cb34506861c..7d789744a4e1 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/impl/ConsoleViewImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/impl/ConsoleViewImplTest.java @@ -22,8 +22,10 @@ import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.ide.DataManager; import com.intellij.ide.ui.UISettings; -import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.ex.ActionUtil; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.actionSystem.EditorActionManager; import com.intellij.openapi.editor.actionSystem.TypedAction; @@ -31,17 +33,18 @@ import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.testFramework.LightPlatformCodeInsightTestCase; -import com.intellij.testFramework.LightPlatformTestCase; -import com.intellij.testFramework.PlatformTestUtil; -import com.intellij.testFramework.TestDataProvider; +import com.intellij.testFramework.*; import com.intellij.util.Alarm; import com.intellij.util.Consumer; import com.intellij.util.TimeoutUtil; import com.intellij.util.ui.UIUtil; +import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import java.io.ByteArrayOutputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -207,7 +210,7 @@ public class ConsoleViewImplTest extends LightPlatformTestCase { GlobalSearchScope.allScope(project), false, false); - console.getComponent(); + console.getComponent(); // initConsoleEditor() ProcessHandler processHandler = new NopProcessHandler(); processHandler.startNotify(); console.attachToProcess(processHandler); @@ -228,6 +231,21 @@ public class ConsoleViewImplTest extends LightPlatformTestCase { }).cpuBound().assertTiming()); } + /* + public void testPerformanceOfMergeableTokens() throws Exception { + withCycleConsole(1000, console -> + PlatformTestUtil.startPerformanceTest("console print", 1500, () -> { + console.clear(); + for (int i=0; i<10_000_000; i++) { + console.print("xxx\n", ConsoleViewContentType.NORMAL_OUTPUT); + UIUtil.dispatchAllInvocationEvents(); + } + LightPlatformCodeInsightTestCase.type('\n', console.getEditor(), getProject()); + console.waitAllRequests(); + }).cpuBound().assertTiming()); + } + */ + private static void withCycleConsole(int capacityKB, Consumer runnable) { boolean oldUse = UISettings.getInstance().OVERRIDE_CONSOLE_CYCLE_BUFFER_SIZE; int oldSize = UISettings.getInstance().CONSOLE_CYCLE_BUFFER_SIZE_KB; @@ -318,4 +336,38 @@ public class ConsoleViewImplTest extends LightPlatformTestCase { action.actionPerformed(editor, c, dataContext); } + + public void testBackspaceDoesDeleteTheLastTypedChar() throws Exception { + final ConsoleViewImpl console = myConsole; + final Editor editor = console.getEditor(); + console.print("xxxx", ConsoleViewContentType.NORMAL_OUTPUT); + console.print("a", ConsoleViewContentType.USER_INPUT); + console.print("b", ConsoleViewContentType.USER_INPUT); + console.print("c", ConsoleViewContentType.USER_INPUT); + console.print("d", ConsoleViewContentType.USER_INPUT); + console.flushDeferredText(); + assertEquals("xxxxabcd", editor.getDocument().getText()); + + backspace(console); + assertEquals("xxxxabc", editor.getDocument().getText()); + backspace(console); + assertEquals("xxxxab", editor.getDocument().getText()); + backspace(console); + assertEquals("xxxxa", editor.getDocument().getText()); + backspace(console); + assertEquals("xxxx", editor.getDocument().getText()); + } + + private static void backspace(ConsoleViewImpl consoleView) { + Editor editor = consoleView.getEditor(); + Set backShortcuts = new THashSet<>(Arrays.asList(ActionManager.getInstance().getAction(IdeActions.ACTION_EDITOR_BACKSPACE).getShortcutSet().getShortcuts())); + List actions = ActionUtil.getActions(consoleView.getEditor().getContentComponent()); + AnAction handler = actions.stream() + .filter(a -> new THashSet<>(Arrays.asList(a.getShortcutSet().getShortcuts())).equals(backShortcuts)) + .findFirst() + .get(); + CommandProcessor.getInstance().executeCommand(getProject(), + () -> EditorTestUtil.executeAction(editor, true, handler), + "", null, editor.getDocument()); + } } diff --git a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java index cc46819bc025..01c6504693ec 100644 --- a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java @@ -98,12 +98,17 @@ public class EditorTestUtil { ActionManagerEx actionManager = ActionManagerEx.getInstanceEx(); AnAction action = actionManager.getAction(actionId); assertNotNull(action); + executeAction(editor, assertActionIsEnabled, action); + } + + public static void executeAction(@NotNull Editor editor, boolean assertActionIsEnabled, @NotNull AnAction action) { AnActionEvent event = AnActionEvent.createFromAnAction(action, null, "", createEditorContext(editor)); action.beforeActionPerformedUpdate(event); if (!event.getPresentation().isEnabled()) { - assertFalse("Action " + actionId + " is disabled", assertActionIsEnabled); + assertFalse("Action " + action + " is disabled", assertActionIsEnabled); return; } + ActionManagerEx actionManager = ActionManagerEx.getInstanceEx(); actionManager.fireBeforeActionPerformed(action, event.getDataContext(), event); action.actionPerformed(event); actionManager.fireAfterActionPerformed(action, event.getDataContext(), event);