Supported "initializer block" arrangement entry (IDEA-95115)

Previous behaviour was to treat initializer block as field and stick it with previous field, now it's eliminated with matching and rearranging according to matching rules. See comments also in [CR-IC-6618]
This commit is contained in:
Yaroslav Lepenkin
2014-10-27 22:19:07 +04:00
parent 31c8033856
commit 98b4ec43a6
8 changed files with 126 additions and 34 deletions
@@ -35,4 +35,6 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings {
public int ANNOTATION_PARAMETER_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; public int ANNOTATION_PARAMETER_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
public boolean ALIGN_MULTILINE_ANNOTATION_PARAMETERS = false; public boolean ALIGN_MULTILINE_ANNOTATION_PARAMETERS = false;
public int BLANK_LINES_AROUND_INITIALIZER = 1;
} }
@@ -341,31 +341,11 @@ public class JavaArrangementVisitor extends JavaRecursiveElementVisitor {
@Override @Override
public void visitClassInitializer(PsiClassInitializer initializer) { public void visitClassInitializer(PsiClassInitializer initializer) {
JavaElementArrangementEntry entry = createNewEntry(initializer, initializer.getTextRange(), FIELD, null, true); JavaElementArrangementEntry entry = createNewEntry(initializer, initializer.getTextRange(), INIT_BLOCK, null, true);
if (entry == null) { if (entry == null) {
return; return;
} }
parseModifiers(initializer.getModifierList(), entry);
PsiElement classLBrace = null;
PsiClass clazz = initializer.getContainingClass();
if (clazz != null) {
classLBrace = clazz.getLBrace();
}
for (PsiElement e = initializer.getPrevSibling(); e != null; e = e.getPrevSibling()) {
JavaElementArrangementEntry prevEntry;
if (e == classLBrace) {
prevEntry = myEntries.get(clazz);
}
else {
prevEntry = myEntries.get(e);
}
if (prevEntry != null) {
entry.addDependency(prevEntry);
}
if (!(e instanceof PsiWhiteSpace)) {
break;
}
}
} }
@NotNull @NotNull
@@ -27,6 +27,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine; import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule; import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher; import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
@@ -36,6 +37,7 @@ import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchConditio
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition; import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition; import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.*; import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -62,7 +64,7 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
// Type // Type
@NotNull private static final Set<ArrangementSettingsToken> SUPPORTED_TYPES = @NotNull private static final Set<ArrangementSettingsToken> SUPPORTED_TYPES =
ContainerUtilRt.newLinkedHashSet( ContainerUtilRt.newLinkedHashSet(
FIELD, CONSTRUCTOR, METHOD, CLASS, INTERFACE, ENUM, GETTER, SETTER, OVERRIDDEN FIELD, INIT_BLOCK, CONSTRUCTOR, METHOD, CLASS, INTERFACE, ENUM, GETTER, SETTER, OVERRIDDEN
); );
// Modifier // Modifier
@NotNull private static final Set<ArrangementSettingsToken> SUPPORTED_MODIFIERS = @NotNull private static final Set<ArrangementSettingsToken> SUPPORTED_MODIFIERS =
@@ -79,6 +81,9 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
@NotNull private static final Collection<Set<ArrangementSettingsToken>> MUTEXES = @NotNull private static final Collection<Set<ArrangementSettingsToken>> MUTEXES =
ContainerUtilRt.newArrayList(); ContainerUtilRt.newArrayList();
private static final Set<ArrangementSettingsToken> TYPES_WITH_DISABLED_ORDER = ContainerUtil.newHashSet();
private static final Set<ArrangementSettingsToken> TYPES_WITH_DISABLED_NAME_MATCH = ContainerUtil.newHashSet();
static { static {
Set<ArrangementSettingsToken> visibilityModifiers = ContainerUtilRt.newHashSet(PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE); Set<ArrangementSettingsToken> visibilityModifiers = ContainerUtilRt.newHashSet(PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE);
MUTEXES.add(visibilityModifiers); MUTEXES.add(visibilityModifiers);
@@ -96,6 +101,11 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
MODIFIERS_BY_TYPE.put(GETTER, ContainerUtilRt.<ArrangementSettingsToken>newHashSet()); MODIFIERS_BY_TYPE.put(GETTER, ContainerUtilRt.<ArrangementSettingsToken>newHashSet());
MODIFIERS_BY_TYPE.put(SETTER, ContainerUtilRt.<ArrangementSettingsToken>newHashSet()); MODIFIERS_BY_TYPE.put(SETTER, ContainerUtilRt.<ArrangementSettingsToken>newHashSet());
MODIFIERS_BY_TYPE.put(OVERRIDDEN, ContainerUtilRt.<ArrangementSettingsToken>newHashSet()); MODIFIERS_BY_TYPE.put(OVERRIDDEN, ContainerUtilRt.<ArrangementSettingsToken>newHashSet());
MODIFIERS_BY_TYPE.put(INIT_BLOCK, ContainerUtilRt.newHashSet(STATIC));
TYPES_WITH_DISABLED_ORDER.add(INIT_BLOCK);
TYPES_WITH_DISABLED_NAME_MATCH.add(INIT_BLOCK);
} }
private static final Map<ArrangementSettingsToken, List<ArrangementSettingsToken>> GROUPING_RULES = ContainerUtilRt.newLinkedHashMap(); private static final Map<ArrangementSettingsToken, List<ArrangementSettingsToken>> GROUPING_RULES = ContainerUtilRt.newLinkedHashMap();
@@ -129,6 +139,8 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
for (ArrangementSettingsToken modifier : visibility) { for (ArrangementSettingsToken modifier : visibility) {
and(matchRules, FIELD, STATIC, modifier); and(matchRules, FIELD, STATIC, modifier);
} }
and(matchRules, INIT_BLOCK, STATIC);
for (ArrangementSettingsToken modifier : visibility) { for (ArrangementSettingsToken modifier : visibility) {
and(matchRules, FIELD, FINAL, modifier); and(matchRules, FIELD, FINAL, modifier);
} }
@@ -136,6 +148,7 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
and(matchRules, FIELD, modifier); and(matchRules, FIELD, modifier);
} }
and(matchRules, FIELD); and(matchRules, FIELD);
and(matchRules, INIT_BLOCK);
and(matchRules, CONSTRUCTOR); and(matchRules, CONSTRUCTOR);
and(matchRules, METHOD, STATIC); and(matchRules, METHOD, STATIC);
and(matchRules, METHOD); and(matchRules, METHOD);
@@ -304,10 +317,14 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
} }
CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JavaLanguage.INSTANCE); CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JavaLanguage.INSTANCE);
JavaCodeStyleSettings javaSettings = settings.getCustomSettings(JavaCodeStyleSettings.class);
if (FIELD.equals(target.getType())) { if (FIELD.equals(target.getType())) {
if (parent != null && parent.getType() == INTERFACE) { if (parent != null && parent.getType() == INTERFACE) {
return commonSettings.BLANK_LINES_AROUND_FIELD_IN_INTERFACE; return commonSettings.BLANK_LINES_AROUND_FIELD_IN_INTERFACE;
} }
else if (INIT_BLOCK.equals(previous.getType())) {
return javaSettings.BLANK_LINES_AROUND_INITIALIZER;
}
else { else {
return commonSettings.BLANK_LINES_AROUND_FIELD; return commonSettings.BLANK_LINES_AROUND_FIELD;
} }
@@ -323,6 +340,9 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
else if (CLASS.equals(target.getType())) { else if (CLASS.equals(target.getType())) {
return commonSettings.BLANK_LINES_AROUND_CLASS; return commonSettings.BLANK_LINES_AROUND_CLASS;
} }
else if (INIT_BLOCK.equals(target.getType())) {
return javaSettings.BLANK_LINES_AROUND_INITIALIZER;
}
else { else {
return -1; return -1;
} }
@@ -363,9 +383,10 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
@Override @Override
public boolean isEnabled(@NotNull ArrangementSettingsToken token, @Nullable ArrangementMatchCondition current) { public boolean isEnabled(@NotNull ArrangementSettingsToken token, @Nullable ArrangementMatchCondition current) {
if (SUPPORTED_TYPES.contains(token) || SUPPORTED_ORDERS.contains(token) || StdArrangementTokens.Regexp.NAME.equals(token)) { if (SUPPORTED_TYPES.contains(token)) {
return true; return true;
} }
ArrangementSettingsToken type = null; ArrangementSettingsToken type = null;
if (current != null) { if (current != null) {
type = ArrangementUtil.parseType(current); type = ArrangementUtil.parseType(current);
@@ -373,6 +394,15 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
if (type == null) { if (type == null) {
type = NO_TYPE; type = NO_TYPE;
} }
if (SUPPORTED_ORDERS.contains(token)) {
return !TYPES_WITH_DISABLED_ORDER.contains(type);
}
if (StdArrangementTokens.Regexp.NAME.equals(token)) {
return !TYPES_WITH_DISABLED_NAME_MATCH.contains(type);
}
Set<ArrangementSettingsToken> modifiers = MODIFIERS_BY_TYPE.get(type); Set<ArrangementSettingsToken> modifiers = MODIFIERS_BY_TYPE.get(type);
return modifiers != null && modifiers.contains(token); return modifiers != null && modifiers.contains(token);
} }
@@ -425,13 +425,8 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
} }
else if (myRole1 == ChildRole.FIELD) { else if (myRole1 == ChildRole.FIELD) {
int lines = Math.max(getLinesAroundField(), getLinesAroundMethod()) + 1; int blankLines = myJavaSettings.BLANK_LINES_AROUND_INITIALIZER + 1;
// IJ has been keeping initialization block which starts at the same line as a field for a while. myResult = Spacing.createSpacing(0, mySettings.SPACE_BEFORE_CLASS_LBRACE ? 1 : 0, blankLines, true, mySettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
// However, it's not convenient for a situation when particular code is created via PSI - it's easier to not bothering
// with whitespace elements when inserting, say, new initialization blocks. That's why we don't enforce new line
// only during explicit reformatting ('Reformat' action).
//int minLineFeeds = FormatterUtil.isFormatterCalledExplicitly() ? 0 : 1;
myResult = Spacing.createSpacing(0, mySettings.SPACE_BEFORE_CLASS_LBRACE ? 1 : 0, 1, true, mySettings.KEEP_BLANK_LINES_BEFORE_RBRACE, lines);
} }
else if (myRole1 == ChildRole.CLASS) { else if (myRole1 == ChildRole.CLASS) {
setAroundClassSpacing(); setAroundClassSpacing();
@@ -450,7 +445,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
setAroundClassSpacing(); setAroundClassSpacing();
} }
else { else {
final int blankLines = getLinesAroundMethod() + 1; final int blankLines = myJavaSettings.BLANK_LINES_AROUND_INITIALIZER + 1;
myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, blankLines, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS); myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, blankLines, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
} }
} }
@@ -83,9 +83,10 @@ class Test {
expected: '''\ expected: '''\
class Test { class Test {
public int j; public int j;
{ j = 1; }
protected int k; protected int k;
private int i; private int i;
{ j = 1; }
}''', }''',
rules: [rule(FIELD, PUBLIC), rule(FIELD, PROTECTED), rule(FIELD, PRIVATE)]) rules: [rule(FIELD, PUBLIC), rule(FIELD, PROTECTED), rule(FIELD, PRIVATE)])
} }
@@ -101,10 +102,11 @@ class Test {
}''', }''',
expected: '''\ expected: '''\
class Test { class Test {
{ j = 1; }
public int j; public int j;
protected int k; protected int k;
private int i; private int i;
{ j = 1; }
}''', }''',
rules: [rule(FIELD, PUBLIC), rule(FIELD, PROTECTED), rule(FIELD, PRIVATE)]) rules: [rule(FIELD, PUBLIC), rule(FIELD, PROTECTED), rule(FIELD, PRIVATE)])
} }
@@ -569,4 +569,85 @@ class B extends A {
rules: [rule(PUBLIC, METHOD), rule(PRIVATE, METHOD)] rules: [rule(PUBLIC, METHOD), rule(PRIVATE, METHOD)]
) )
} }
void "test initializer block after fields"() {
doTest(
initial: '''\
public class NewOneClass {
{
a = 1;
}
int a;
{
b = 5;
}
int b;
}
''',
expected: '''\
public class NewOneClass {
int a;
int b;
{
a = 1;
}
{
b = 5;
}
}
''',
rules: [rule(FIELD), rule(INIT_BLOCK)]
)
}
void "test static initializer block"() {
doTest(
initial: '''\
public class NewOneClass {
static {
a = 1;
}
static int a;
{
b = 5;
}
int b;
}
''',
expected: '''\
public class NewOneClass {
static int a;
static {
a = 1;
}
int b;
{
b = 5;
}
}
''',
rules: [rule(STATIC, FIELD), rule(STATIC, INIT_BLOCK), rule(FIELD), rule(INIT_BLOCK)]
)
}
} }
@@ -25,6 +25,7 @@ public class JavaFormatterBlankLinesTest extends AbstractJavaFormatterTest {
public void testBlankLinesAroundClassInitializationBlock() throws Exception { public void testBlankLinesAroundClassInitializationBlock() throws Exception {
getSettings().BLANK_LINES_AROUND_METHOD = 3; getSettings().BLANK_LINES_AROUND_METHOD = 3;
getJavaSettings().BLANK_LINES_AROUND_INITIALIZER = 3;
doTextTest( doTextTest(
"class T {\n" + "class T {\n" +
" private final DecimalFormat fmt = new DecimalFormat();\n" + " private final DecimalFormat fmt = new DecimalFormat();\n" +
@@ -164,6 +164,7 @@ public class StdArrangementTokens {
@NotNull public static final ArrangementSettingsToken PROPERTY = invertible("PROPERTY", StdArrangementTokenType.ENTRY_TYPE); @NotNull public static final ArrangementSettingsToken PROPERTY = invertible("PROPERTY", StdArrangementTokenType.ENTRY_TYPE);
@NotNull public static final ArrangementSettingsToken EVENT_HANDLER = invertible("EVENT_HANDLER", StdArrangementTokenType.ENTRY_TYPE); @NotNull public static final ArrangementSettingsToken EVENT_HANDLER = invertible("EVENT_HANDLER", StdArrangementTokenType.ENTRY_TYPE);
@NotNull public static final ArrangementSettingsToken STATIC_INIT = invertible("STATIC_INIT", StdArrangementTokenType.ENTRY_TYPE); @NotNull public static final ArrangementSettingsToken STATIC_INIT = invertible("STATIC_INIT", StdArrangementTokenType.ENTRY_TYPE);
@NotNull public static final ArrangementSettingsToken INIT_BLOCK = invertible("INITIALIZER BLOCK", StdArrangementTokenType.ENTRY_TYPE);
@NotNull public static final ArrangementSettingsToken NAMESPACE = invertible("NAMESPACE", StdArrangementTokenType.ENTRY_TYPE); @NotNull public static final ArrangementSettingsToken NAMESPACE = invertible("NAMESPACE", StdArrangementTokenType.ENTRY_TYPE);
@NotNull public static final ArrangementSettingsToken TRAIT = invertible("TRAIT", StdArrangementTokenType.ENTRY_TYPE); @NotNull public static final ArrangementSettingsToken TRAIT = invertible("TRAIT", StdArrangementTokenType.ENTRY_TYPE);