From 03a72e58c33bc50c82441568dd094a3bfba488c5 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 17 Jun 2015 12:53:37 +0300 Subject: [PATCH] Expandable indent storing additional block, which indent is used as min indent marker for all children of blocks corresponding to particular expandable indent. If all blocks corresponding to current expandable indent has no linefeeds in their whitespaces, if one of these blocks has child which has indent less or equal than min marker indent, than indent is expanded. Total summary: Indent is expanded, if any of blocks with these indent is located on new line, or when there is some block's children with indent less or equal than min marker indent. --- .../psi/formatter/java/AbstractJavaBlock.java | 17 ++++--- .../src/com/intellij/formatting/Indent.java | 8 +-- .../intellij/formatting/IndentFactory.java | 3 +- .../intellij/formatting/ExpandableIndent.java | 20 +++----- .../intellij/formatting/FormatProcessor.java | 51 ++++++++++--------- .../intellij/formatting/FormatterImpl.java | 11 +--- .../formatting/InitialInfoBuilder.java | 33 +++++++++--- 7 files changed, 73 insertions(+), 70 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java index 53c3d3e73ae8..7c32ad77d1dc 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java @@ -867,9 +867,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo Indent internalIndent = Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS); if (isInsideMethodCallParenthesis(child)) { - Object group = new Object(); - externalIndent = Indent.getSmartIndentMinOffsetMarker(Indent.Type.NONE, group); - internalIndent = Indent.getSmartIndent(Indent.Type.CONTINUATION, group); + internalIndent = Indent.getSmartIndent(Indent.Type.CONTINUATION); } AlignmentStrategy alignmentStrategy = AlignmentStrategy.wrap(createAlignment(doAlign, null), JavaTokenType.COMMA); @@ -904,11 +902,14 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo result.add(createJavaBlock(child, mySettings, myJavaSettings, externalIndent, null, bracketAlignment)); } else if (child.getElementType() == to) { - result.add(createJavaBlock(child, mySettings, myJavaSettings, - isAfterIncomplete && !afterAnonymousClass ? internalIndent : externalIndent, - null, - isAfterIncomplete ? alignmentStrategy.getAlignment(null) : bracketAlignment) - ); + Block block = createJavaBlock(child, mySettings, myJavaSettings, + isAfterIncomplete && !afterAnonymousClass ? internalIndent : externalIndent, + null, + isAfterIncomplete ? alignmentStrategy.getAlignment(null) : bracketAlignment); + result.add(block); + if (internalIndent instanceof ExpandableIndent && to == JavaTokenType.RPARENTH) { + ((ExpandableIndent)internalIndent).setStrictMinOffsetBlock(block); + } return child; } else { diff --git a/platform/lang-api/src/com/intellij/formatting/Indent.java b/platform/lang-api/src/com/intellij/formatting/Indent.java index 3cb9dace7bad..62f80608de91 100644 --- a/platform/lang-api/src/com/intellij/formatting/Indent.java +++ b/platform/lang-api/src/com/intellij/formatting/Indent.java @@ -269,12 +269,8 @@ public abstract class Indent { return myFactory.getIndent(type, spaces, relativeToDirectParent, enforceIndentToChildren); } - public static Indent getSmartIndent(Type type, Object group) { - return myFactory.getSmartIndent(type, group); - } - - public static Indent getSmartIndentMinOffsetMarker(Type type, Object group) { - return myFactory.getSmartIndentMinOffsetMarker(type, group); + public static Indent getSmartIndent(Type type) { + return myFactory.getSmartIndent(type); } public static class Type { diff --git a/platform/lang-api/src/com/intellij/formatting/IndentFactory.java b/platform/lang-api/src/com/intellij/formatting/IndentFactory.java index 01afe5f03120..35d2d52d6aa5 100644 --- a/platform/lang-api/src/com/intellij/formatting/IndentFactory.java +++ b/platform/lang-api/src/com/intellij/formatting/IndentFactory.java @@ -34,6 +34,5 @@ interface IndentFactory { Indent getSpaceIndent(final int spaces, boolean relativeToDirectParent); Indent getIndent(@NotNull Indent.Type type, boolean relativeToDirectParent, boolean enforceIndentToChildren); Indent getIndent(@NotNull Indent.Type type, int spaces, boolean relativeToDirectParent, boolean enforceIndentToChildren); - Indent getSmartIndent(@NotNull Indent.Type type, @NotNull Object group); - Indent getSmartIndentMinOffsetMarker(@NotNull Indent.Type type, @NotNull Object group); + Indent getSmartIndent(@NotNull Indent.Type type); } diff --git a/platform/lang-impl/src/com/intellij/formatting/ExpandableIndent.java b/platform/lang-impl/src/com/intellij/formatting/ExpandableIndent.java index be049c53e3a5..f14ac939cd09 100644 --- a/platform/lang-impl/src/com/intellij/formatting/ExpandableIndent.java +++ b/platform/lang-impl/src/com/intellij/formatting/ExpandableIndent.java @@ -16,30 +16,22 @@ package com.intellij.formatting; public class ExpandableIndent extends IndentImpl { - - private final Object myGroup; - private boolean myMinGroupOffsetMarker; + private Block myStrictMinOffsetBlock; private boolean myEnforceIndent; - public ExpandableIndent(Type type, Object group) { + public ExpandableIndent(Type type) { super(type, false, 0, false, true); - myGroup = group; myEnforceIndent = false; } - public boolean isMinGroupOffsetMarker() { - return myMinGroupOffsetMarker; + public void setStrictMinOffsetBlock(Block block) { + myStrictMinOffsetBlock = block; } - void setMinGroupOffsetMarker(boolean value) { - myMinGroupOffsetMarker = value; + Block getStrictMinOffsetBlock() { + return myStrictMinOffsetBlock; } - public Object getGroup() { - return myGroup; - } - - @Override public boolean isEnforceIndentToChildren() { return myEnforceIndent; diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java index 698a1677f5ab..8d157038435f 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java @@ -159,7 +159,8 @@ public class FormatProcessor { @NotNull private State myCurrentState; - private MultiMap myExpandableIndents; + private MultiMap myExpandableIndents; + private Map myExpandableIndentsMinOffsetBlocksToWrappers; public FormatProcessor(final FormattingDocumentModel docModel, Block rootBlock, @@ -1365,7 +1366,9 @@ public class FormatProcessor { root, model, affectedRanges, mySettings, myDefaultIndentOption, interestingOffset, myProgressCallback ); myWrapper.setCollectAlignmentsInsideFormattingRange(myReformatContext); - myExpandableIndents = myWrapper.getBlocksWithSmartIndents(); + + myExpandableIndents = myWrapper.getExpandableIndentsBlocks(); + myExpandableIndentsMinOffsetBlocksToWrappers = myWrapper.getMarkerBlocks(); } @Override @@ -1590,9 +1593,8 @@ public class FormatProcessor { } } - private class ExpandChildrenIndent extends State { - private Iterator myIterator; + private Iterator myIterator; public ExpandChildrenIndent() { super(FormattingStateId.EXPANDING_CHILDREN_INDENTS); @@ -1608,11 +1610,10 @@ public class FormatProcessor { return; } - Collection blocksToExpandIndent = myExpandableIndents.get(myIterator.next()); - - if (shouldExpand(blocksToExpandIndent)) { + final ExpandableIndent indent = myIterator.next(); + Collection blocksToExpandIndent = myExpandableIndents.get(indent); + if (shouldExpand(indent, blocksToExpandIndent)) { for (AbstractBlockWrapper block : blocksToExpandIndent) { - ExpandableIndent indent = (ExpandableIndent)block.getIndent(); indent.setEnforceIndent(true); reindentNewLineChildren(block); indent.setEnforceIndent(false); @@ -1620,28 +1621,20 @@ public class FormatProcessor { } } - private boolean shouldExpand(Collection blocksToExpandIndent) { - int minGroupOffset = Integer.MAX_VALUE; + private boolean shouldExpand(ExpandableIndent indent, Collection blocksToExpandIndent) { for (AbstractBlockWrapper block : blocksToExpandIndent) { if (!block.getWhiteSpace().containsLineFeeds()) continue; - - ExpandableIndent indent = (ExpandableIndent)block.getIndent(); - if (indent.isMinGroupOffsetMarker()) { - minGroupOffset = block.getNumberOfSymbolsBeforeBlock().getTotalSpaces(); - } - else { - return true; - } + return true; } - if (minGroupOffset == Integer.MAX_VALUE) return false; + int strictMinOffset = getStrictMinOffset(indent); + if (strictMinOffset == Integer.MAX_VALUE) { + return false; + } for (AbstractBlockWrapper block : blocksToExpandIndent) { - ExpandableIndent indent = (ExpandableIndent)block.getIndent(); - if (indent.isMinGroupOffsetMarker()) continue; - int minNewLineChildrenOffset = findMinNewLineIndent(block); - if (minNewLineChildrenOffset <= minGroupOffset) { + if (minNewLineChildrenOffset <= strictMinOffset) { return true; } } @@ -1649,6 +1642,18 @@ public class FormatProcessor { return false; } + private int getStrictMinOffset(ExpandableIndent indent) { + final Block minOffsetBlock = indent.getStrictMinOffsetBlock(); + if (minOffsetBlock == null) return Integer.MAX_VALUE; + + AbstractBlockWrapper wrapper = myExpandableIndentsMinOffsetBlocksToWrappers.get(minOffsetBlock); + if (wrapper.getWhiteSpace().containsLineFeeds()) { + return wrapper.getNumberOfSymbolsBeforeBlock().getTotalSpaces(); + } + + return Integer.MAX_VALUE; + } + private int findMinNewLineIndent(@NotNull AbstractBlockWrapper block) { if (block instanceof LeafBlockWrapper && block.getWhiteSpace().containsLineFeeds()) { return block.getNumberOfSymbolsBeforeBlock().getTotalSpaces(); diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java index e7e8cae90650..f8dbc4ed53f9 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java @@ -819,15 +819,8 @@ public class FormatterImpl extends FormatterEx } @Override - public Indent getSmartIndent(@NotNull Indent.Type type, @NotNull Object group) { - return new ExpandableIndent(type, group); - } - - @Override - public Indent getSmartIndentMinOffsetMarker(@NotNull Indent.Type type, @NotNull Object group) { - ExpandableIndent indent = new ExpandableIndent(type, group); - indent.setMinGroupOffsetMarker(true); - return indent; + public Indent getSmartIndent(@NotNull Indent.Type type) { + return new ExpandableIndent(type); } @Override diff --git a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java index ba74eb8165da..86a94d27ffcc 100644 --- a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java +++ b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java @@ -76,7 +76,9 @@ class InitialInfoBuilder { private Set myAlignmentsInsideRangeToModify = ContainerUtil.newHashSet(); private boolean myCollectAlignmentsInsideFormattingRange = false; - private MultiMap myBlocksToForceChildrenIndent = new LinkedMultiMap(); + private Set myStrictMinOffsetBlocks = ContainerUtil.newHashSet(); + private MultiMap myBlocksToForceChildrenIndent = new LinkedMultiMap(); + private Map myMarkerIndentToBlock = ContainerUtil.newHashMap(); private InitialInfoBuilder(final Block rootBlock, final FormattingDocumentModel model, @@ -289,10 +291,14 @@ class InitialInfoBuilder { return wrappedRootBlock; } - public MultiMap getBlocksWithSmartIndents() { + public MultiMap getExpandableIndentsBlocks() { return myBlocksToForceChildrenIndent; } + public Map getMarkerBlocks() { + return myMarkerIndentToBlock; + } + private void doIteration(@NotNull State state) { List subBlocks = state.parentBlock.getSubBlocks(); final int subBlocksCount = subBlocks.size(); @@ -311,11 +317,7 @@ class InitialInfoBuilder { final AbstractBlockWrapper wrapper = buildFrom( block, childBlockIndex, state.wrappedBlock, state.parentBlockWrap, state.parentBlock, childBlockIsRightBlock ); - - if (block.getIndent() instanceof ExpandableIndent) { - ExpandableIndent expandableIndent = (ExpandableIndent)block.getIndent(); - myBlocksToForceChildrenIndent.putValue(expandableIndent.getGroup(), wrapper); - } + registerExpandableIndents(block, wrapper); if (wrapper.getIndent() == null) { wrapper.setIndent((IndentImpl)block.getIndent()); @@ -334,7 +336,22 @@ class InitialInfoBuilder { } } } - + + private void registerExpandableIndents(@NotNull Block block, @NotNull AbstractBlockWrapper wrapper) { + ExpandableIndent expandableIndent = block.getIndent() instanceof ExpandableIndent ? ((ExpandableIndent)block.getIndent()) : null; + if (expandableIndent != null) { + myBlocksToForceChildrenIndent.putValue(expandableIndent, wrapper); + Block markerBlock = expandableIndent.getStrictMinOffsetBlock(); + if (markerBlock != null) { + myStrictMinOffsetBlocks.add(markerBlock); + } + } + + if (myStrictMinOffsetBlocks.contains(block)) { + myMarkerIndentToBlock.put(block, wrapper); + } + } + private void setDefaultIndents(final List list) { if (!list.isEmpty()) { for (AbstractBlockWrapper wrapper : list) {