From c462a235056a7e8c4a6cc84f9bfd1952f59fbe8d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 4 Nov 2011 17:02:14 +0100 Subject: [PATCH 1/3] rule-based API for spacing calculation in formatter; use it in Python formatter --- .../com/jetbrains/python/PyElementTypes.java | 4 +- .../com/jetbrains/python/PyTokenTypes.java | 1 + .../jetbrains/python/formatter/PyBlock.java | 182 +----------------- .../PythonFormattingModelBuilder.java | 58 +++++- 4 files changed, 67 insertions(+), 178 deletions(-) diff --git a/python/src/com/jetbrains/python/PyElementTypes.java b/python/src/com/jetbrains/python/PyElementTypes.java index de8d6eee8e4a..12685701da0f 100644 --- a/python/src/com/jetbrains/python/PyElementTypes.java +++ b/python/src/com/jetbrains/python/PyElementTypes.java @@ -131,5 +131,7 @@ public interface PyElementTypes { TokenSet PARTS = TokenSet.create(IF_PART_IF, IF_PART_ELIF, FOR_PART, WHILE_PART, TRY_PART, FINALLY_PART, ELSE_PART); TokenSet ELIFS = TokenSet.create(IF_PART_ELIF); - + TokenSet STAR_PARAMETERS = TokenSet.create(NAMED_PARAMETER, STAR_ARGUMENT_EXPRESSION, STAR_EXPRESSION); + TokenSet CLASS_OR_FUNCTION = TokenSet.create(CLASS_DECLARATION, FUNCTION_DECLARATION); + TokenSet IMPORT_STATEMENTS = TokenSet.create(IMPORT_STATEMENT, FROM_IMPORT_STATEMENT); } diff --git a/python/src/com/jetbrains/python/PyTokenTypes.java b/python/src/com/jetbrains/python/PyTokenTypes.java index b66d80a31bc1..21c909462028 100644 --- a/python/src/com/jetbrains/python/PyTokenTypes.java +++ b/python/src/com/jetbrains/python/PyTokenTypes.java @@ -135,6 +135,7 @@ public class PyTokenTypes { public static final TokenSet SHIFT_OPERATIONS = TokenSet.create(LTLT, GTGT); public static final TokenSet ADDITIVE_OPERATIONS = TokenSet.create(PLUS, MINUS); public static final TokenSet MULTIPLICATIVE_OPERATIONS = TokenSet.create(MULT, FLOORDIV, DIV, PERC); + public static final TokenSet MULTIPLICATIVE_OR_EXP = TokenSet.create(MULT, FLOORDIV, DIV, PERC, EXP); public static final TokenSet UNARY_OPERATIONS = TokenSet.create(PLUS, MINUS, TILDE); public static final TokenSet BITWISE_OPERATIONS = TokenSet.create(AND, OR, XOR); public static final TokenSet EQUALITY_OPERATIONS = TokenSet.create(EQEQ, NE, NE_OLD); diff --git a/python/src/com/jetbrains/python/formatter/PyBlock.java b/python/src/com/jetbrains/python/formatter/PyBlock.java index 37d3eea9ef84..243d55d945b6 100644 --- a/python/src/com/jetbrains/python/formatter/PyBlock.java +++ b/python/src/com/jetbrains/python/formatter/PyBlock.java @@ -33,6 +33,7 @@ public class PyBlock implements ASTBlock { private final ASTNode _node; private final Wrap _wrap; private final CommonCodeStyleSettings mySettings; + private final SpacingBuilder mySpacingBuilder; private List _subBlocks = null; private Alignment myChildAlignment; private static final boolean DUMP_FORMATTING_BLOCKS = false; @@ -58,12 +59,14 @@ public class PyBlock implements ASTBlock { final Alignment alignment, final Indent indent, final Wrap wrap, - final CommonCodeStyleSettings settings) { + final CommonCodeStyleSettings settings, + SpacingBuilder spacingBuilder) { _alignment = alignment; _indent = indent; _node = node; _wrap = wrap; mySettings = settings; + mySpacingBuilder = spacingBuilder; } @NotNull @@ -186,7 +189,7 @@ public class PyBlock implements ASTBlock { childIndent = Indent.getNormalIndent(); } - return new PyBlock(child, childAlignment, childIndent, wrap, mySettings); + return new PyBlock(child, childAlignment, childIndent, wrap, mySettings, mySpacingBuilder); } private static boolean isEmptyList(PsiElement psi) { @@ -304,180 +307,7 @@ public class PyBlock implements ASTBlock { @Nullable public Spacing getSpacing(Block child1, Block child2) { - ASTNode childNode1 = ((PyBlock)child1).getNode(); - ASTNode childNode2 = ((PyBlock)child2).getNode(); - IElementType parentType = _node.getElementType(); - IElementType type1 = childNode1.getElementType(); - IElementType type2 = childNode2.getElementType(); - - if (type1 == PyElementTypes.CLASS_DECLARATION) { - if ((type2 == PyElementTypes.CLASS_DECLARATION || type2 == PyElementTypes.FUNCTION_DECLARATION) && - parentType instanceof PyFileElementType) { - return getBlankLinesForOption(getPySettings().BLANK_LINES_BETWEEN_TOP_LEVEL_CLASSES_FUNCTIONS); - } - return getBlankLinesForOption(mySettings.BLANK_LINES_AROUND_CLASS); - } - if (type2 == PyElementTypes.CLASS_DECLARATION && !(parentType instanceof PyFileElementType)) { - return getBlankLinesForOption(mySettings.BLANK_LINES_AROUND_CLASS); - } - if (type1 == PyElementTypes.FUNCTION_DECLARATION && - (type2 == PyElementTypes.CLASS_DECLARATION || type2 == PyElementTypes.FUNCTION_DECLARATION) && - parentType instanceof PyFileElementType) { - return getBlankLinesForOption(getPySettings().BLANK_LINES_BETWEEN_TOP_LEVEL_CLASSES_FUNCTIONS); - } - if (type1 == PyElementTypes.FUNCTION_DECLARATION || - (type2 == PyElementTypes.FUNCTION_DECLARATION && isStatementOrDeclaration(type1))) { - return getBlankLinesForOption(mySettings.BLANK_LINES_AROUND_METHOD); - } - if (isImportStatement(type1) && (isStatementOrDeclaration(type2) && !isImportStatement(type2))) { - return getBlankLinesForOption(mySettings.BLANK_LINES_AFTER_IMPORTS); - } - - if (isStatementOrDeclaration(type1) && isStatementOrDeclaration(type2)) { - return Spacing.createSpacing(0, Integer.MAX_VALUE, 1, false, 1); - } - - if (parentType == PyElementTypes.ANNOTATION) { - if (type1 == PyTokenTypes.GT) { - return createSpaces(1); - } - if (type1 == PyTokenTypes.MINUS && type2 == PyTokenTypes.GT) { - return createSpaces(0); - } - } - if (parentType == PyElementTypes.FUNCTION_DECLARATION && type2 == PyElementTypes.ANNOTATION) { - return createSpaces(1); - } - - if (type1 == PyTokenTypes.COLON) { - if (type2 == PyElementTypes.STATEMENT_LIST) { - return Spacing.createSpacing(1, Integer.MAX_VALUE, 0, true, 0); - } - if (parentType == PyElementTypes.KEY_VALUE_EXPRESSION || parentType == PyElementTypes.LAMBDA_EXPRESSION) { - return getSpacingForOption(getPySettings().SPACE_AFTER_PY_COLON); - } - } - if (type2 == PyTokenTypes.COLON) { - return getSpacingForOption(getPySettings().SPACE_BEFORE_PY_COLON); - } - - if (type1 == PyTokenTypes.COMMA) { - return getSpacingForOption(mySettings.SPACE_AFTER_COMMA); - } - if (type2 == PyTokenTypes.COMMA) { - return getSpacingForOption(mySettings.SPACE_BEFORE_COMMA); - } - if (type2 == PyTokenTypes.SEMICOLON) { - return getSpacingForOption(mySettings.SPACE_BEFORE_SEMICOLON); - } - - if (type1 == PyTokenTypes.LPAR || type2 == PyTokenTypes.RPAR) { - if (parentType == PyElementTypes.ARGUMENT_LIST) { - return getSpacingForOption(mySettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES); - } - } - if (type2 == PyTokenTypes.LBRACKET) { - return getSpacingForOption(getPySettings().SPACE_BEFORE_LBRACKET); - } - if (type1 == PyTokenTypes.LBRACKET || type2 == PyTokenTypes.RBRACKET) { - return getSpacingForOption(mySettings.SPACE_WITHIN_BRACKETS); - } - if (type1 == PyTokenTypes.LBRACE || type2 == PyTokenTypes.RBRACE) { - return getSpacingForOption(getPySettings().SPACE_WITHIN_BRACES); - } - if (type2 == PyElementTypes.ARGUMENT_LIST) { - return getSpacingForOption(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES); - } - if (type2 == PyElementTypes.PARAMETER_LIST && type1 != PyTokenTypes.LAMBDA_KEYWORD) { - return getSpacingForOption(mySettings.SPACE_BEFORE_METHOD_PARENTHESES); - } - - if (type1 == PyTokenTypes.EQ || type2 == PyTokenTypes.EQ) { - if (parentType == PyElementTypes.ASSIGNMENT_STATEMENT) { - return getSpacingForOption(mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS); - } - if (parentType == PyElementTypes.NAMED_PARAMETER) { - return getSpacingForOption(getPySettings().SPACE_AROUND_EQ_IN_NAMED_PARAMETER); - } - if (parentType == PyElementTypes.KEYWORD_ARGUMENT_EXPRESSION) { - return getSpacingForOption(getPySettings().SPACE_AROUND_EQ_IN_KEYWORD_ARGUMENT); - } - } - if (isAround(type1, type2, PyTokenTypes.AUG_ASSIGN_OPERATIONS)) { - return getSpacingForOption(mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS); - } - if (isAround(type1, type2, PyTokenTypes.ADDITIVE_OPERATIONS) && parentType != PyElementTypes.PREFIX_EXPRESSION) { - return getSpacingForOption(mySettings.SPACE_AROUND_ADDITIVE_OPERATORS); - } - if (isAround(type1, type2, PyTokenTypes.MULTIPLICATIVE_OPERATIONS) || type1 == PyTokenTypes.EXP || type2 == PyTokenTypes.EXP) { - if (parentType == PyElementTypes.NAMED_PARAMETER || - parentType == PyElementTypes.STAR_ARGUMENT_EXPRESSION || - parentType == PyElementTypes.STAR_EXPRESSION) { - return createSpaces(0); - } - return getSpacingForOption(mySettings.SPACE_AROUND_MULTIPLICATIVE_OPERATORS); - } - if (isAround(type1, type2, PyTokenTypes.SHIFT_OPERATIONS)) { - return getSpacingForOption(mySettings.SPACE_AROUND_SHIFT_OPERATORS); - } - if (isAround(type1, type2, PyTokenTypes.BITWISE_OPERATIONS)) { - return getSpacingForOption(mySettings.SPACE_AROUND_BITWISE_OPERATORS); - } - if (isAround(type1, type2, PyTokenTypes.EQUALITY_OPERATIONS)) { - return getSpacingForOption(mySettings.SPACE_AROUND_EQUALITY_OPERATORS); - } - if (isAround(type1, type2, PyTokenTypes.RELATIONAL_OPERATIONS)) { - return getSpacingForOption(mySettings.SPACE_AROUND_RELATIONAL_OPERATORS); - } - - - //if (parentType == PyElementTypes.ARGUMENT_LIST - // || parentType == PyElementTypes.LIST_LITERAL_EXPRESSION) { - // if (type1 == PyTokenTypes.COMMA && PyElementTypes.EXPRESSIONS.contains(type2)) { - // return Spacing.createSpacing(1, 1, 0, true, Integer.MAX_VALUE); - // } - //} - //if (PyElementTypes.STATEMENTS.contains(type1) - // && PyElementTypes.STATEMENTS.contains(type2)) { - // return Spacing.createSpacing(1, Integer.MAX_VALUE, 1, true, Integer.MAX_VALUE); - //} - - //return new PySpacingProcessor(getNode(), childNode1, childNode2, - // mySettings).getResult(); - //return Spacing.createSpacing(0, Integer.MAX_VALUE, 1, true, Integer.MAX_VALUE); - - return null; - } - - private static boolean isImportStatement(IElementType type1) { - return (type1 == PyElementTypes.IMPORT_STATEMENT || type1 == PyElementTypes.FROM_IMPORT_STATEMENT); - } - - private static boolean isAround(IElementType type1, IElementType type2, final TokenSet tokenSet) { - return tokenSet.contains(type1) || tokenSet.contains(type2); - } - - private PyCodeStyleSettings getPySettings() { - return mySettings.getRootSettings().getCustomSettings(PyCodeStyleSettings.class); - } - - private Spacing getBlankLinesForOption(final int option) { - int blankLines = option + 1; - return Spacing.createSpacing(0, 0, blankLines, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS); - } - - private Spacing getSpacingForOption(boolean isOptionSet) { - return createSpaces(isOptionSet ? 1 : 0); - } - - private Spacing createSpaces(int count) { - return Spacing.createSpacing(count, count, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - - private static boolean isStatementOrDeclaration(final IElementType type) { - return PythonDialectsTokenSetProvider.INSTANCE.getStatementTokens().contains(type) || - type == PyElementTypes.CLASS_DECLARATION || - type == PyElementTypes.FUNCTION_DECLARATION; + return mySpacingBuilder.getSpacing(this, child1, child2); } @NotNull diff --git a/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java b/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java index d3e36002dd9d..63a222e838ab 100644 --- a/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java +++ b/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java @@ -6,9 +6,16 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.tree.IStubFileElementType; +import com.intellij.psi.tree.TokenSet; +import com.jetbrains.python.PyElementTypes; +import com.jetbrains.python.PythonDialectsTokenSetProvider; import com.jetbrains.python.PythonLanguage; import org.jetbrains.annotations.NotNull; +import static com.jetbrains.python.PyElementTypes.*; +import static com.jetbrains.python.PyTokenTypes.*; + /** * @author yole */ @@ -23,13 +30,62 @@ public class PythonFormattingModelBuilder implements FormattingModelBuilder, Cus printAST(fileNode, 0); } final PyBlock block = - new PyBlock(element.getNode(), null, Indent.getNoneIndent(), null, settings.getCommonSettings(PythonLanguage.getInstance())); + new PyBlock(element.getNode(), null, Indent.getNoneIndent(), null, settings.getCommonSettings(PythonLanguage.getInstance()), + createSpacingBuilder(settings)); if (DUMP_FORMATTING_AST) { FormattingModelDumper.dumpFormattingModel(block, 2, System.out); } return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), block, settings); } + private static SpacingBuilder createSpacingBuilder(CodeStyleSettings settings) { + final IStubFileElementType file = PythonLanguage.getInstance().getFileElementType(); + final PyCodeStyleSettings pySettings = settings.getCustomSettings(PyCodeStyleSettings.class); + final TokenSet STATEMENT_OR_DECLARATION = TokenSet.orSet(PythonDialectsTokenSetProvider.INSTANCE.getStatementTokens(), + CLASS_OR_FUNCTION); + + return new SpacingBuilder(settings) + .between(IMPORT_STATEMENTS, STATEMENT_OR_DECLARATION.minus(IMPORT_STATEMENTS)).blankLines(settings.BLANK_LINES_AFTER_IMPORTS) + .betweenInside(CLASS_OR_FUNCTION, CLASS_OR_FUNCTION, file).blankLines(pySettings.BLANK_LINES_BETWEEN_TOP_LEVEL_CLASSES_FUNCTIONS) + .around(CLASS_DECLARATION).blankLines(settings.BLANK_LINES_AROUND_CLASS) + .around(FUNCTION_DECLARATION).blankLines(settings.BLANK_LINES_AROUND_METHOD) + .between(STATEMENT_OR_DECLARATION, STATEMENT_OR_DECLARATION).spacing(0, Integer.MAX_VALUE, 1, false, 1) + + .between(COLON, STATEMENT_LIST).spacing(1, Integer.MAX_VALUE, 0, true, 0) + .afterInside(COLON, TokenSet.create(KEY_VALUE_EXPRESSION, PyElementTypes.LAMBDA_EXPRESSION)).spaceIf(pySettings.SPACE_AFTER_PY_COLON) + + .afterInside(GT, ANNOTATION).spaces(1) + .betweenInside(MINUS, GT, ANNOTATION).none() + .beforeInside(ANNOTATION, FUNCTION_DECLARATION).spaces(1) + + .between(TokenSet.not(TokenSet.create(LAMBDA_KEYWORD)), PARAMETER_LIST).spaceIf(settings.SPACE_BEFORE_METHOD_PARENTHESES) + + .before(COLON).spaceIf(pySettings.SPACE_BEFORE_PY_COLON) + .after(COMMA).spaceIf(settings.SPACE_AFTER_COMMA) + .before(COMMA).spaceIf(settings.SPACE_BEFORE_COMMA) + .before(SEMICOLON).spaceIf(settings.SPACE_BEFORE_SEMICOLON) + .withinPairInside(LPAR, RPAR, ARGUMENT_LIST).spaceIf(settings.SPACE_WITHIN_METHOD_CALL_PARENTHESES) + .before(LBRACKET).spaceIf(pySettings.SPACE_BEFORE_LBRACKET) + + .withinPair(LBRACE, RBRACE).spaceIf(settings.SPACE_WITHIN_BRACES) + .withinPair(LBRACKET, RBRACKET).spaceIf(settings.SPACE_WITHIN_BRACKETS) + + .before(ARGUMENT_LIST).spaceIf(settings.SPACE_BEFORE_METHOD_CALL_PARENTHESES) + + .aroundInside(EQ, ASSIGNMENT_STATEMENT).spaceIf(settings.SPACE_AROUND_ASSIGNMENT_OPERATORS) + .aroundInside(EQ, NAMED_PARAMETER).spaceIf(pySettings.SPACE_AROUND_EQ_IN_NAMED_PARAMETER) + .aroundInside(EQ, KEYWORD_ARGUMENT_EXPRESSION).spaceIf(pySettings.SPACE_AROUND_EQ_IN_KEYWORD_ARGUMENT) + + .around(AUG_ASSIGN_OPERATIONS).spaceIf(settings.SPACE_AROUND_ASSIGNMENT_OPERATORS) + .aroundInside(ADDITIVE_OPERATIONS, BINARY_EXPRESSION).spaceIf(settings.SPACE_AROUND_ADDITIVE_OPERATORS) + .aroundInside(MULTIPLICATIVE_OR_EXP, STAR_PARAMETERS).none() + .around(MULTIPLICATIVE_OR_EXP).spaceIf(settings.SPACE_AROUND_MULTIPLICATIVE_OPERATORS) + .around(SHIFT_OPERATIONS).spaceIf(settings.SPACE_AROUND_SHIFT_OPERATORS) + .around(BITWISE_OPERATIONS).spaceIf(settings.SPACE_AROUND_BITWISE_OPERATORS) + .around(EQUALITY_OPERATIONS).spaceIf(settings.SPACE_AROUND_EQUALITY_OPERATORS) + .around(RELATIONAL_OPERATIONS).spaceIf(settings.SPACE_AROUND_RELATIONAL_OPERATORS); + } + public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) { return null; } From 0ede4e25feaba18e9b3f3f2141814ca738f2cb7f Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Mon, 7 Nov 2011 13:44:52 +0100 Subject: [PATCH 2/3] JavaScript debugger in PyCharm (PY-3021). --- python/build/pycharm_build.gant | 1 + python/main_pycharm.iml | 4 ++++ python/python.iml | 3 +++ python/src/META-INF/python-plugin-common.xml | 3 +++ 4 files changed, 11 insertions(+) diff --git a/python/build/pycharm_build.gant b/python/build/pycharm_build.gant index c0cba960ff0a..fc7f5400edff 100644 --- a/python/build/pycharm_build.gant +++ b/python/build/pycharm_build.gant @@ -22,6 +22,7 @@ setProperty("jdk16", guessJdk()) setProperty("pluginFilter", [ "htmltools", "JavaScriptLanguage", + "JavaScriptDebugger", "FirefoxConnector", "ChromeConnector", "python-javascript-debugger", "cvsIntegration", "cvs-core", "cvs-plugin", "javacvs-src", "smartcvs-src", "PerforceIntegration", "Perforce", "perforce_util", "svn4idea", diff --git a/python/main_pycharm.iml b/python/main_pycharm.iml index 96462dc87bdf..d76235686977 100644 --- a/python/main_pycharm.iml +++ b/python/main_pycharm.iml @@ -19,6 +19,10 @@ + + + + diff --git a/python/python.iml b/python/python.iml index 8186b05135e6..a802b31f9847 100644 --- a/python/python.iml +++ b/python/python.iml @@ -36,6 +36,9 @@ + + + diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml index eb2ff0cd1456..dcde4e614665 100644 --- a/python/src/META-INF/python-plugin-common.xml +++ b/python/src/META-INF/python-plugin-common.xml @@ -715,6 +715,9 @@ + + From 65e99445259fb8ce44e259da29321188b0782cdd Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 7 Nov 2011 14:00:16 +0100 Subject: [PATCH 3/3] tweak Python formatting rules to fix tests --- .../python/formatter/PythonFormattingModelBuilder.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java b/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java index 63a222e838ab..f8ffdc55f7ed 100644 --- a/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java +++ b/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java @@ -47,8 +47,12 @@ public class PythonFormattingModelBuilder implements FormattingModelBuilder, Cus return new SpacingBuilder(settings) .between(IMPORT_STATEMENTS, STATEMENT_OR_DECLARATION.minus(IMPORT_STATEMENTS)).blankLines(settings.BLANK_LINES_AFTER_IMPORTS) .betweenInside(CLASS_OR_FUNCTION, CLASS_OR_FUNCTION, file).blankLines(pySettings.BLANK_LINES_BETWEEN_TOP_LEVEL_CLASSES_FUNCTIONS) - .around(CLASS_DECLARATION).blankLines(settings.BLANK_LINES_AROUND_CLASS) - .around(FUNCTION_DECLARATION).blankLines(settings.BLANK_LINES_AROUND_METHOD) + .between(CLASS_DECLARATION, STATEMENT_OR_DECLARATION).blankLines(settings.BLANK_LINES_AROUND_CLASS) + .between(STATEMENT_OR_DECLARATION, CLASS_DECLARATION).blankLines(settings.BLANK_LINES_AROUND_CLASS) + .between(FUNCTION_DECLARATION, STATEMENT_OR_DECLARATION).blankLines(settings.BLANK_LINES_AROUND_METHOD) + .between(STATEMENT_OR_DECLARATION, FUNCTION_DECLARATION).blankLines(settings.BLANK_LINES_AROUND_METHOD) + .after(FUNCTION_DECLARATION).blankLines(settings.BLANK_LINES_AROUND_METHOD) + .after(CLASS_DECLARATION).blankLines(settings.BLANK_LINES_AROUND_CLASS) .between(STATEMENT_OR_DECLARATION, STATEMENT_OR_DECLARATION).spacing(0, Integer.MAX_VALUE, 1, false, 1) .between(COLON, STATEMENT_LIST).spacing(1, Integer.MAX_VALUE, 0, true, 0)