From f1b217be4c7e352053fe6a40cdbcfecb111ba268 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 6 Nov 2018 18:12:10 +0300 Subject: [PATCH] fail fast when creating range marker with invalid offsets from virtual file in presence of cached document --- .../openapi/editor/impl/RangeMarkerImpl.java | 7 +++++- .../openapi/editor/impl/RangeMarkerTest.java | 23 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java index 9ce029401890..3dc0b523c717 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java @@ -54,7 +54,12 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx // constructor which creates marker without document and saves it in the virtual file directly. Can be cheaper than loading document. RangeMarkerImpl(@NotNull VirtualFile virtualFile, int start, int end, boolean register) { // unfortunately we don't know the exact document size until we load it - this(virtualFile, Integer.MAX_VALUE, start, end, register, false, false); + this(virtualFile, estimateDocumentLength(virtualFile), start, end, register, false, false); + } + + private static int estimateDocumentLength(@NotNull VirtualFile virtualFile) { + Document document = FileDocumentManager.getInstance().getCachedDocument(virtualFile); + return document == null ? Integer.MAX_VALUE : document.getTextLength(); } private RangeMarkerImpl(@NotNull Object documentOrFile, int documentTextLength, int start, diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java index ca156814357e..79ec24d40510 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java @@ -1112,22 +1112,39 @@ public class RangeMarkerTest extends LightPlatformTestCase { marker.dispose(); } - public void testLazyRangeMarkersWithInvalidOffset() { + public void testLazyRangeMarkersWithInvalidOffsetWhenNoDocumentCreatedMustInvalidateThemSelvesOnFirstOpportunity() { psiFile = createFile("x.txt", ""); LazyRangeMarkerFactoryImpl factory = (LazyRangeMarkerFactoryImpl)LazyRangeMarkerFactory.getInstance(getProject()); VirtualFile virtualFile = psiFile.getVirtualFile(); - Document document = FileDocumentManager.getInstance().getDocument(virtualFile); - assertEquals("", document.getText()); + assertEquals("", psiFile.getText()); RangeMarker marker = factory.createRangeMarker(virtualFile, 1 /* invalid offset */); + document = FileDocumentManager.getInstance().getDocument(virtualFile); document.replaceString(0, 0, "\n\t\n"); // used to throw AssertionError from RangeMarkerTree.updateMarkersOnChange assertEquals("\n\t\n", document.getText()); assertFalse(marker.isValid()); } + public void testLazyRangeMarkersWithInvalidOffsetWhenCachedDocumentAlreadyExistsMustRejectInvalidOffsetsRightAway() { + psiFile = createFile("x.txt", ""); + + LazyRangeMarkerFactoryImpl factory = (LazyRangeMarkerFactoryImpl)LazyRangeMarkerFactory.getInstance(getProject()); + VirtualFile virtualFile = psiFile.getVirtualFile(); + document = FileDocumentManager.getInstance().getDocument(virtualFile); + + assertEquals("", psiFile.getText()); + + try { + factory.createRangeMarker(virtualFile, 1 /* invalid offset */); + fail("Must fail fast"); + } + catch (IllegalArgumentException ignored) { + } + } + public void testNonGreedyMarkersGrowOnAppendingReplace() { Document doc = new DocumentImpl("foo"); RangeMarker marker = doc.createRangeMarker(0, 3);