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 boolean ALIGN_MULTILINE_ANNOTATION_PARAMETERS = false;
public int BLANK_LINES_AROUND_INITIALIZER = 1;
}
@@ -341,31 +341,11 @@ public class JavaArrangementVisitor extends JavaRecursiveElementVisitor {
@Override
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) {
return;
}
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;
}
}
parseModifiers(initializer.getModifierList(), entry);
}
@NotNull
@@ -27,6 +27,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
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.group.ArrangementGroupingRule;
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.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -62,7 +64,7 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
// Type
@NotNull private static final Set<ArrangementSettingsToken> SUPPORTED_TYPES =
ContainerUtilRt.newLinkedHashSet(
FIELD, CONSTRUCTOR, METHOD, CLASS, INTERFACE, ENUM, GETTER, SETTER, OVERRIDDEN
FIELD, INIT_BLOCK, CONSTRUCTOR, METHOD, CLASS, INTERFACE, ENUM, GETTER, SETTER, OVERRIDDEN
);
// Modifier
@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 =
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 {
Set<ArrangementSettingsToken> visibilityModifiers = ContainerUtilRt.newHashSet(PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE);
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(SETTER, 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();
@@ -129,6 +139,8 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
for (ArrangementSettingsToken modifier : visibility) {
and(matchRules, FIELD, STATIC, modifier);
}
and(matchRules, INIT_BLOCK, STATIC);
for (ArrangementSettingsToken modifier : visibility) {
and(matchRules, FIELD, FINAL, modifier);
}
@@ -136,6 +148,7 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
and(matchRules, FIELD, modifier);
}
and(matchRules, FIELD);
and(matchRules, INIT_BLOCK);
and(matchRules, CONSTRUCTOR);
and(matchRules, METHOD, STATIC);
and(matchRules, METHOD);
@@ -304,10 +317,14 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
}
CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JavaLanguage.INSTANCE);
JavaCodeStyleSettings javaSettings = settings.getCustomSettings(JavaCodeStyleSettings.class);
if (FIELD.equals(target.getType())) {
if (parent != null && parent.getType() == INTERFACE) {
return commonSettings.BLANK_LINES_AROUND_FIELD_IN_INTERFACE;
}
else if (INIT_BLOCK.equals(previous.getType())) {
return javaSettings.BLANK_LINES_AROUND_INITIALIZER;
}
else {
return commonSettings.BLANK_LINES_AROUND_FIELD;
}
@@ -323,6 +340,9 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
else if (CLASS.equals(target.getType())) {
return commonSettings.BLANK_LINES_AROUND_CLASS;
}
else if (INIT_BLOCK.equals(target.getType())) {
return javaSettings.BLANK_LINES_AROUND_INITIALIZER;
}
else {
return -1;
}
@@ -363,9 +383,10 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
@Override
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;
}
ArrangementSettingsToken type = null;
if (current != null) {
type = ArrangementUtil.parseType(current);
@@ -373,6 +394,15 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
if (type == null) {
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);
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);
}
else if (myRole1 == ChildRole.FIELD) {
int lines = Math.max(getLinesAroundField(), getLinesAroundMethod()) + 1;
// IJ has been keeping initialization block which starts at the same line as a field for a while.
// 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);
int blankLines = myJavaSettings.BLANK_LINES_AROUND_INITIALIZER + 1;
myResult = Spacing.createSpacing(0, mySettings.SPACE_BEFORE_CLASS_LBRACE ? 1 : 0, blankLines, true, mySettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
}
else if (myRole1 == ChildRole.CLASS) {
setAroundClassSpacing();
@@ -450,7 +445,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
setAroundClassSpacing();
}
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);
}
}
@@ -83,9 +83,10 @@ class Test {
expected: '''\
class Test {
public int j;
{ j = 1; }
protected int k;
private int i;
{ j = 1; }
}''',
rules: [rule(FIELD, PUBLIC), rule(FIELD, PROTECTED), rule(FIELD, PRIVATE)])
}
@@ -101,10 +102,11 @@ class Test {
}''',
expected: '''\
class Test {
{ j = 1; }
public int j;
protected int k;
private int i;
{ j = 1; }
}''',
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)]
)
}
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 {
getSettings().BLANK_LINES_AROUND_METHOD = 3;
getJavaSettings().BLANK_LINES_AROUND_INITIALIZER = 3;
doTextTest(
"class T {\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 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 INIT_BLOCK = invertible("INITIALIZER BLOCK", 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);