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 a49cede74175..c092223ea47a 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 @@ -39,6 +39,7 @@ import com.intellij.psi.impl.source.tree.java.ClassElement; import com.intellij.psi.jsp.JspElementType; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -90,6 +91,8 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo private final JavaWrapManager myWrapManager; private final AlignmentInColumnsHelper myAlignmentInColumnsHelper; + private Map myPreferredWraps; + private AbstractJavaBlock myParentBlock; protected AbstractJavaBlock(@NotNull final ASTNode node, final Wrap wrap, @@ -505,12 +508,9 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo mySettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS); } else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.PARAMETER_LIST) { - // There is a possible case that particular annotated method definition is too long. We may wrap either after annotation - // or after opening lbrace then. Our strategy is to wrap after annotation whenever possible. - Wrap wrap = Wrap.createWrap(getWrapType(mySettings.METHOD_PARAMETERS_WRAP), false); - child = processParenthesisBlock(result, child, - WrappingStrategy.createDoNotWrapCommaStrategy(wrap), - mySettings.ALIGN_MULTILINE_PARAMETERS); + Wrap wrapToUse = getMethodParametersWrap(); + WrappingStrategy wrapStrategy = WrappingStrategy.createDoNotWrapCommaStrategy(wrapToUse); + child = processParenthesisBlock(result, child, wrapStrategy, mySettings.ALIGN_MULTILINE_PARAMETERS); } else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.RESOURCE_LIST) { Wrap wrap = Wrap.createWrap(getWrapType(mySettings.RESOURCE_LIST_WRAP), false); @@ -572,6 +572,25 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo return child; } + @NotNull + private Wrap getMethodParametersWrap() { + Wrap preferredWrap = getModifierListWrap(); + if (preferredWrap == null) { + return Wrap.createWrap(getWrapType(mySettings.METHOD_PARAMETERS_WRAP), false); + } else { + return Wrap.createChildWrap(preferredWrap, getWrapType(mySettings.METHOD_PARAMETERS_WRAP), false); + } + } + + @Nullable + private Wrap getModifierListWrap() { + AbstractJavaBlock parentBlock = getParentBlock(); + if (parentBlock != null) { + return parentBlock.getReservedWrap(JavaElementType.MODIFIER_LIST); + } + return null; + } + private ASTNode processField(@NotNull final List result, ASTNode child, @NotNull final AlignmentStrategy alignmentStrategy, @@ -1135,7 +1154,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo @Nullable @Override public Wrap getReservedWrap(IElementType elementType) { - return null; + return myPreferredWraps != null ? myPreferredWraps.get(elementType) : null; } /** @@ -1150,7 +1169,11 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo * @param reservedWrap reserved wrap instance * @param operationType target operation type to associate with the given wrap instance */ - protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { + public void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { + if (myPreferredWraps == null) { + myPreferredWraps = ContainerUtil.newHashMap(); + } + myPreferredWraps.put(operationType, reservedWrap); } @Nullable @@ -1262,6 +1285,14 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo return null; } + public AbstractJavaBlock getParentBlock() { + return myParentBlock; + } + + public void setParentBlock(@NotNull AbstractJavaBlock parentBlock) { + myParentBlock = parentBlock; + } + /** * Allows to answer if special 'variable declaration alignment' strategy should be used for the given node. * I.e. given node is supposed to be parent node of sub-nodes that should be aligned 'by-columns'. diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java index a97d6d12646f..098993124bdf 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java @@ -61,8 +61,13 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{ buildChildren(result, childAlignment, childWrap); - return result; + for (Block block : result) { + if (block instanceof AbstractJavaBlock) { + ((AbstractJavaBlock)block).setParentBlock(this); + } + } + return result; } private void buildChildren(final ArrayList result, final Alignment childAlignment, final Wrap childWrap) { diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java index c74b9c05b19b..478f8ba8d065 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java @@ -127,7 +127,7 @@ public class SimpleJavaBlock extends AbstractJavaBlock { } @Override - protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { + public void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { myReservedWrap.put(operationType, reservedWrap); } diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java index 50bbcbc3b5d6..54965f9eca1e 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java @@ -19,8 +19,8 @@ import com.intellij.formatting.ASTBlock; import com.intellij.formatting.Block; import com.intellij.formatting.Wrap; import com.intellij.lang.ASTNode; -import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.psi.formatter.java.AbstractJavaBlock; import com.intellij.psi.formatter.java.wrap.impl.JavaChildBlockWrapFactory; import com.intellij.psi.formatter.java.wrap.impl.JavaChildWrapArranger; import org.jetbrains.annotations.Nullable; @@ -79,7 +79,7 @@ public class JavaWrapManager { */ @Nullable public Wrap arrangeChildWrap(ASTNode child, ASTNode parent, CommonCodeStyleSettings settings, Wrap suggestedWrap, - ReservedWrapsProvider reservedWrapsProvider) + AbstractJavaBlock reservedWrapsProvider) { return myChildArranger.arrange(child, parent, settings, suggestedWrap, reservedWrapsProvider); } diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java index 5b05ced2d5a1..579e9ae86180 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java @@ -22,6 +22,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.JavaCodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; +import com.intellij.psi.formatter.java.AbstractJavaBlock; import com.intellij.psi.formatter.java.JavaFormatterUtil; import com.intellij.psi.formatter.java.wrap.JavaWrapManager; import com.intellij.psi.formatter.java.wrap.ReservedWrapsProvider; @@ -70,7 +71,7 @@ public class JavaChildWrapArranger { ASTNode parent, CommonCodeStyleSettings settings, Wrap suggestedWrap, - ReservedWrapsProvider reservedWrapsProvider) { + AbstractJavaBlock reservedWrapsProvider) { final JavaCodeStyleSettings javaSettings = settings.getRootSettings().getCustomSettings(JavaCodeStyleSettings.class); ASTNode directParent = child.getTreeParent(); int role = ((CompositeElement)directParent).getChildRole(child); @@ -188,8 +189,9 @@ public class JavaChildWrapArranger { if (javaSettings.DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION && isFieldModifierListWithSingleAnnotation(parent)) { return Wrap.createWrap(WrapType.NONE, false); } - - return Wrap.createWrap(getWrapType(getAnnotationWrapType(parent.getTreeParent(), child, settings)), true); + Wrap wrap = Wrap.createWrap(getWrapType(getAnnotationWrapType(parent.getTreeParent(), child, settings)), true); + putPreferredWrapInParentBlock(reservedWrapsProvider, wrap); + return wrap; } return null; @@ -263,6 +265,13 @@ public class JavaChildWrapArranger { return suggestedWrap; } + private static void putPreferredWrapInParentBlock(@NotNull AbstractJavaBlock block, @NotNull Wrap preferredWrap) { + AbstractJavaBlock parentBlock = block.getParentBlock(); + if (parentBlock != null) { + parentBlock.setReservedWrap(preferredWrap, JavaElementType.MODIFIER_LIST); + } + } + private static boolean isFieldModifierListWithSingleAnnotation(@NotNull ASTNode elem) { ASTNode parent = elem.getTreeParent(); if (parent != null && parent.getElementType() == JavaElementType.FIELD) { diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java index b16e23e83e37..fa960980d297 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java @@ -260,7 +260,6 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest { ); } - @Bombed(user = "Roman Shevchenko", year = 2014, month = Calendar.MARCH, day = 14) public void testWrapMethodAnnotationBeforeParams() { // Inspired by IDEA-59536 getSettings().RIGHT_MARGIN = 90;