From 5c8a90fe85ef84fc2230a65b67c09912763d8c0d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 22 Jun 2017 15:33:01 +0200 Subject: [PATCH] "Blank lines after class header" option supported --- .../idea/formatter/kotlinSpacingRules.kt | 24 ++++++++++++++-- ...KotlinLanguageCodeStyleSettingsProvider.kt | 3 +- .../BlankLinesAfterClassHeader.after.kt | 28 +++++++++++++++++++ .../formatter/BlankLinesAfterClassHeader.kt | 26 +++++++++++++++++ .../formatter/FormatterTestGenerated.java | 6 ++++ 5 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 idea/testData/formatter/BlankLinesAfterClassHeader.after.kt create mode 100644 idea/testData/formatter/BlankLinesAfterClassHeader.kt diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/kotlinSpacingRules.kt b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/kotlinSpacingRules.kt index 2c445b7be7f..ae6d5986ac0 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/kotlinSpacingRules.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/kotlinSpacingRules.kt @@ -17,10 +17,12 @@ package org.jetbrains.kotlin.idea.formatter import com.intellij.formatting.ASTBlock +import com.intellij.formatting.DependentSpacingRule import com.intellij.formatting.Spacing import com.intellij.formatting.SpacingBuilder import com.intellij.formatting.SpacingBuilder.RuleBuilder import com.intellij.lang.ASTNode +import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.codeStyle.CodeStyleSettings import com.intellij.psi.tree.IElementType @@ -32,6 +34,7 @@ import org.jetbrains.kotlin.idea.formatter.KotlinSpacingBuilder.CustomSpacingBui import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral import org.jetbrains.kotlin.psi.psiUtil.textRangeWithoutComments val MODIFIERS_LIST_ENTRIES = TokenSet.orSet(TokenSet.create(ANNOTATION_ENTRY, ANNOTATION), MODIFIER_KEYWORDS) @@ -78,6 +81,25 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing } else null } + inPosition(parent = CLASS_BODY, left = LBRACE).customRule { parent, left, right -> + if (right.node.elementType == RBRACE) { + return@customRule createSpacing(0) + } + val classBody = parent.node.psi as KtClassBody + val parentPsi = classBody.parent as? KtClassOrObject ?: return@customRule null + if (commonCodeStyleSettings.BLANK_LINES_AFTER_CLASS_HEADER == 0 || parentPsi.isObjectLiteral()) { + null + } + else { + Spacing.createDependentLFSpacing( + 0, 0, + TextRange(parentPsi.textRange.startOffset, left.node.psi.textRange.startOffset), + settings.KEEP_LINE_BREAKS, settings.KEEP_BLANK_LINES_IN_DECLARATIONS, + DependentSpacingRule(DependentSpacingRule.Trigger.HAS_LINE_FEEDS) + .registerData(DependentSpacingRule.Anchor.MIN_LINE_FEEDS, commonCodeStyleSettings.BLANK_LINES_AFTER_CLASS_HEADER + 1)) + } + } + val parameterWithDocCommentRule = { _: ASTBlock, _: ASTBlock, right: ASTBlock -> if (right.node.firstChildNode.elementType == KtTokens.DOC_COMMENT) { @@ -130,8 +152,6 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing after(DOC_COMMENT).lineBreakInCode() // =============== Spacing ================ - betweenInside(LBRACE, RBRACE, CLASS_BODY).spaces(0) - before(COMMA).spaceIf(kotlinCommonSettings.SPACE_BEFORE_COMMA) after(COMMA).spaceIf(kotlinCommonSettings.SPACE_AFTER_COMMA) diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt index ffcf5466352..e2be7d80325 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt @@ -252,7 +252,8 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide LanguageCodeStyleSettingsProvider.SettingsType.BLANK_LINES_SETTINGS -> { consumer.showStandardOptions( "KEEP_BLANK_LINES_IN_CODE", - "KEEP_BLANK_LINES_IN_DECLARATIONS" + "KEEP_BLANK_LINES_IN_DECLARATIONS", + "BLANK_LINES_AFTER_CLASS_HEADER" ) showCustomOption(KotlinCodeStyleSettings::BLANK_LINES_AROUND_BLOCK_WHEN_BRANCHES, "Around 'when' branches with {}", diff --git a/idea/testData/formatter/BlankLinesAfterClassHeader.after.kt b/idea/testData/formatter/BlankLinesAfterClassHeader.after.kt new file mode 100644 index 00000000000..d581c319182 --- /dev/null +++ b/idea/testData/formatter/BlankLinesAfterClassHeader.after.kt @@ -0,0 +1,28 @@ +class Foo { + fun bar() { + } +} + +object Bar { + fun xyzzy() { + } +} + +val f = object { + fun foo() {} +} + +class FooM + : IFoo { + + fun bar() +} + +class FooC( + val x: String +) { + + fun bar() +} + +// SET_INT: BLANK_LINES_AFTER_CLASS_HEADER = 1 diff --git a/idea/testData/formatter/BlankLinesAfterClassHeader.kt b/idea/testData/formatter/BlankLinesAfterClassHeader.kt new file mode 100644 index 00000000000..4d0d3d9b5f9 --- /dev/null +++ b/idea/testData/formatter/BlankLinesAfterClassHeader.kt @@ -0,0 +1,26 @@ +class Foo { + fun bar() { + } +} + +object Bar { + fun xyzzy() { + } +} + +val f = object { + fun foo() {} +} + +class FooM + : IFoo { + fun bar() +} + +class FooC( + val x: String +) { + fun bar() +} + +// SET_INT: BLANK_LINES_AFTER_CLASS_HEADER = 1 diff --git a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java index 64bb1a8a9e5..399939b8f04 100644 --- a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java @@ -92,6 +92,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest { doTest(fileName); } + @TestMetadata("BlankLinesAfterClassHeader.after.kt") + public void testBlankLinesAfterClassHeader() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/BlankLinesAfterClassHeader.after.kt"); + doTest(fileName); + } + @TestMetadata("BlockFor.after.kt") public void testBlockFor() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/BlockFor.after.kt");