diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DocumentGuardedTextUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DocumentGuardedTextUtil.java index d5bd6310fcd3..d3eb04ed67fd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DocumentGuardedTextUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DocumentGuardedTextUtil.java @@ -28,7 +28,7 @@ public final class DocumentGuardedTextUtil { CharSequence textBefore = document.getImmutableCharSequence().subSequence(Math.max(0, startOffset - blockPrefix.length()), startOffset); - if (blockPrefix.toString().equals(textBefore.toString())) { + if (!blockPrefix.isEmpty() && blockPrefix.toString().equals(textBefore.toString())) { deleteString(document, startOffset - blockPrefix.length(), endOffset - blockPrefix.length()); } else { @@ -48,7 +48,7 @@ public final class DocumentGuardedTextUtil { } catch (ReadOnlyFragmentModificationException ex) { String blockPrefix = document.getImmutableCharSequence().subSequence(ex.getGuardedBlock().getStartOffset(), offset).toString(); - if (s.toString().endsWith(blockPrefix)) { + if (!blockPrefix.isEmpty() && s.toString().endsWith(blockPrefix)) { int newOffset = offset - blockPrefix.length(); String newString = blockPrefix + s.subSequence(0, s.length() - blockPrefix.length()); insertString(document, newOffset, newString); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java index ba7a2016572a..471f0ada2a2d 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java @@ -95,4 +95,66 @@ public class GuardBlockTest extends BasePlatformTestCase { myFixture.getEditor().getCaretModel().moveToOffset(offset - 1); assertNotNull(myFixture.completeBasic()); } + + public void testDocumentGuardedTextUtilDuplicateLine() { + String text = "a\n#%%\nc"; + // ^^^^^^^ <- guarded + // com.intellij.openapi.editor.actions.DocumentGuardedTextUtil.insertString handles this case and inserts "\na" after first "a" + myFixture.configureByText("x.txt", text); + RangeMarker guard = createGuard(1, 6); + + myFixture.performEditorAction(IdeActions.ACTION_EDITOR_DUPLICATE_LINES); + myFixture.checkResult("a\na\n#%%\nc"); + assertTrue(guard.isValid()); + assertEquals(3, guard.getStartOffset()); + assertEquals(8, guard.getEndOffset()); + } + + public void testDocumentGuardedTextUtilDeleteLine() { + String text = "a\nb\n#%%\nc"; + // ^^^^^^^ <- guarded + // com.intellij.openapi.editor.actions.DocumentGuardedTextUtil.deleteString handles this case and removes \n before caret + myFixture.configureByText("x.txt", text); + RangeMarker guard = createGuard(3, 8); + + myFixture.performEditorAction(IdeActions.ACTION_EDITOR_DELETE_LINE); + myFixture.checkResult("a\n#%%\nc"); + assertTrue(guard.isValid()); + assertEquals(1, guard.getStartOffset()); + assertEquals(6, guard.getEndOffset()); + } + + public void testDocumentGuardedTextUtilDuplicateLineWithGreedy() { + String text = "a\n#%%\nc"; + // ^^^^^^^ <- guarded + myFixture.configureByText("x.txt", text); + createGuard(1, 6).setGreedyToLeft(true); + + try { + myFixture.performEditorAction(IdeActions.ACTION_EDITOR_DUPLICATE_LINES); + } + catch (RuntimeException e) { + assertEquals("Unable to perform an action since it changes read-only fragments of the current document", e.getMessage()); + myFixture.checkResult(text); + return; + } + fail("must be read only at " + 1); + } + + public void testDocumentGuardedTextUtilDeleteLineWithGreedy() { + String text = "a\nb\n#%%\nc"; + // ^^^^^^^ <- guarded + myFixture.configureByText("x.txt", text); + createGuard(3, 8).setGreedyToLeft(true); + + try { + myFixture.performEditorAction(IdeActions.ACTION_EDITOR_DELETE_LINE); + } + catch (RuntimeException e) { + assertEquals("Unable to perform an action since it changes read-only fragments of the current document", e.getMessage()); + myFixture.checkResult(text); + return; + } + fail("must be read only at " + 3); + } }