From 39b27d23b0470d4ee362478202b875cdce314de1 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 2 Jul 2013 14:28:30 +0400 Subject: [PATCH] Explicitly release range markers created by PostprocessReformattingAspect - fails in case of great document changes number within the same transaction --- .../source/PostprocessReformattingAspect.java | 90 +++++++++++++------ 1 file changed, 62 insertions(+), 28 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java index 65818b26efbb..9d7a9e90ddee 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java @@ -18,6 +18,7 @@ package com.intellij.psi.impl.source; import com.intellij.formatting.FormatTextRanges; import com.intellij.lang.ASTNode; import com.intellij.lang.injection.InjectedLanguageManager; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationAdapter; import com.intellij.openapi.application.ApplicationListener; import com.intellij.openapi.application.ApplicationManager; @@ -46,6 +47,7 @@ import com.intellij.psi.impl.source.codeStyle.CodeFormatterFacade; import com.intellij.psi.impl.source.codeStyle.IndentHelperImpl; import com.intellij.psi.impl.source.tree.*; import com.intellij.util.LocalTimeCounter; +import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly; @@ -295,33 +297,44 @@ public class PostprocessReformattingAspect implements PomModelAspect { final VirtualFile virtualFile = key.getVirtualFile(); if (!virtualFile.isValid()) return; - final TreeSet postprocessTasks = new TreeSet(); - // process all roots in viewProvider to find marked for reformat before elements and create appropriate range markers - handleReformatMarkers(key, postprocessTasks); + final TreeSet postProcessTasks = new TreeSet(); + Collection toDispose = ContainerUtilRt.newArrayList(); + try { + // process all roots in viewProvider to find marked for reformat before elements and create appropriate range markers + handleReformatMarkers(key, postProcessTasks); + toDispose.addAll(postProcessTasks); - // then we create ranges by changed nodes. One per node. There ranges can intersect. Ranges are sorted by end offset. - if (astNodes != null) createActionsMap(astNodes, key, postprocessTasks); + // then we create ranges by changed nodes. One per node. There ranges can intersect. Ranges are sorted by end offset. + if (astNodes != null) createActionsMap(astNodes, key, postProcessTasks); - if ("true".equals(System.getProperty("check.psi.is.valid")) && ApplicationManager.getApplication().isUnitTestMode()) { - checkPsiIsCorrect(key); + if ("true".equals(System.getProperty("check.psi.is.valid")) && ApplicationManager.getApplication().isUnitTestMode()) { + checkPsiIsCorrect(key); + } + + while (!postProcessTasks.isEmpty()) { + // now we have to normalize actions so that they not intersect and ordered in most appropriate way + // (free reformatting -> reindent -> formatting under reindent) + final List normalizedActions = normalizeAndReorderPostponedActions(postProcessTasks, document); + toDispose.addAll(normalizedActions); + + // only in following loop real changes in document are made + for (final PostponedAction normalizedAction : normalizedActions) { + CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(myPsiManager.getProject()); + boolean old = settings.ENABLE_JAVADOC_FORMATTING; + settings.ENABLE_JAVADOC_FORMATTING = false; + try { + normalizedAction.execute(key); + } + finally { + settings.ENABLE_JAVADOC_FORMATTING = old; + } + } + } } - - while (!postprocessTasks.isEmpty()) { - // now we have to normalize actions so that they not intersect and ordered in most appropriate way - // (free reformatting -> reindent -> formatting under reindent) - final List normalizedActions = normalizeAndReorderPostponedActions(postprocessTasks, document); - - // only in following loop real changes in document are made - for (final PostponedAction normalizedAction : normalizedActions) { - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(myPsiManager.getProject()); - boolean old = settings.ENABLE_JAVADOC_FORMATTING; - settings.ENABLE_JAVADOC_FORMATTING = false; - try { - normalizedAction.execute(key); - } - finally { - settings.ENABLE_JAVADOC_FORMATTING = old; - } + finally { + for (Disposable disposable : toDispose) { + //noinspection SSBasedInspection + disposable.dispose(); } } } @@ -599,10 +612,10 @@ public class PostprocessReformattingAspect implements PomModelAspect { return codeFormatter; } - private abstract static class PostprocessFormattingTask implements Comparable, Segment { - private final RangeMarker myRange; + private abstract static class PostprocessFormattingTask implements Comparable, Segment, Disposable { + @NotNull private final RangeMarker myRange; - public PostprocessFormattingTask(RangeMarker rangeMarker) { + public PostprocessFormattingTask(@NotNull RangeMarker rangeMarker) { myRange = rangeMarker; } @@ -621,6 +634,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { return diff; } + @NotNull public RangeMarker getRange() { return myRange; } @@ -634,6 +648,12 @@ public class PostprocessReformattingAspect implements PomModelAspect { public int getEndOffset() { return myRange.getEndOffset(); } + + public void dispose() { + if (myRange.isValid()) { + myRange.dispose(); + } + } } private static class ReformatTask extends PostprocessFormattingTask { @@ -661,7 +681,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { } } - private interface PostponedAction { + private interface PostponedAction extends Disposable { void execute(FileViewProvider viewProvider); } @@ -677,6 +697,10 @@ public class PostprocessReformattingAspect implements PomModelAspect { final CodeFormatterFacade codeFormatter = getFormatterFacade(viewProvider); codeFormatter.processText(viewProvider.getPsi(viewProvider.getBaseLanguage()), myRanges.ensureNonEmpty(), false); } + + @Override + public void dispose() { + } } private static class ReindentRangesAction implements PostponedAction { @@ -700,6 +724,16 @@ public class PostprocessReformattingAspect implements PomModelAspect { if (indentAdjustment != 0) adjustIndentationInRange(psiFile, document, whitespaces, indentAdjustment); } } + + @Override + public void dispose() { + for (Pair pair : myRangesToReindent) { + RangeMarker marker = pair.second; + if (marker.isValid()) { + marker.dispose(); + } + } + } } @TestOnly