Groovy code style settings: blank lines

This commit is contained in:
Max Medvedev
2013-05-02 18:56:50 +04:00
parent b20177d80d
commit ee9186bf36
7 changed files with 132 additions and 47 deletions
@@ -221,6 +221,28 @@ public class GroovyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSe
consumer.showCustomOption(GroovyCodeStyleSettings.class, "SPACE_WITHIN_TUPLE_EXPRESSION", "Tuple assignment expression", CodeStyleSettingsCustomizable.SPACES_WITHIN);
return;
}
if (settingsType == SettingsType.BLANK_LINES_SETTINGS) {
consumer.showStandardOptions(
"KEEP_BLANK_LINES_IN_DECLARATIONS",
"KEEP_BLANK_LINES_IN_CODE",
"KEEP_BLANK_LINES_BEFORE_RBRACE",
"BLANK_LINES_BEFORE_PACKAGE",
"BLANK_LINES_AFTER_PACKAGE",
"BLANK_LINES_BEFORE_IMPORTS",
"BLANK_LINES_AFTER_IMPORTS",
"BLANK_LINES_AROUND_CLASS",
"BLANK_LINES_AFTER_CLASS_HEADER",
//"BLANK_LINES_AFTER_ANONYMOUS_CLASS_HEADER",
"BLANK_LINES_AROUND_FIELD_IN_INTERFACE",
"BLANK_LINES_AROUND_FIELD",
"BLANK_LINES_AROUND_METHOD_IN_INTERFACE",
"BLANK_LINES_AROUND_METHOD",
"BLANK_LINES_BEFORE_METHOD_BODY"
);
return;
}
consumer.showAllStandardOptions();
}
@@ -61,13 +61,13 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAn
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrArrayTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList;
import static org.jetbrains.plugins.groovy.GroovyFileType.GROOVY_LANGUAGE;
import static org.jetbrains.plugins.groovy.formatter.models.spacing.SpacingTokens.*;
import static org.jetbrains.plugins.groovy.formatter.models.spacing.SpacingTokens.GROOVY_DOC_COMMENT;
import static org.jetbrains.plugins.groovy.formatter.models.spacing.SpacingTokens.mCOMMA;
import static org.jetbrains.plugins.groovy.formatter.models.spacing.SpacingTokens.mELVIS;
import static org.jetbrains.plugins.groovy.formatter.models.spacing.SpacingTokens.mQUESTION;
@@ -331,13 +331,51 @@ public class GroovySpacingProcessor extends GroovyElementVisitor {
@Override
public void visitFile(GroovyFileBase file) {
if (myType1 == PACKAGE_DEFINITION && myType2 != mSEMI ||
myType1 == mSEMI && getStatementBySemicolon(myChild1.getPsi()) instanceof GrPackageDefinition) {
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, 100);
if (isAfterElementOrSemi(PACKAGE_DEFINITION)) {
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2);
}
else if (myType2 == PACKAGE_DEFINITION) {
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_BEFORE_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, 100);
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_BEFORE_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2);
}
else if (TYPE_DEFINITION_TYPES.contains(myType1) || TYPE_DEFINITION_TYPES.contains(myType2)) {
if (myType1 == GROOVY_DOC_COMMENT) {
createLF(true);
}
else {
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AROUND_CLASS + 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
}
}
else if (isAfterElementOrSemi(IMPORT_STATEMENT) && myType2 != IMPORT_STATEMENT) { //after imports
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_IMPORTS + 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2);
}
else if (myType1 != IMPORT_STATEMENT && !isSemiAfter(IMPORT_STATEMENT) && myType2 == IMPORT_STATEMENT) { //before imports
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_BEFORE_IMPORTS, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2);
}
else if (isAfterElementOrSemi(IMPORT_STATEMENT) && myType2 == IMPORT_STATEMENT) {
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2);
}
else {
processClassMembers(null);
}
}
private boolean isAfterElementOrSemi(final IElementType elementType) {
return myType1 == elementType && myType2 != mSEMI || isSemiAfter(PACKAGE_DEFINITION);
}
private boolean isSemiAfter(@NotNull IElementType statement) {
return myType1 == mSEMI && getStatementTypeBySemi(myChild1) == statement;
}
private boolean isSemiAfter(@NotNull TokenSet set) {
return myType1 == mSEMI && set.contains(getStatementTypeBySemi(myChild1));
}
@Nullable
private static IElementType getStatementTypeBySemi(@NotNull ASTNode semi) {
final GrTopStatement statement = getStatementBySemicolon(semi.getPsi());
if (statement == null) return null;
return statement.getNode().getElementType();
}
@Nullable
@@ -390,15 +428,22 @@ public class GroovySpacingProcessor extends GroovyElementVisitor {
}
public void visitOpenBlock(GrOpenBlock block) {
final PsiElement parent = block.getParent();
boolean keepInOneLine = parent instanceof GrMethod ? mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE :
mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE;
boolean isMethod = block.getParent() instanceof GrMethod;
boolean keepInOneLine = isMethod ? mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE : mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE;
if (myType1 == mLCURLY && myType2 == mRCURLY) {
createLF(!keepInOneLine);
}
else if (myType1 == mLCURLY || myType2 == mRCURLY) {
else if (myType1 == mLCURLY) {
if (keepInOneLine) {
createDependentLFSpacing(true, mySettings.SPACE_WITHIN_BRACES, block.getTextRange());
}
else {
int lineFeedsCount = isMethod ? mySettings.BLANK_LINES_BEFORE_METHOD_BODY + 1 : 1;
myResult = Spacing.createSpacing(0, 0, lineFeedsCount, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
}
}
else if (myType2 == mRCURLY) {
if (keepInOneLine) {
createDependentLFSpacing(true, mySettings.SPACE_WITHIN_BRACES, block.getTextRange());
}
@@ -436,11 +481,49 @@ public class GroovySpacingProcessor extends GroovyElementVisitor {
else {
createLF(true);
}
} else if (myType1 == mLCURLY) {
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_CLASS_HEADER + 1,
mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
} else if (myType2 == mRCURLY) {
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
}
else if (myType1 == mLCURLY) {
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_CLASS_HEADER + 1, mySettings.KEEP_LINE_BREAKS,
mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
}
else if (myType2 == mRCURLY) {
createLF(true);
}
else {
processClassMembers(typeDefinitionBody);
}
}
private void processClassMembers(@Nullable GrTypeDefinitionBody typeDefinitionBody) {
final boolean isInterface = typeDefinitionBody != null && ((GrTypeDefinition)typeDefinitionBody.getParent()).isInterface();
if (myType2 == mSEMI) return;
if (typeDefinitionBody != null) { //check variable definitions only inside class body
if ((myType1 == VARIABLE_DEFINITION || isSemiAfter(VARIABLE_DEFINITION)) && METHOD_DEFS.contains(myType2)) {
final int minBlankLines = Math.max(
isInterface ? mySettings.BLANK_LINES_AROUND_METHOD_IN_INTERFACE : mySettings.BLANK_LINES_AROUND_METHOD,
isInterface ? mySettings.BLANK_LINES_AROUND_FIELD_IN_INTERFACE : mySettings.BLANK_LINES_AROUND_FIELD
);
myResult = Spacing.createSpacing(0, 0, minBlankLines + 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
return;
}
else if (myType1 == VARIABLE_DEFINITION || isSemiAfter(VARIABLE_DEFINITION) || myType2 == VARIABLE_DEFINITION) {
final int minBlankLines =
isInterface ? mySettings.BLANK_LINES_AROUND_FIELD_IN_INTERFACE : mySettings.BLANK_LINES_AROUND_FIELD;
myResult = Spacing.createSpacing(0, 0, minBlankLines + 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
return;
}
}
if (METHOD_DEFS.contains(myType1) || isSemiAfter(METHOD_DEFS) || METHOD_DEFS.contains((myType2))) {
if (myType1 == GROOVY_DOC_COMMENT) {
createLF(true);
}
else {
final int minBlankLines = isInterface ? mySettings.BLANK_LINES_AROUND_METHOD_IN_INTERFACE : mySettings.BLANK_LINES_AROUND_METHOD;
myResult = Spacing.createSpacing(0, 0, minBlankLines + 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
}
}
}
@@ -661,6 +744,7 @@ public class GroovySpacingProcessor extends GroovyElementVisitor {
@Override
public void visitBinaryExpression(GrBinaryExpression expression) {
@SuppressWarnings("SimplifiableConditionalExpression" )
boolean spaceAround = isLeftOrRight(LOGICAL_OPERATORS) ? mySettings.SPACE_AROUND_LOGICAL_OPERATORS :
isLeftOrRight(EQUALITY_OPERATORS) ? mySettings.SPACE_AROUND_EQUALITY_OPERATORS :
isLeftOrRight(RELATIONAL_OPERATORS) ? mySettings.SPACE_AROUND_RELATIONAL_OPERATORS :
@@ -972,7 +1056,12 @@ public class GroovySpacingProcessor extends GroovyElementVisitor {
}
private int keepBlankLines() {
return mySettings.KEEP_BLANK_LINES_IN_CODE;
if (myType2 == mRCURLY) {
return mySettings.KEEP_BLANK_LINES_BEFORE_RBRACE;
}
else {
return mySettings.KEEP_BLANK_LINES_IN_CODE;
}
}
static boolean isWhiteSpace(final ASTNode node) {
@@ -46,7 +46,6 @@ import static org.jetbrains.plugins.groovy.lang.groovydoc.parser.GroovyDocElemen
import static org.jetbrains.plugins.groovy.lang.groovydoc.parser.GroovyDocElementTypes.GROOVY_DOC_COMMENT;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mTRIPLE_DOT;
import static org.jetbrains.plugins.groovy.lang.lexer.TokenSets.DOTS;
import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.METHOD_DEFS;
/**
* @author ilyas
@@ -57,8 +56,6 @@ public abstract class GroovySpacingProcessorBasic {
private static final Spacing NO_SPACING = Spacing.createSpacing(0, 0, 0, false, 0);
private static final Spacing COMMON_SPACING = Spacing.createSpacing(1, 1, 0, true, 100);
private static final Spacing COMMON_SPACING_WITH_NL = Spacing.createSpacing(1, 1, 1, true, 100);
private static final Spacing IMPORT_BETWEEN_SPACING = Spacing.createSpacing(0, 0, 1, true, 100);
private static final Spacing IMPORT_OTHER_SPACING = Spacing.createSpacing(0, 0, 2, true, 100);
private static final Spacing LAZY_SPACING = Spacing.createSpacing(0, 239, 0, true, 100);
public static Spacing getSpacing(GroovyBlock child1,
@@ -95,21 +92,7 @@ public abstract class GroovySpacingProcessorBasic {
return COMMON_SPACING_WITH_NL;
}
if (METHOD_DEFS.contains(leftType)) {
if (rightType == mSEMI) {
return NO_SPACING;
}
return Spacing.createSpacing(0, 0, settings.BLANK_LINES_AROUND_METHOD + 1, settings.KEEP_LINE_BREAKS, 100);
}
if (METHOD_DEFS.contains(rightType)) {
if (leftNode.getElementType() == GROOVY_DOC_COMMENT) {
return Spacing.createSpacing(0, 0, settings.BLANK_LINES_AROUND_METHOD, settings.KEEP_LINE_BREAKS, 0);
}
return Spacing.createSpacing(0, 0, settings.BLANK_LINES_AROUND_METHOD + 1, settings.KEEP_LINE_BREAKS, 100);
}
if (right != null && right instanceof GrTypeArgumentList) {
if (right instanceof GrTypeArgumentList) {
return NO_SPACING_WITH_NEWLINE;
}
@@ -136,16 +119,6 @@ public abstract class GroovySpacingProcessorBasic {
return NO_SPACING_WITH_NEWLINE;
}
/********** imports ************/
if (IMPORT_STATEMENT.equals(leftType) && IMPORT_STATEMENT.equals(rightType)) {
return IMPORT_BETWEEN_SPACING;
}
if ((IMPORT_STATEMENT.equals(leftType) &&
(!IMPORT_STATEMENT.equals(rightType) && !mSEMI.equals(rightType))) ||
((!IMPORT_STATEMENT.equals(leftType) && !mSEMI.equals(leftType)) && IMPORT_STATEMENT.equals(rightType))) {
return IMPORT_OTHER_SPACING;
}
//todo:check it for multiple assignments
if ((VARIABLE_DEFINITION.equals(leftType) || VARIABLE_DEFINITION.equals(rightType)) &&
!(leftNode.getTreeNext() instanceof PsiErrorElement)) {
@@ -274,6 +274,7 @@ class B {
''', '''\
class A {
}
class B {
}
''')
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -253,7 +253,7 @@ package pack
import foo.Foo
import foo.Bar
import java.test.Test
import java.test.Test
import java.test2.Test2
import static foo.Bar.foo0
import static java.test.Test.foo
@@ -8,4 +8,5 @@ print "foo $s.foo x"
class X {
def getFoo(){2}
}
print "foo ${new X().foo} x"
@@ -1,5 +1,4 @@
import javax.swing.*
// preved!
def frame = new JFrame()