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) {