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.
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);
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 {
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 {
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);
}
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;
- }
-
- void setMinGroupOffsetMarker(boolean value) {
- myMinGroupOffsetMarker = value;
+ public void setStrictMinOffsetBlock(Block block) {
+ myStrictMinOffsetBlock = block;
}
- public Object getGroup() {
- return myGroup;
+ Block getStrictMinOffsetBlock() {
+ return myStrictMinOffsetBlock;
}
-
@Override
public boolean isEnforceIndentToChildren() {
return myEnforceIndent;
@NotNull
private State myCurrentState;
- private MultiMap<Object, AbstractBlockWrapper> myExpandableIndents;
+ private MultiMap<ExpandableIndent, AbstractBlockWrapper> myExpandableIndents;
+ private Map<Block, AbstractBlockWrapper> myExpandableIndentsMinOffsetBlocksToWrappers;
public FormatProcessor(final FormattingDocumentModel docModel,
Block rootBlock,
root, model, affectedRanges, mySettings, myDefaultIndentOption, interestingOffset, myProgressCallback
);
myWrapper.setCollectAlignmentsInsideFormattingRange(myReformatContext);
- myExpandableIndents = myWrapper.getBlocksWithSmartIndents();
+
+ myExpandableIndents = myWrapper.getExpandableIndentsBlocks();
+ myExpandableIndentsMinOffsetBlocksToWrappers = myWrapper.getMarkerBlocks();
}
@Override
}
}
-
private class ExpandChildrenIndent extends State {
- private Iterator<Object> myIterator;
+ private Iterator<ExpandableIndent> myIterator;
public ExpandChildrenIndent() {
super(FormattingStateId.EXPANDING_CHILDREN_INDENTS);
return;
}
- Collection<AbstractBlockWrapper> blocksToExpandIndent = myExpandableIndents.get(myIterator.next());
-
- if (shouldExpand(blocksToExpandIndent)) {
+ final ExpandableIndent indent = myIterator.next();
+ Collection<AbstractBlockWrapper> 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);
}
}
- private boolean shouldExpand(Collection<AbstractBlockWrapper> blocksToExpandIndent) {
- int minGroupOffset = Integer.MAX_VALUE;
+ private boolean shouldExpand(ExpandableIndent indent, Collection<AbstractBlockWrapper> 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;
}
}
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();
}
@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
private Set<Alignment> myAlignmentsInsideRangeToModify = ContainerUtil.newHashSet();
private boolean myCollectAlignmentsInsideFormattingRange = false;
- private MultiMap<Object, AbstractBlockWrapper> myBlocksToForceChildrenIndent = new LinkedMultiMap<Object, AbstractBlockWrapper>();
+ private Set<Block> myStrictMinOffsetBlocks = ContainerUtil.newHashSet();
+ private MultiMap<ExpandableIndent, AbstractBlockWrapper> myBlocksToForceChildrenIndent = new LinkedMultiMap<ExpandableIndent, AbstractBlockWrapper>();
+ private Map<Block, AbstractBlockWrapper> myMarkerIndentToBlock = ContainerUtil.newHashMap();
private InitialInfoBuilder(final Block rootBlock,
final FormattingDocumentModel model,
return wrappedRootBlock;
}
- public MultiMap<Object, AbstractBlockWrapper> getBlocksWithSmartIndents() {
+ public MultiMap<ExpandableIndent, AbstractBlockWrapper> getExpandableIndentsBlocks() {
return myBlocksToForceChildrenIndent;
}
+ public Map<Block, AbstractBlockWrapper> getMarkerBlocks() {
+ return myMarkerIndentToBlock;
+ }
+
private void doIteration(@NotNull State state) {
List<Block> subBlocks = state.parentBlock.getSubBlocks();
final int subBlocksCount = subBlocks.size();
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());
}
}
}
-
+
+ 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<AbstractBlockWrapper> list) {
if (!list.isEmpty()) {
for (AbstractBlockWrapper wrapper : list) {