diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index 9116bbd62b98..449aa62aa208 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -2,10 +2,12 @@ // Each line contains plugin ID and list of versions that are broken. // If plugin name or version contains a space you can quote it like in command line. -NodeJS 134.680 134.31 134.307 134.262 134.198 134.125 +NodeJS 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 com.jetbrains.php 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12 com.jetbrains.lang.ejs 131.17 131.12 com.jetbrains.twig 133.51 130.1639 +org.jetbrains.plugins.ruby 6.0.0.20140207 +Pythonid 3.1 Karma 134.686 134.31 org.intellij.scala 0.32.512 org.jetbrains.kannotator 0.2.420 diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-after.txt new file mode 100644 index 000000000000..7a9d37447149 --- /dev/null +++ b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-after.txt @@ -0,0 +1,3 @@ +some text +some other text +another line of text \ No newline at end of file diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-before.txt new file mode 100644 index 000000000000..caad4cba166c --- /dev/null +++ b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-before.txt @@ -0,0 +1,3 @@ +some text +some other text +another line of text \ No newline at end of file diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-after.txt new file mode 100644 index 000000000000..a24e0341fed4 --- /dev/null +++ b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-after.txt @@ -0,0 +1,3 @@ +some text +some other text +another line of text \ No newline at end of file diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-before.txt new file mode 100644 index 000000000000..3758a93e2c92 --- /dev/null +++ b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-before.txt @@ -0,0 +1,3 @@ +some text +some other text +another line of text \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretStateRestoreTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretStateRestoreTest.java new file mode 100644 index 000000000000..d915753db54c --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretStateRestoreTest.java @@ -0,0 +1,66 @@ +/* + * 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. + */ +package com.intellij.openapi.editor; + +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.impl.DocumentImpl; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.HeavyFileEditorManagerTestCase; +import com.intellij.openapi.fileEditor.TextEditor; +import com.intellij.openapi.fileTypes.PlainTextFileType; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.EditorTestUtil; +import org.jetbrains.annotations.NotNull; + +public class EditorMultiCaretStateRestoreTest extends HeavyFileEditorManagerTestCase { + public void testRestoreState() throws Exception { + EditorTestUtil.enableMultipleCarets(); + try { + String text = "some text\n" + + "some other text\n" + + "another line"; + PsiFile psiFile = myFixture.configureByText(PlainTextFileType.INSTANCE, text); + VirtualFile virtualFile = psiFile.getVirtualFile(); + assertNotNull(virtualFile); + myManager.openFile(virtualFile, false); + myManager.closeAllFiles(); + FileEditor[] fileEditors = myManager.openFile(virtualFile, false); + assertNotNull(fileEditors); + assertEquals(1, fileEditors.length); + Editor editor = ((TextEditor)fileEditors[0]).getEditor(); + + verifyEditorState(editor, text); + } + finally { + EditorTestUtil.disableMultipleCarets(); + } + } + + private static void verifyEditorState(Editor editor, String textWithMarkup) { + final Document document = new DocumentImpl(textWithMarkup); + EditorTestUtil.CaretsState caretAndSelectionState = new WriteCommandAction(null) { + @Override + protected void run(@NotNull Result result) throws Throwable { + result.setResult(EditorTestUtil.extractCaretAndSelectionMarkers(document)); + } + }.execute().getResultObject(); + assertEquals(document.getCharsSequence().toString(), editor.getDocument().getText()); + EditorTestUtil.verifyCaretAndSelectionState(editor, caretAndSelectionState); + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretTest.java index e93fd8c7882a..7dc178471b92 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretTest.java @@ -17,6 +17,11 @@ package com.intellij.openapi.editor; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.impl.AbstractEditorTest; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.OpenFileDescriptor; +import com.intellij.openapi.fileEditor.impl.EditorHistoryManager; +import com.intellij.openapi.project.ex.ProjectManagerEx; +import com.intellij.openapi.project.impl.ProjectManagerImpl; import com.intellij.testFramework.EditorTestUtil; import com.intellij.testFramework.TestFileType; import com.intellij.testFramework.fixtures.EditorScrollingFixture; @@ -142,4 +147,78 @@ public class EditorMultiCaretTest extends AbstractEditorTest { "long line\n" + "line"); } + + public void testTyping() throws Exception { + init("some text\n" + + "some other text\n" + + "another line", + TestFileType.TEXT); + type('A'); + checkResultByText("someA textA\n" + + "some A A\n" + + "A line"); + } + + public void testCopyPaste() throws Exception { + init("one two \n" + + "three four ", + TestFileType.TEXT); + executeAction("EditorCopy"); + executeAction("EditorLineEnd"); + executeAction("EditorPaste"); + checkResultByText("one twoone \n" + + "three fourthree "); + } + + public void testCutAndPaste() throws Exception { + init("one two \n" + + "three four ", + TestFileType.TEXT); + executeAction("EditorCut"); + executeAction("EditorLineEnd"); + executeAction("EditorPaste"); + checkResultByText(" twoone \n" + + " fourthree "); + } + + public void testPasteSingleItem() throws Exception { + init("one two \n" + + "three four ", + TestFileType.TEXT); + executeAction("EditorCopy"); + executeAction("EditorCloneCaretBelow"); + executeAction("EditorLineEnd"); + executeAction("EditorPaste"); + checkResultByText("one twoone \n" + + "three fourone "); + } + + public void testCutAndPasteMultiline() throws Exception { + init("one two \n" + + "three four \n" + + "five six \n" + + "seven eight", + TestFileType.TEXT); + executeAction("EditorCut"); + executeAction("EditorLineEnd"); + executeAction("EditorPaste"); + checkResultByText("one fourtwo \n" + + "three \n" + + "five eightsix \n" + + "seven"); + } + + public void testStateStoreAndLoad() throws Exception { + init("some text\n" + + "some other text\n" + + "another line", + TestFileType.TEXT); + EditorHistoryManager.getInstance(ourProject).projectOpened(); + FileEditorManager fileEditorManager = FileEditorManager.getInstance(ourProject); + fileEditorManager.closeFile(myVFile); + myEditor = fileEditorManager.openTextEditor(new OpenFileDescriptor(getProject(), myVFile, 0), false); + checkResultByText("some text\n" + + "some other text\n" + + "another line"); + } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretUndoRedoTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretUndoRedoTest.java new file mode 100644 index 000000000000..8bafc3e0b977 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretUndoRedoTest.java @@ -0,0 +1,118 @@ +/* + * 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. + */ +package com.intellij.openapi.editor; + +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.impl.CurrentEditorProvider; +import com.intellij.openapi.command.impl.UndoManagerImpl; +import com.intellij.openapi.command.undo.UndoManager; +import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; +import com.intellij.openapi.editor.impl.AbstractEditorTest; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.TextEditor; +import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider; +import com.intellij.testFramework.EditorTestUtil; +import com.intellij.testFramework.TestFileType; +import com.intellij.testFramework.fixtures.EditorScrollingFixture; +import org.jetbrains.annotations.NotNull; + +public class EditorMultiCaretUndoRedoTest extends AbstractEditorTest { + private CurrentEditorProvider mySavedCurrentEditorProvider; + + public void setUp() throws Exception { + super.setUp(); + EditorTestUtil.enableMultipleCarets(); + mySavedCurrentEditorProvider = getUndoManager().getEditorProvider(); + } + + public void tearDown() throws Exception { + getUndoManager().setEditorProvider(mySavedCurrentEditorProvider); + EditorTestUtil.disableMultipleCarets(); + super.tearDown(); + } + + @Override + // disabling execution of tests in command + protected void runTest() throws Throwable { + new WriteAction() { + @Override + protected void run(@NotNull Result result) throws Throwable { + doRunTest(); + } + }.execute(); + } + + public void testUndoRedo() throws Exception { + init("some text\n" + + "some other text\n" + + "another line", + TestFileType.TEXT); + setupEditorProvider(); + type('A'); + executeAction("EditorDelete"); + mouse().clickAt(0, 1); + undo(); + checkResult("someAtextAsome AAAline"); + undo(); + checkResult("someA textA\n" + + "some A A\n" + + "A line"); + undo(); + checkResult("some text\n" + + "some other text\n" + + "another line"); + redo(); + checkResult("someA textA\n" + + "some A A\n" + + "A line"); + } + + private void checkResult(final String text) { + CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { + @Override + public void run() { + checkResultByText(text); + } + }); + } + + private static void undo() { + getUndoManager().undo(getTextEditor()); + } + + private static void redo() { + getUndoManager().redo(getTextEditor()); + } + + private static UndoManagerImpl getUndoManager() { + return (UndoManagerImpl) UndoManager.getInstance(ourProject); + } + + private static TextEditor getTextEditor() { + return TextEditorProvider.getInstance().getTextEditor(myEditor); + } + + private static void setupEditorProvider() { + getUndoManager().setEditorProvider(new CurrentEditorProvider() { + @Override + public FileEditor getCurrentEditor() { + return getTextEditor(); + } + }); + } +} diff --git a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java index a80ab7c1fbd3..b80b2350b8f5 100644 --- a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java @@ -17,9 +17,7 @@ package com.intellij.testFramework; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.actionSystem.EditorActionManager; import com.intellij.openapi.editor.actionSystem.TypedAction; @@ -39,6 +37,9 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + /** * User: Maxim.Mossienko * Date: 15.03.2010 @@ -284,6 +285,35 @@ public class EditorTestUtil { return result; } + public static void verifyCaretAndSelectionState(Editor editor, CaretsState caretState) { + CaretModel caretModel = editor.getCaretModel(); + List allCarets = new ArrayList(caretModel.getAllCarets()); + assertEquals("Unexpected number of carets", caretState.carets.size(), allCarets.size()); + for (int i = 0; i < caretState.carets.size(); i++) { + String caretDescription = caretState.carets.size() == 1 ? "" : "caret " + (i + 1) + "/" + caretState.carets.size() + " "; + com.intellij.openapi.editor.Caret currentCaret = allCarets.get(i); + LogicalPosition actualCaretPosition = currentCaret.getLogicalPosition(); + LogicalPosition actualSelectionStart = editor.offsetToLogicalPosition(currentCaret.getSelectionStart()); + LogicalPosition actualSelectionEnd = editor.offsetToLogicalPosition(currentCaret.getSelectionEnd()); + EditorTestUtil.Caret expected = caretState.carets.get(i); + if (expected.offset != null) { + LogicalPosition expectedCaretPosition = editor.offsetToLogicalPosition(expected.offset); + assertEquals(caretDescription + "unexpected caret position", expectedCaretPosition, actualCaretPosition); + } + if (expected.selection != null) { + LogicalPosition expectedSelectionStart = editor.offsetToLogicalPosition(expected.selection.getStartOffset()); + LogicalPosition expectedSelectionEnd = editor.offsetToLogicalPosition(expected.selection.getEndOffset()); + + assertEquals(caretDescription + "unexpected selection start", expectedSelectionStart, actualSelectionStart); + assertEquals(caretDescription + "unexpected selection end", expectedSelectionEnd, actualSelectionEnd); + } + else { + assertFalse(caretDescription + "should has no selection, but was: (" + actualSelectionStart + ", " + actualSelectionEnd + ")", + currentCaret.hasSelection()); + } + } + } + public static void enableMultipleCarets() { Registry.get("editor.allow.multiple.carets").setValue(true); } diff --git a/platform/util/src/com/intellij/util/containers/OrderedSet.java b/platform/util/src/com/intellij/util/containers/OrderedSet.java index 25682ab868cd..9900eb92e800 100644 --- a/platform/util/src/com/intellij/util/containers/OrderedSet.java +++ b/platform/util/src/com/intellij/util/containers/OrderedSet.java @@ -15,13 +15,11 @@ */ package com.intellij.util.containers; +import com.intellij.util.IncorrectOperationException; import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Collection; -import java.util.RandomAccess; -import java.util.Set; +import java.util.*; // have to extend ArrayList because otherwise the spliterator() methods declared in Set and List are in conflict public class OrderedSet extends ArrayList implements Set, RandomAccess { @@ -40,6 +38,33 @@ public class OrderedSet extends ArrayList implements Set, RandomAccess myHashSet = new OpenTHashSet(capacity, hashingStrategy); } + @Override + public boolean removeAll(@NotNull Collection c) { + boolean removed = false; + for (Object o : c) { + removed |= remove(o); + } + return removed; + } + + @Override + public boolean retainAll(@NotNull Collection c) { + boolean removed = false; + for (int i = size() - 1; i >= 0; i--) { + Object o = get(i); + if (!c.contains(o)) { + removed |= remove(o); + } + } + return removed; + } + + @NotNull + @Override + public List subList(int fromIndex, int toIndex) { + throw new IncorrectOperationException(); + } + @Override public boolean contains(Object o) { return myHashSet.contains(o);