From 6fb36472456e216be22650214d95269e75d18fa8 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Mon, 1 Feb 2016 15:54:33 +0300 Subject: [PATCH] IDEA-150943 Strange code folding in a method with lambda --- .../folding/JavaFoldingTest.groovy | 36 +++++++++++++++++-- .../impl/UpdateFoldRegionsOperation.java | 9 +++-- .../injected/editor/FoldingModelWindow.java | 11 +++++- .../openapi/editor/ex/FoldingModelEx.java | 6 +++- .../openapi/editor/impl/FoldingModelImpl.java | 16 ++++++++- 5 files changed, 71 insertions(+), 7 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy index f69deedd9c55..36389acf1e86 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -24,6 +24,7 @@ import com.intellij.openapi.application.ex.PathManagerEx import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.editor.FoldRegion import com.intellij.openapi.editor.ex.DocumentEx +import com.intellij.openapi.editor.ex.EditorEx import com.intellij.openapi.editor.ex.FoldingModelEx import com.intellij.openapi.editor.impl.FoldingModelImpl import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider @@ -36,7 +37,6 @@ import com.intellij.psi.search.GlobalSearchScope import com.intellij.testFramework.EditorTestUtil import com.intellij.testFramework.LightProjectDescriptor import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase - /** * @author Denis Zhdanov * @since 1/17/11 1:00 PM @@ -1185,6 +1185,38 @@ class Foo { myFixture.doHighlighting() assertTopLevelFoldRegionsState "[FoldRegion +(57:144), placeholder='(Runnable) () → { ', FoldRegion +(165:189), placeholder=' }']" } + + public void "test folding update after external change"() { + configure """\ +class Foo { + void m1() { + System.out.println(1); + System.out.println(2); + } + + void m2() { + System.out.println(3); + System.out.println(4); + } +} +""" + myFixture.performEditorAction(IdeActions.ACTION_COLLAPSE_ALL_REGIONS) + assertTopLevelFoldRegionsState "[FoldRegion +(24:83), placeholder='{...}', FoldRegion +(99:158), placeholder='{...}']" + + def virtualFile = ((EditorEx)myFixture.getEditor()).virtualFile + myFixture.saveText(virtualFile, """\ +class Foo { + void m1() { + System.out.println(1); + System.out.println(4); + } +} +""") + virtualFile.refresh(false, false) + + myFixture.doHighlighting() + assertTopLevelFoldRegionsState "[FoldRegion +(24:83), placeholder='{...}']" + } private void assertTopLevelFoldRegionsState(String expectedState) { assertEquals(expectedState, myFixture.editor.foldingModel.toString()) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java index 3d55ed673c03..9676ac79dbd9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -93,6 +93,8 @@ class UpdateFoldRegionsOperation implements Runnable { List newRegions = addNewRegions(info, foldingModel, elementsToFold, rangeToExpandStatusMap, shouldExpand, groupExpand); applyExpandStatus(newRegions, shouldExpand, groupExpand); + + foldingModel.clearExternalChangeFlag(); } private static void applyExpandStatus(@NotNull List newRegions, @@ -248,7 +250,10 @@ class UpdateFoldRegionsOperation implements Runnable { } private boolean regionCanBeRemovedWhenCollapsed(FoldRegion region) { - return Boolean.TRUE.equals(region.getUserData(CAN_BE_REMOVED_WHEN_COLLAPSED)) || !region.isValid() || isRegionInCaretLine(region); + return Boolean.TRUE.equals(region.getUserData(CAN_BE_REMOVED_WHEN_COLLAPSED)) || + ((FoldingModelEx)myEditor.getFoldingModel()).documentHasBeenChangedExternally() || + !region.isValid() || + isRegionInCaretLine(region); } private boolean isRegionInCaretLine(FoldRegion region) { diff --git a/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java index fd8fe0527f10..08041767cd57 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -200,6 +200,15 @@ class FoldingModelWindow implements FoldingModelEx{ return result; } + @Override + public boolean documentHasBeenChangedExternally() { + return false; + } + + @Override + public void clearExternalChangeFlag() { + } + @Override public void clearFoldRegions() { myDelegate.clearFoldRegions(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.java index 2784015c092a..53246ea58aab 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -64,4 +64,8 @@ public interface FoldingModelEx extends FoldingModel { @NotNull List getGroupedRegions(FoldingGroup group); + + boolean documentHasBeenChangedExternally(); + + void clearExternalChangeFlag(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java index efe4b2311172..7e5dee7abeb6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -26,6 +26,7 @@ package com.intellij.openapi.editor.impl; import com.intellij.diagnostic.Dumpable; import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; @@ -36,6 +37,7 @@ import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.ModificationTracker; +import com.intellij.psi.ExternalChangeAction; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; @@ -65,6 +67,7 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedInternalDocu private int mySavedCaretShift; private final MultiMap myGroups = new MultiMap(); private boolean myDocumentChangeProcessed = true; + private boolean myDocumentHasBeenChangedExternally; private final AtomicLong myExpansionCounter = new AtomicLong(); public FoldingModelImpl(EditorImpl editor) { @@ -532,6 +535,7 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedInternalDocu if (!((DocumentEx)event.getDocument()).isInBulkUpdate()) { updateCachedOffsets(); } + if (ApplicationManager.getApplication().hasWriteAction(ExternalChangeAction.class)) myDocumentHasBeenChangedExternally = true; } finally { myDocumentChangeProcessed = true; @@ -593,4 +597,14 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedInternalDocu public long getModificationCount() { return myExpansionCounter.get(); } + + @Override + public boolean documentHasBeenChangedExternally() { + return myDocumentHasBeenChangedExternally; + } + + @Override + public void clearExternalChangeFlag() { + myDocumentHasBeenChangedExternally = false; + } }