diff --git a/platform/platform-tests/intellij.platform.tests.iml b/platform/platform-tests/intellij.platform.tests.iml index f43d45322aa0..327fd4e50c4e 100644 --- a/platform/platform-tests/intellij.platform.tests.iml +++ b/platform/platform-tests/intellij.platform.tests.iml @@ -68,5 +68,6 @@ + \ No newline at end of file diff --git a/platform/platform-tests/testData/codeInsight/editing/afterAutoWrapOnTypingAtLineEnd.txt b/platform/platform-tests/testData/codeInsight/editing/afterAutoWrapOnTypingAtLineEnd.txt new file mode 100644 index 000000000000..02b8c7a9e9d5 --- /dev/null +++ b/platform/platform-tests/testData/codeInsight/editing/afterAutoWrapOnTypingAtLineEnd.txt @@ -0,0 +1,2 @@ +a b c d e f g h i j k l +mnop \ No newline at end of file diff --git a/platform/platform-tests/testData/codeInsight/editing/afterAutoWrapsMerge.txt b/platform/platform-tests/testData/codeInsight/editing/afterAutoWrapsMerge.txt new file mode 100644 index 000000000000..a26acb6efe04 --- /dev/null +++ b/platform/platform-tests/testData/codeInsight/editing/afterAutoWrapsMerge.txt @@ -0,0 +1,2 @@ +a b 1 2 3 4 5 +c d e f g \ No newline at end of file diff --git a/platform/platform-tests/testData/codeInsight/editing/afterAvoidAutoWrapForIndentedLine.txt b/platform/platform-tests/testData/codeInsight/editing/afterAvoidAutoWrapForIndentedLine.txt new file mode 100644 index 000000000000..767fd459c70e --- /dev/null +++ b/platform/platform-tests/testData/codeInsight/editing/afterAvoidAutoWrapForIndentedLine.txt @@ -0,0 +1 @@ + abc12345 \ No newline at end of file diff --git a/platform/platform-tests/testData/codeInsight/editing/afterAvoidAutoWrapForNonIndentedLine.txt b/platform/platform-tests/testData/codeInsight/editing/afterAvoidAutoWrapForNonIndentedLine.txt new file mode 100644 index 000000000000..68fff2097535 --- /dev/null +++ b/platform/platform-tests/testData/codeInsight/editing/afterAvoidAutoWrapForNonIndentedLine.txt @@ -0,0 +1 @@ +abc12345 \ No newline at end of file diff --git a/platform/platform-tests/testData/codeInsight/editing/afterCopyPasteWithoutUnnecessaryIndent.txt b/platform/platform-tests/testData/codeInsight/editing/afterCopyPasteWithoutUnnecessaryIndent.txt new file mode 100644 index 000000000000..23575b3438ba --- /dev/null +++ b/platform/platform-tests/testData/codeInsight/editing/afterCopyPasteWithoutUnnecessaryIndent.txt @@ -0,0 +1,2 @@ +this is line 1 +this is line 2 diff --git a/platform/platform-tests/testData/codeInsight/editing/beforeAutoWrapOnTypingAtLineEnd.txt b/platform/platform-tests/testData/codeInsight/editing/beforeAutoWrapOnTypingAtLineEnd.txt new file mode 100644 index 000000000000..1b974354be76 --- /dev/null +++ b/platform/platform-tests/testData/codeInsight/editing/beforeAutoWrapOnTypingAtLineEnd.txt @@ -0,0 +1 @@ +a b c d e f g h i j k l mn \ No newline at end of file diff --git a/platform/platform-tests/testData/codeInsight/editing/beforeAutoWrapsMerge.txt b/platform/platform-tests/testData/codeInsight/editing/beforeAutoWrapsMerge.txt new file mode 100644 index 000000000000..0ebd6b4522ce --- /dev/null +++ b/platform/platform-tests/testData/codeInsight/editing/beforeAutoWrapsMerge.txt @@ -0,0 +1 @@ +a b c d e f g \ No newline at end of file diff --git a/platform/platform-tests/testData/codeInsight/editing/beforeAvoidAutoWrapForIndentedLine.txt b/platform/platform-tests/testData/codeInsight/editing/beforeAvoidAutoWrapForIndentedLine.txt new file mode 100644 index 000000000000..9eb866138b93 --- /dev/null +++ b/platform/platform-tests/testData/codeInsight/editing/beforeAvoidAutoWrapForIndentedLine.txt @@ -0,0 +1 @@ + abc \ No newline at end of file diff --git a/platform/platform-tests/testData/codeInsight/editing/beforeAvoidAutoWrapForNonIndentedLine.txt b/platform/platform-tests/testData/codeInsight/editing/beforeAvoidAutoWrapForNonIndentedLine.txt new file mode 100644 index 000000000000..a81fae9f04d8 --- /dev/null +++ b/platform/platform-tests/testData/codeInsight/editing/beforeAvoidAutoWrapForNonIndentedLine.txt @@ -0,0 +1 @@ +abc \ No newline at end of file diff --git a/platform/platform-tests/testData/codeInsight/editing/beforeCopyPasteWithoutUnnecessaryIndent.txt b/platform/platform-tests/testData/codeInsight/editing/beforeCopyPasteWithoutUnnecessaryIndent.txt new file mode 100644 index 000000000000..23575b3438ba --- /dev/null +++ b/platform/platform-tests/testData/codeInsight/editing/beforeCopyPasteWithoutUnnecessaryIndent.txt @@ -0,0 +1,2 @@ +this is line 1 +this is line 2 diff --git a/platform/platform-tests/testSrc/com/intellij/codeInsight/PlainTextEditingTest.java b/platform/platform-tests/testSrc/com/intellij/codeInsight/PlainTextEditingTest.java new file mode 100644 index 000000000000..9cbc35a0d99b --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/codeInsight/PlainTextEditingTest.java @@ -0,0 +1,310 @@ +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.codeInsight; + +import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.fileTypes.PlainTextFileType; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.testFramework.PlatformTestUtil; +import gnu.trove.TIntArrayList; +import org.jetbrains.annotations.NotNull; + +public class PlainTextEditingTest extends EditingTestBase { + + @NotNull + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getPlatformTestDataPath(); + } + + public void testAutoWrapOnTypingAtLineEnd() { + mySettings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = true; + mySettings.setDefaultRightMargin(27); + doTest(PlainTextFileType.INSTANCE, 'o', 'p'); + } + + public void testAutoWrapOnTyping_WrapsOnNewlyAddedSymbol_WhenTotalLengthExceedsRightMargin() { + boolean oldWrapValue = mySettings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN; + int oldMarginValue = mySettings.getDefaultRightMargin(); + mySettings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = true; + mySettings.setDefaultRightMargin(10); + + try { + init("qqqq aaaa", PlainTextFileType.INSTANCE); + type('b'); + checkResultByText("qqqq aaaab"); + type('c'); + checkResultByText("qqqq \naaaabc"); + } + finally { + mySettings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = oldWrapValue; + mySettings.setDefaultRightMargin(oldMarginValue); + } + } + + public void testAutoWrapsMerge() { + mySettings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = true; + mySettings.setDefaultRightMargin(14); + doTest(PlainTextFileType.INSTANCE, '1', ' ', '2', ' ', '3', ' ', '4', ' ', '5'); + } + + public void testAvoidAutoWrapForIndentedLine() { + mySettings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = true; + mySettings.setDefaultRightMargin(10); + doTest(PlainTextFileType.INSTANCE, '1', '2', '3', '4', '5'); + } + + public void testAvoidAutoWrapForNonIndentedLine() { + mySettings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = true; + mySettings.setDefaultRightMargin(5); + doTest(PlainTextFileType.INSTANCE, '1', '2', '3', '4', '5'); + } + + public void testCopyPasteWithoutUnnecessaryIndent() { + CodeInsightSettings settings = CodeInsightSettings.getInstance(); + int oldValue = settings.REFORMAT_ON_PASTE; + settings.REFORMAT_ON_PASTE = CodeInsightSettings.INDENT_BLOCK; + try { + doTest(PlainTextFileType.INSTANCE, () -> { + // Move caret to the non-zero column. + getEditor().getCaretModel().moveToOffset(3); + + // Select all text. + getEditor().getSelectionModel().setSelection(0, getEditor().getDocument().getTextLength()); + + // Perform 'copy-paste' action. Expecting to get the same file. + copy(); + paste(); + }); + } + finally { + settings.REFORMAT_ON_PASTE = oldValue; + } + } + + public void testCamelHumpsSelectionAndDigits() { + // Inspired by IDEA-63313 + + String text = + "class Test {\n" + + " String my1FieldWithLongName;\n" + + "}"; + + init(text, PlainTextFileType.INSTANCE); + + CaretModel caretModel = getEditor().getCaretModel(); + SelectionModel selectionModel = getEditor().getSelectionModel(); + + + TIntArrayList expectedBoundaries = new TIntArrayList(); + expectedBoundaries.add(text.indexOf("my")); + expectedBoundaries.add(text.indexOf("Field")); + expectedBoundaries.add(text.indexOf("With")); + expectedBoundaries.add(text.indexOf("Long")); + expectedBoundaries.add(text.indexOf("Name")); + + + boolean camelWords = getEditor().getSettings().isCamelWords(); + getEditor().getSettings().setCamelWords(true); + try { + int selectionStart; + int selectionEnd = text.indexOf("Name") + 1; + caretModel.moveToOffset(selectionEnd); + + // Check backward selection. + for (int i = expectedBoundaries.size() - 1; i >= 0; i--) { + selectionStart = expectedBoundaries.get(i); + moveCaretToPreviousWordWithSelection(); + assertEquals(selectionStart, caretModel.getOffset()); + assertEquals(selectionStart, selectionModel.getSelectionStart()); + assertEquals(selectionEnd, selectionModel.getSelectionEnd()); + } + + // Check forward selection. + selectionStart = text.indexOf("my") - 1; + selectionModel.removeSelection(); + caretModel.moveToOffset(selectionStart); + for (int i = 1; i < expectedBoundaries.size(); i++) { + selectionEnd = expectedBoundaries.get(i); + moveCaretToNextWordWithSelection(); + assertEquals(selectionEnd, caretModel.getOffset()); + assertEquals(selectionStart, selectionModel.getSelectionStart()); + assertEquals(selectionEnd, selectionModel.getSelectionEnd()); + } + } + finally { + getEditor().getSettings().setCamelWords(camelWords); + } + } + + public void testNewLineAboveCurrentAction() { + // Inspired by IDEA-69728 + String initial = + "class Test {\n" + + " public void test() {\n" + + " String s =\n" + + " \"test string\";\n" + + " }\n" + + "}"; + + init(initial, PlainTextFileType.INSTANCE); + executeAction("EditorStartNewLineBefore"); + + String expected = + "class Test {\n" + + " public void test() {\n" + + " String s =\n" + + "\n" + + " \"test string\";\n" + + " }\n" + + "}"; + + checkResultByText(expected); + } + + public void testHungryBackspace() { + String text = + " a b "; + init(text, PlainTextFileType.INSTANCE); + + executeAction("EditorHungryBackSpace"); + checkResultByText(" a b"); + + executeAction("EditorHungryBackSpace"); + checkResultByText(" a "); + + executeAction("EditorHungryBackSpace"); + checkResultByText(" a"); + + executeAction("EditorHungryBackSpace"); + checkResultByText(" "); + + executeAction("EditorHungryBackSpace"); + checkResultByText(""); + + executeAction("EditorHungryBackSpace"); + checkResultByText(""); + } + + + public void testMoveToPrevWordStartInsideStringLiteral() { + String text = "one \"two\""; + init(text, PlainTextFileType.INSTANCE); + executeAction("EditorPreviousWord"); + checkResultByText("one \"two\""); + } + + public void testPrefixAwareEditorWithTabOnNonFirstLine() { + init("", PlainTextFileType.INSTANCE); + ((EditorEx)getEditor()).setPrefixTextAndAttributes("prefix", new TextAttributes()); + type("first"); + type("\n"); + type("\tsecond"); + // Expected that no exception is thrown here + } + + public void testCutFromStickySelection() { + init("abcd", PlainTextFileType.INSTANCE); + EditorEx editor = (EditorEx)getEditor(); + CaretModel caretModel = editor.getCaretModel(); + caretModel.moveToOffset(1); + executeAction("EditorToggleStickySelection"); + caretModel.moveToOffset(3); + assertEquals("bc", editor.getSelectionModel().getSelectedText()); + + executeAction("EditorCut"); + checkResultByText("ad"); + } + + + public void testSurroundByQuotesAndStickySelection() { + init("abcdef", PlainTextFileType.INSTANCE); + EditorEx editorEx = (EditorEx)getEditor(); + editorEx.setStickySelection(true); + editorEx.getCaretModel().moveCaretRelatively(2, 0, false, false, false); + CodeInsightSettings settings = CodeInsightSettings.getInstance(); + boolean oldValue = settings.SURROUND_SELECTION_ON_QUOTE_TYPED; + settings.SURROUND_SELECTION_ON_QUOTE_TYPED = true; + try { + type('\''); + } + finally { + settings.SURROUND_SELECTION_ON_QUOTE_TYPED = oldValue; + } + checkResultByText("ab'cd'ef"); + } + + public void testStickySelectionIsCanceledByEscapeAction() { + init("abcde", PlainTextFileType.INSTANCE); + EditorEx editorEx = (EditorEx)getEditor(); + editorEx.setStickySelection(true); + editorEx.getCaretModel().moveCaretRelatively(2, 0, false, false, false); + SelectionModel selectionModel = editorEx.getSelectionModel(); + assertEquals(2, selectionModel.getSelectionStart()); + assertEquals(4, selectionModel.getSelectionEnd()); + executeAction(IdeActions.ACTION_EDITOR_ESCAPE); + assertFalse("sticky selection is not dropped after 'escape' action", selectionModel.hasSelection()); + assertFalse(editorEx.isStickySelection()); + } + + public void testDifferentHumpsMode() { + String text = "testVar1 testVar2"; + init(text, PlainTextFileType.INSTANCE); + + CaretModel caretModel = getEditor().getCaretModel(); + caretModel.moveToOffset(0); + Document document = getEditor().getDocument(); + EditorSettings settings = getEditor().getSettings(); + boolean camelModeToRestore = settings.isCamelWords(); + settings.setCamelWords(false); + + try { + executeAction("EditorNextWord"); + assertEquals(text.indexOf(" "), caretModel.getOffset()); + + executeAction("EditorPreviousWordInDifferentHumpsMode"); + assertEquals(text.indexOf("Var1"), caretModel.getOffset()); + + caretModel.moveToOffset(text.length()); + executeAction("EditorPreviousWord"); + assertEquals(text.indexOf("testVar2"), caretModel.getOffset()); + + executeAction("EditorNextWordInDifferentHumpsMode"); + assertEquals(text.indexOf("Var2"), caretModel.getOffset()); + + caretModel.moveToOffset(text.length()); + settings.setCamelWords(true); + executeAction("EditorPreviousWordInDifferentHumpsMode"); + assertEquals(text.indexOf("testVar2"), caretModel.getOffset()); + + executeAction("EditorNextWordInDifferentHumpsMode"); + assertEquals(text.length(), caretModel.getOffset()); + + settings.setCamelWords(false); + executeAction("EditorDeleteToWordStartInDifferentHumpsMode"); + assertEquals("testVar1 test", document.getText()); + + caretModel.moveToOffset(0); + executeAction("EditorDeleteToWordEndInDifferentHumpsMode"); + assertEquals("Var1 test", document.getText()); + } + finally { + settings.setCamelWords(camelModeToRestore); + } + } + + public void testCalculatingLongLinesPositionPerformanceInEditorWithNoTabs() { + final String longLine = StringUtil.repeatSymbol(' ', 1000000); + configureFromFileText("x.txt", longLine); + PlatformTestUtil.startPerformanceTest("calcOffset", 10, () -> { + for (int i = 0; i < 1000; i++) { + int off = getEditor().logicalPositionToOffset(new LogicalPosition(0, longLine.length() - 1)); + assertEquals(longLine.length() - 1, off); + int col = getEditor().offsetToLogicalPosition(longLine.length() - 1).column; + assertEquals(longLine.length() - 1, col); + } + }).assertTiming(); + } +}