diff --git a/java/java-tests/testSrc/com/intellij/openapi/editor/impl/JavaFileEditorManagerTest.java b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/JavaFileEditorManagerTest.java index 47735323ad42..acff670b0a5a 100644 --- a/java/java-tests/testSrc/com/intellij/openapi/editor/impl/JavaFileEditorManagerTest.java +++ b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/JavaFileEditorManagerTest.java @@ -15,6 +15,15 @@ */ package com.intellij.openapi.editor.impl; +import com.intellij.codeInsight.daemon.impl.CodeFoldingPassFactory; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.FoldRegion; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.TextEditor; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiJavaFile; +import com.intellij.psi.PsiMethod; +import com.intellij.testFramework.EditorTestUtil; import com.intellij.testFramework.FileEditorManagerTestCase; import com.intellij.testFramework.PlatformTestUtil; import org.jdom.JDOMException; @@ -47,6 +56,29 @@ public class JavaFileEditorManagerTest extends FileEditorManagerTestCase { " "); } + public void testFoldingIsNotBlinkingOnNavigationToSingleLineMethod() { + VirtualFile file = getFile("/src/Bar.java"); + PsiJavaFile psiFile = (PsiJavaFile)getPsiManager().findFile(file); + assertNotNull(psiFile); + PsiMethod method = psiFile.getClasses()[0].getMethods()[0]; + method.navigate(true); + + FileEditor[] editors = myManager.getEditors(file); + assertEquals(1, editors.length); + Editor editor = ((TextEditor)editors[0]).getEditor(); + FoldRegion[] regions = editor.getFoldingModel().getAllFoldRegions(); + assertEquals(2, regions.length); + assertTrue(regions[0].isExpanded()); + assertTrue(regions[1].isExpanded()); + + EditorTestUtil.runTextEditorHighlightingPass(editor, CodeFoldingPassFactory.class); + + regions = editor.getFoldingModel().getAllFoldRegions(); + assertEquals(2, regions.length); + assertTrue(regions[0].isExpanded()); + assertTrue(regions[1].isExpanded()); + } + @Override protected String getTestDataPath() { return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/java/java-tests/testData/fileEditorManager"; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java index 9a5bd2cbbe6b..ddf115bfdde7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java @@ -49,6 +49,8 @@ import java.awt.*; import java.awt.event.MouseEvent; import java.util.List; +import static com.intellij.codeInsight.folding.impl.UpdateFoldRegionsOperation.ApplyDefaultStateMode.*; + public class CodeFoldingManagerImpl extends CodeFoldingManager implements ProjectComponent { private final Project myProject; @@ -246,7 +248,7 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec if (isFoldingsInitializedInEditor(editor)) return; if (DumbService.isDumb(myProject) && !FoldingUpdate.supportsDumbModeFolding(editor)) return; - foldingModel.runBatchFoldingOperationDoNotCollapseCaret(new UpdateFoldRegionsOperation(myProject, editor, file, foldingMap, true, false)); + foldingModel.runBatchFoldingOperationDoNotCollapseCaret(new UpdateFoldRegionsOperation(myProject, editor, file, foldingMap, YES, false)); initFolding(editor); } }; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java index de59a0d9592c..62f641b37807 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java @@ -51,6 +51,8 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import static com.intellij.codeInsight.folding.impl.UpdateFoldRegionsOperation.ApplyDefaultStateMode.*; + public class FoldingUpdate { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.folding.impl.FoldingUpdate"); @@ -116,7 +118,8 @@ public class FoldingUpdate { final boolean applyDefaultState) { final FoldingMap elementsToFoldMap = getFoldingsFor(project, file, document, quick); - final UpdateFoldRegionsOperation operation = new UpdateFoldRegionsOperation(project, editor, file, elementsToFoldMap, applyDefaultState, false); + final UpdateFoldRegionsOperation operation = new UpdateFoldRegionsOperation(project, editor, file, elementsToFoldMap, + applyDefaultState ? EXCEPT_CARET_REGION : NO, false); Runnable runnable = new Runnable() { @Override public void run() { @@ -190,7 +193,8 @@ public class FoldingUpdate { PsiFile injectedFile = injectedFiles.get(i); if (!injectedEditor.getDocument().isValid()) continue; FoldingMap map = maps.get(i); - updateOperations.add(new UpdateFoldRegionsOperation(project, injectedEditor, injectedFile, map, applyDefaultState, true)); + updateOperations.add(new UpdateFoldRegionsOperation(project, injectedEditor, injectedFile, map, + applyDefaultState ? EXCEPT_CARET_REGION : NO, true)); } foldingModel.runBatchFoldingOperation(new Runnable() { @Override 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 30367e67ff31..fe40cfa91b1a 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-2013 JetBrains s.r.o. + * 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. @@ -23,6 +23,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.FoldRegion; import com.intellij.openapi.editor.FoldingGroup; import com.intellij.openapi.editor.ex.FoldingModelEx; +import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; @@ -42,13 +43,15 @@ import static com.intellij.util.containers.ContainerUtil.newTroveMap; * @author cdr */ class UpdateFoldRegionsOperation implements Runnable { + + enum ApplyDefaultStateMode { YES, EXCEPT_CARET_REGION, NO } private static final Logger LOG = Logger.getInstance("#" + UpdateFoldRegionsOperation.class.getName()); private final Project myProject; private final Editor myEditor; private final PsiFile myFile; - private final boolean myApplyDefaultState; + private final ApplyDefaultStateMode myApplyDefaultState; private final FoldingUpdate.FoldingMap myElementsToFoldMap; private final boolean myForInjected; @@ -56,7 +59,7 @@ class UpdateFoldRegionsOperation implements Runnable { @NotNull Editor editor, @NotNull PsiFile file, @NotNull FoldingUpdate.FoldingMap elementsToFoldMap, - boolean applyDefaultState, + ApplyDefaultStateMode applyDefaultState, boolean forInjected) { myProject = project; myEditor = editor; @@ -144,8 +147,14 @@ class UpdateFoldRegionsOperation implements Runnable { } private boolean shouldExpandNewRegion(PsiElement element, TextRange range, Map rangeToExpandStatusMap) { - if (myApplyDefaultState) { + if (myApplyDefaultState != ApplyDefaultStateMode.NO) { // Considering that this code is executed only on initial fold regions construction on editor opening. + if (myApplyDefaultState == ApplyDefaultStateMode.EXCEPT_CARET_REGION) { + TextRange lineRange = OpenFileDescriptor.getRangeToUnfoldOnNavigation(myEditor); + if (lineRange.intersects(range)) { + return true; + } + } return !FoldingPolicy.isCollapseByDefault(element); } diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java index fdf32b9adcba..fbf057f50acc 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java @@ -224,11 +224,7 @@ public class OpenFileDescriptor implements Navigatable { private static void unfoldCurrentLine(@NotNull final Editor editor) { final FoldRegion[] allRegions = editor.getFoldingModel().getAllFoldRegions(); - final int offset = editor.getCaretModel().getOffset(); - int line = editor.getDocument().getLineNumber(offset); - int start = editor.getDocument().getLineStartOffset(line); - int end = editor.getDocument().getLineEndOffset(line); - final TextRange range = new TextRange(start, end); + final TextRange range = getRangeToUnfoldOnNavigation(editor); editor.getFoldingModel().runBatchFoldingOperation(new Runnable() { @Override public void run() { @@ -241,6 +237,15 @@ public class OpenFileDescriptor implements Navigatable { }); } + @NotNull + public static TextRange getRangeToUnfoldOnNavigation(@NotNull Editor editor) { + final int offset = editor.getCaretModel().getOffset(); + int line = editor.getDocument().getLineNumber(offset); + int start = editor.getDocument().getLineStartOffset(line); + int end = editor.getDocument().getLineEndOffset(line); + return new TextRange(start, end); + } + private static void scrollToCaret(@NotNull Editor e) { e.getScrollingModel().scrollToCaret(ScrollType.CENTER); }