From c30e7b54e082cae3b73def7257d9f2aef0295b68 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 27 Oct 2015 18:26:30 +0300 Subject: [PATCH] Implemented simple check for alignment infinite recusrsion - we limit amount of backward block rollbacks (when we switch myCurrentBlock to some previously located block) to the number of total blocks with alignments. --- .../AbstractBlockAlignmentProcessor.java | 2 +- .../com/intellij/formatting/FormatProcessor.java | 15 ++++++++++++++- .../intellij/formatting/InitialInfoBuilder.java | 9 +++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockAlignmentProcessor.java b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockAlignmentProcessor.java index a66eceb51618..7740ea2a2603 100644 --- a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockAlignmentProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockAlignmentProcessor.java @@ -135,7 +135,7 @@ public abstract class AbstractBlockAlignmentProcessor implements BlockAlignmentP */ protected abstract int getAlignmentIndentDiff(@NotNull IndentData alignmentAnchorIndent, @NotNull Context context); - private static void reportAlignmentProcessingError(Context context) { + protected static void reportAlignmentProcessingError(Context context) { ASTNode node = context.targetBlock.getNode(); Language language = node != null ? node.getPsi().getLanguage() : null; LogMessageEx.error(LOG, diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java index c3091e64828e..615bd0daf055 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java @@ -42,6 +42,8 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import static com.intellij.formatting.AbstractBlockAlignmentProcessor.*; + public class FormatProcessor { private static final Map ALIGNMENT_PROCESSORS = @@ -160,6 +162,8 @@ public class FormatProcessor { @NotNull private State myCurrentState; private MultiMap myExpandableIndents; + private int myTotalBlocksWithAlignments; + private int myBlockRollbacks; public FormatProcessor(final FormattingDocumentModel docModel, Block rootBlock, @@ -752,7 +756,15 @@ public class FormatProcessor { myBackwardShiftedAlignedBlocks.put(offsetResponsibleBlock, blocksCausedRealignment); blocksCausedRealignment.add(myCurrentBlock); storeAlignmentMapping(myCurrentBlock, offsetResponsibleBlock); - myCurrentBlock = offsetResponsibleBlock.getNextBlock(); + + if (myBlockRollbacks > myTotalBlocksWithAlignments) { + reportAlignmentProcessingError(context); + return true; + } + else { + myCurrentBlock = offsetResponsibleBlock.getNextBlock(); + myBlockRollbacks++; + } onCurrentLineChanged(); return false; case RECURSION_DETECTED: @@ -1398,6 +1410,7 @@ public class FormatProcessor { myLastWhiteSpace = new WhiteSpace(lastBlockOffset, false); myLastWhiteSpace.append(Math.max(lastBlockOffset, myWrapper.getEndOffset()), myModel, myDefaultIndentOption); myAlignmentsInsideRangesToModify = myWrapper.getAlignmentsInsideRangeToModify(); + myTotalBlocksWithAlignments = myWrapper.getBlocksToAlign().values().size(); } } diff --git a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java index 46045c827735..b9db5823b859 100644 --- a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java +++ b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java @@ -77,6 +77,7 @@ class InitialInfoBuilder { private boolean myCollectAlignmentsInsideFormattingRange = false; private MultiMap myBlocksToForceChildrenIndent = new LinkedMultiMap(); + private MultiMap myBlocksToAlign = new MultiMap(); private InitialInfoBuilder(final Block rootBlock, final FormattingDocumentModel model, @@ -205,6 +206,10 @@ class InitialInfoBuilder { myAlignmentsInsideRangeToModify.add(rootBlock.getAlignment()); } + if (rootBlock.getAlignment() != null) { + myBlocksToAlign.putValue(rootBlock.getAlignment(), rootBlock); + } + ReadOnlyBlockInformationProvider previousProvider = myReadOnlyBlockInformationProvider; try { if (rootBlock instanceof ReadOnlyBlockInformationProvider) { @@ -293,6 +298,10 @@ class InitialInfoBuilder { return myBlocksToForceChildrenIndent; } + public MultiMap getBlocksToAlign() { + return myBlocksToAlign; + } + private void doIteration(@NotNull State state) { List subBlocks = state.parentBlock.getSubBlocks(); final int subBlocksCount = subBlocks.size();