From 52b2832da697ece5c56e095d10a8e0a09d67d436 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 1 Sep 2014 19:12:51 +0400 Subject: [PATCH] Added option to prevent wrapping after single field annotation (IDEA-80173) --- ...JavaLanguageCodeStyleSettingsProvider.java | 5 +++ .../psi/codeStyle/JavaCodeStyleSettings.java | 1 + .../java/JavaSpacePropertyProcessor.java | 2 +- .../java/wrap/impl/JavaChildWrapArranger.java | 26 +++++++++++++++- .../formatter/java/JavaFormatterWrapTest.java | 31 ++++++++++++++++++- .../src/messages/ApplicationBundle.properties | 4 ++- 6 files changed, 65 insertions(+), 4 deletions(-) diff --git a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java index 2f684304ae58..6b5c1fe87e64 100644 --- a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java +++ b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java @@ -19,6 +19,7 @@ import com.intellij.application.options.IndentOptionsEditor; import com.intellij.application.options.JavaIndentOptionsEditor; import com.intellij.lang.Language; import com.intellij.lang.java.JavaLanguage; +import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.pom.java.LanguageLevel; @@ -69,6 +70,10 @@ public class JavaLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett consumer.showCustomOption(JavaCodeStyleSettings.class, "SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER", "Before opening angle bracket", groupName); consumer.showCustomOption(JavaCodeStyleSettings.class, "SPACE_AROUND_TYPE_BOUNDS_IN_TYPE_PARAMETERS", "Around type bounds", groupName); } + else if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) { + String groupName = ApplicationBundle.message("wrapping.fields.annotation"); + consumer.showCustomOption(JavaCodeStyleSettings.class, "DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION", "Do not wrap after single annotation", groupName); + } } @Override diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java b/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java index 7e117e3ed0c7..b7d0f71fe00d 100644 --- a/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java +++ b/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java @@ -30,4 +30,5 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings { public boolean SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER = false; public boolean SPACE_AROUND_TYPE_BOUNDS_IN_TYPE_PARAMETERS = true; + public boolean DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION = false; } diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java index 4d225e65d88b..5230805aa03c 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java @@ -1129,7 +1129,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { @Override public void visitModifierList(PsiModifierList list) { - createSpaceInCode(true); + myResult = Spacing.createSpacing(1, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); } @Override 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 954f03248b9c..5b05ced2d5a1 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 @@ -20,6 +20,7 @@ import com.intellij.formatting.WrapType; import com.intellij.lang.ASTNode; 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.JavaFormatterUtil; import com.intellij.psi.formatter.java.wrap.JavaWrapManager; @@ -29,6 +30,7 @@ import com.intellij.psi.impl.source.tree.CompositeElement; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.tree.IElementType; import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static com.intellij.psi.formatter.java.JavaFormatterUtil.getWrapType; @@ -69,6 +71,7 @@ public class JavaChildWrapArranger { CommonCodeStyleSettings settings, Wrap suggestedWrap, ReservedWrapsProvider reservedWrapsProvider) { + final JavaCodeStyleSettings javaSettings = settings.getRootSettings().getCustomSettings(JavaCodeStyleSettings.class); ASTNode directParent = child.getTreeParent(); int role = ((CompositeElement)directParent).getChildRole(child); @@ -153,7 +156,7 @@ public class JavaChildWrapArranger { if (prev != null && prev.getElementType() == JavaElementType.MODIFIER_LIST) { ASTNode last = prev.getLastChildNode(); if (last != null && last.getElementType() == JavaElementType.ANNOTATION) { - if (isTypeAnnotation(last.getPsi())) { + if (isTypeAnnotation(last.getPsi()) || javaSettings.DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION && isFieldModifierListWithSingleAnnotation(prev)) { return Wrap.createWrap(WrapType.NONE, false); } else { @@ -182,6 +185,10 @@ public class JavaChildWrapArranger { ASTNode prev = FormatterUtil.getPreviousNonWhitespaceSibling(child); if (prev != null && prev.getElementType() == JavaElementType.ANNOTATION) { + 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); } @@ -256,6 +263,23 @@ public class JavaChildWrapArranger { return suggestedWrap; } + private static boolean isFieldModifierListWithSingleAnnotation(@NotNull ASTNode elem) { + ASTNode parent = elem.getTreeParent(); + if (parent != null && parent.getElementType() == JavaElementType.FIELD) { + return isModifierListWithSingleAnnotation(elem); + } + return false; + } + + private static boolean isModifierListWithSingleAnnotation(@NotNull ASTNode elem) { + if (elem.getPsi() instanceof PsiModifierList) { + if (((PsiModifierList)elem.getPsi()).getAnnotations().length == 1) { + return true; + } + } + return false; + } + private static int getAnnotationWrapType(ASTNode parent, ASTNode child, CommonCodeStyleSettings settings) { IElementType nodeType = parent.getElementType(); 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 c06370b06743..b16e23e83e37 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 @@ -16,7 +16,6 @@ package com.intellij.psi.formatter.java; import com.intellij.idea.Bombed; -import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; @@ -448,4 +447,34 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest { " public @TA String m();\n" + "}"); } + + public void testKeepSingleFieldAnnotationOnSameLine() { + getJavaSettings().DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION = true; + doClassTest( + "@NotNull public String result = \"OK\"\n" + + "@NotNull String newResult = \"OK\"\n" + + "@NotNull\n" + + "@Deprecated public String bad = \"bad\"", + + "@NotNull public String result = \"OK\"\n" + + "@NotNull String newResult = \"OK\"\n" + + "@NotNull\n" + + "@Deprecated\n" + + "public String bad = \"bad\"" + ); + } + + public void testMoveSingleAnnotationOnSameLine() { + getJavaSettings().DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION = true; + getSettings().KEEP_LINE_BREAKS = false; + doClassTest( + "@NotNull\n" + + "public String test = \"tst\";\n" + + "String ok = \"ok\";\n", + "@NotNull public String test = \"tst\";\n" + + "String ok = \"ok\";\n" + ); + } + + } diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 053657bf7738..c09c1fc51ca3 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -645,7 +645,9 @@ combobox.richcopy.color.scheme=Color scheme combobox.richcopy.color.scheme.active=Active scheme settings.code.style.default.general=Default (General) +wrapping.wrap.if.multiple.annotations=Wrap if multiple +wrapping.after.annotations=After last field annotation reformat.changed.text.file.too.big.notification.groupId=Reformat changed text reformat.changed.text.file.too.big.notification.title=Couldn't calculate changed ranges -reformat.changed.text.file.too.big.notification.text=file {0} is too big or there are too many changes +reformat.changed.text.file.too.big.notification.text=file {0} is too big or there are too many changes \ No newline at end of file