Added option to prevent wrapping after single field annotation (IDEA-80173)

This commit is contained in:
Yaroslav Lepenkin
2014-09-01 19:16:38 +04:00
parent 8d7040e88e
commit 52b2832da6
6 changed files with 65 additions and 4 deletions
@@ -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
@@ -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;
}
@@ -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
@@ -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();
@@ -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"
);
}
}
@@ -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