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 a8b334419772..62e47570e221 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 @@ -53,23 +53,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo private static final Logger LOG = Logger.getInstance("#com.intellij.psi.formatter.java.AbstractJavaBlock"); - protected static final Set ALIGN_IN_COLUMNS_ELEMENT_TYPES = ContainerUtil.newHashSet(JavaElementType.FIELD); - - private static final AlignmentInColumnsConfig ALIGNMENT_IN_COLUMNS_CONFIG = new AlignmentInColumnsConfig( - TokenSet.create(JavaTokenType.IDENTIFIER), - JavaJspElementType.WHITE_SPACE_BIT_SET, - ElementType.JAVA_COMMENT_BIT_SET, - TokenSet.create(JavaTokenType.EQ), - TokenSet.create(JavaElementType.FIELD) - ); - - private static final Set VAR_DECLARATION_ELEMENT_TYPES_TO_ALIGN = ContainerUtil.newHashSet( - JavaElementType.MODIFIER_LIST, - JavaElementType.TYPE, - JavaTokenType.IDENTIFIER, - JavaTokenType.EQ - ); - @NotNull protected final CommonCodeStyleSettings mySettings; @NotNull protected final JavaCodeStyleSettings myJavaSettings; protected final CommonCodeStyleSettings.IndentOptions myIndentSettings; @@ -84,7 +67,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo protected Alignment myReservedAlignment2; private final JavaWrapManager myWrapManager; - private final AlignmentInColumnsHelper myAlignmentInColumnsHelper; private Map myPreferredWraps; private AbstractJavaBlock myParentBlock; @@ -95,7 +77,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo @NotNull final CommonCodeStyleSettings settings, @NotNull JavaCodeStyleSettings javaSettings) { - this(node, wrap, indent, settings, javaSettings, JavaWrapManager.INSTANCE, AlignmentStrategy.wrap(alignment), AlignmentInColumnsHelper.INSTANCE); + this(node, wrap, indent, settings, javaSettings, JavaWrapManager.INSTANCE, AlignmentStrategy.wrap(alignment)); } protected AbstractJavaBlock(@NotNull final ASTNode node, @@ -105,7 +87,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo @NotNull final CommonCodeStyleSettings settings, @NotNull JavaCodeStyleSettings javaSettings) { - this(node, wrap, indent, settings, javaSettings, JavaWrapManager.INSTANCE, alignmentStrategy, AlignmentInColumnsHelper.INSTANCE); + this(node, wrap, indent, settings, javaSettings, JavaWrapManager.INSTANCE, alignmentStrategy); } protected AbstractJavaBlock(@NotNull final ASTNode node, @@ -114,8 +96,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo @NotNull final CommonCodeStyleSettings settings, @NotNull JavaCodeStyleSettings javaSettings, final JavaWrapManager wrapManager, - @NotNull final AlignmentStrategy alignmentStrategy, - AlignmentInColumnsHelper alignmentInColumnsHelper) { + @NotNull final AlignmentStrategy alignmentStrategy) { super(node, wrap, createBlockAlignment(alignmentStrategy, node)); mySettings = settings; myJavaSettings = javaSettings; @@ -123,7 +104,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo myIndent = indent; myWrapManager = wrapManager; myAlignmentStrategy = alignmentStrategy; - myAlignmentInColumnsHelper = alignmentInColumnsHelper; } @Nullable @@ -708,7 +688,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo if (role == ChildRole.MODIFIER_LIST) return defaultAlignment; return null; } - else if (ALIGN_IN_COLUMNS_ELEMENT_TYPES.contains(nodeType)) { + else if (JavaElementType.FIELD == nodeType) { return getVariableDeclarationSubElementAlignment(child); } else if (nodeType == JavaElementType.METHOD) { @@ -1166,7 +1146,10 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo processChild(localResult, child, AlignmentStrategy.getNullStrategy(), null, Indent.getNoneIndent()); child = child.getTreeNext(); - AlignmentStrategy varDeclarationAlignmentStrategy = AlignmentStrategy.createAlignmentPerTypeStrategy(VAR_DECLARATION_ELEMENT_TYPES_TO_ALIGN, JavaElementType.FIELD, true); + ChildAlignmentStrategyProvider alignmentStrategyProvider = ChildAlignmentStrategyProvider.NULL_STRATEGY_PROVIDER; + if (mySettings.ALIGN_GROUP_FIELD_DECLARATIONS) { + alignmentStrategyProvider = new SubsequentFieldAligner(mySettings); + } while (child != null) { if (FormatterUtil.containsWhiteSpacesOnly(child)) { @@ -1174,12 +1157,8 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo continue; } - if (!ElementType.JAVA_COMMENT_BIT_SET.contains(child.getElementType()) && !shouldUseVarDeclarationAlignment(child)) { - varDeclarationAlignmentStrategy = AlignmentStrategy.createAlignmentPerTypeStrategy(VAR_DECLARATION_ELEMENT_TYPES_TO_ALIGN, JavaElementType.FIELD, true); - } - Indent childIndent = getIndentForCodeBlock(child, childrenIndent); - AlignmentStrategy alignmentStrategyToUse = getAlignmentStrategy(child, varDeclarationAlignmentStrategy); + AlignmentStrategy alignmentStrategyToUse = alignmentStrategyProvider.getNextChildStrategy(child); final boolean isRBrace = isRBrace(child); child = processChild(localResult, child, alignmentStrategyToUse, childWrap, childIndent); @@ -1197,12 +1176,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo return null; } - private AlignmentStrategy getAlignmentStrategy(ASTNode child, AlignmentStrategy varDeclarationAlignmentStrategy) { - return ALIGN_IN_COLUMNS_ELEMENT_TYPES.contains(child.getElementType()) - ? varDeclarationAlignmentStrategy - : AlignmentStrategy.getNullStrategy(); - } - private Indent getIndentForCodeBlock(ASTNode child, int childrenIndent) { if (child.getElementType() == JavaElementType.CODE_BLOCK && (getBraceStyle() == CommonCodeStyleSettings.NEXT_LINE_SHIFTED @@ -1222,13 +1195,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo myParentBlock = parentBlock; } - protected boolean shouldUseVarDeclarationAlignment(@NotNull ASTNode node) { - return mySettings.ALIGN_GROUP_FIELD_DECLARATIONS && ALIGN_IN_COLUMNS_ELEMENT_TYPES.contains(node.getElementType()) - && (!myAlignmentInColumnsHelper.useDifferentVarDeclarationAlignment( - node, ALIGNMENT_IN_COLUMNS_CONFIG, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS) - || compoundFieldPart(node)); - } - @NotNull public SyntheticCodeBlock createCodeBlockBlock(final List localResult, final Indent indent, final int childrenIndent) { final SyntheticCodeBlock result = new SyntheticCodeBlock(localResult, null, getSettings(), myJavaSettings, indent, null); diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/ChildAlignmentStrategyProvider.java b/java/java-impl/src/com/intellij/psi/formatter/java/ChildAlignmentStrategyProvider.java new file mode 100644 index 000000000000..428a399bf2c0 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/formatter/java/ChildAlignmentStrategyProvider.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.formatter.java; + +import com.intellij.formatting.alignment.AlignmentStrategy; +import com.intellij.lang.ASTNode; +import org.jetbrains.annotations.NotNull; + +public interface ChildAlignmentStrategyProvider { + + AlignmentStrategy getNextChildStrategy(@NotNull ASTNode child); + + ChildAlignmentStrategyProvider NULL_STRATEGY_PROVIDER = new ChildAlignmentStrategyProvider() { + @Override + public AlignmentStrategy getNextChildStrategy(@NotNull ASTNode child) { + return AlignmentStrategy.getNullStrategy(); + } + }; + +} 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 c5091abe4df8..cadcd51a7ec0 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 @@ -115,7 +115,7 @@ public class SimpleJavaBlock extends AbstractJavaBlock { } private AlignmentStrategy getAlignmentStrategy(ASTNode child) { - return ALIGN_IN_COLUMNS_ELEMENT_TYPES.contains(myNode.getElementType()) + return JavaElementType.FIELD == myNode.getElementType() ? myAlignmentStrategy : AlignmentStrategy.wrap(chooseAlignment(myReservedAlignment, myReservedAlignment2, child)); } diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/SubsequentFieldAligner.java b/java/java-impl/src/com/intellij/psi/formatter/java/SubsequentFieldAligner.java new file mode 100644 index 000000000000..63889cf55ccd --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/formatter/java/SubsequentFieldAligner.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.formatter.java; + +import com.intellij.formatting.alignment.AlignmentInColumnsConfig; +import com.intellij.formatting.alignment.AlignmentInColumnsHelper; +import com.intellij.formatting.alignment.AlignmentStrategy; +import com.intellij.lang.ASTNode; +import com.intellij.psi.JavaTokenType; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.psi.impl.source.tree.ElementType; +import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.impl.source.tree.JavaJspElementType; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +public class SubsequentFieldAligner implements ChildAlignmentStrategyProvider { + + private final static Set TYPES_TO_ALIGN = ContainerUtil.newHashSet( + JavaElementType.MODIFIER_LIST, + JavaElementType.TYPE, + JavaTokenType.IDENTIFIER, + JavaTokenType.EQ + ); + + private static final AlignmentInColumnsConfig ALIGNMENT_IN_COLUMNS_CONFIG = new AlignmentInColumnsConfig( + TokenSet.create(JavaTokenType.IDENTIFIER), + JavaJspElementType.WHITE_SPACE_BIT_SET, + ElementType.JAVA_COMMENT_BIT_SET, + TokenSet.create(JavaTokenType.EQ), + TokenSet.create(JavaElementType.FIELD) + ); + + private final CommonCodeStyleSettings mySettings; + private final AlignmentInColumnsHelper myAlignmentInColumnsHelper; + private AlignmentStrategy myAlignmentStrategy; + + public SubsequentFieldAligner(@NotNull CommonCodeStyleSettings settings) { + myAlignmentInColumnsHelper = AlignmentInColumnsHelper.INSTANCE; + myAlignmentStrategy = newAlignmentStrategy(); + mySettings = settings; + } + + private AlignmentStrategy newAlignmentStrategy() { + return AlignmentStrategy.createAlignmentPerTypeStrategy(TYPES_TO_ALIGN, JavaElementType.FIELD, true); + } + + @Override + public AlignmentStrategy getNextChildStrategy(@NotNull ASTNode child) { + if (!ElementType.JAVA_COMMENT_BIT_SET.contains(child.getElementType()) && !shouldUseVarDeclarationAlignment(child)) { + myAlignmentStrategy = newAlignmentStrategy(); + } + + return JavaElementType.FIELD == child.getElementType() + ? myAlignmentStrategy + : AlignmentStrategy.getNullStrategy(); + } + + protected boolean shouldUseVarDeclarationAlignment(@NotNull ASTNode node) { + return JavaElementType.FIELD == node.getElementType() + && (!myAlignmentInColumnsHelper.useDifferentVarDeclarationAlignment(node, ALIGNMENT_IN_COLUMNS_CONFIG, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS) + || MultipleFieldDeclarationHelper.compoundFieldPart(node)); + } + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java index ac4aaa2bda42..8068d31d0681 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java @@ -238,6 +238,23 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest { "}" ); } + + public void testDoNotAlignIfNotEnabled() { + getSettings().ALIGN_GROUP_FIELD_DECLARATIONS = false; + doTextTest( + "public class Test {\n" + + "private Long field2 = null;\n" + + "private final Object field1 = null;\n" + + "private int i = 1;\n" + + "}", + + "public class Test {\n" + + " private Long field2 = null;\n" + + " private final Object field1 = null;\n" + + " private int i = 1;\n" + + "}" + ); + } public void testAnnotatedAndNonAnnotatedFieldsInColumnsAlignment() { // Inspired by IDEA-60237