diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java b/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java
index e7bbbb75452..b73f5ff9249 100644
--- a/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java
+++ b/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java
@@ -54,6 +54,7 @@ public class KotlinCodeStyleSettings extends CustomCodeStyleSettings {
public int WRAP_ELVIS_EXPRESSIONS = 1;
public boolean IF_RPAREN_ON_NEW_LINE = false;
public boolean ALLOW_TRAILING_COMMA = false;
+ public int BLANK_LINES_BEFORE_DECLARATION_WITH_COMMENT_OR_ANNOTATION_ON_SEPARATE_LINE = 1;
@ReflectionUtil.SkipInEquals
public String CODE_STYLE_DEFAULTS = null;
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 3b9863243ba..8e56896103d 100644
--- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/kotlinSpacingRules.kt
+++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/kotlinSpacingRules.kt
@@ -114,7 +114,7 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing
node.text.subSequence(0, elementStart.startOffset - node.startOffset).trimStart()
)
)
- createSpacing(0, minLineFeeds = 2)
+ createSpacing(0, minLineFeeds = 1 + kotlinCustomSettings.BLANK_LINES_BEFORE_DECLARATION_WITH_COMMENT_OR_ANNOTATION_ON_SEPARATE_LINE)
else
null
})
@@ -131,7 +131,6 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing
// Case left for alternative constructors
inPosition(left = FUN, right = CLASS).emptyLinesIfLineBreakInLeft(1)
-
inPosition(left = ENUM_ENTRY, right = ENUM_ENTRY).emptyLinesIfLineBreakInLeft(
emptyLines = 0, numberOfLineFeedsOtherwise = 0, numSpacesOtherwise = 1
)
@@ -139,7 +138,7 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing
inPosition(parent = CLASS_BODY, left = SEMICOLON).customRule { parent, _, right ->
val klass = parent.requireNode().treeParent.psi as? KtClass ?: return@customRule null
if (klass.isEnum() && right.requireNode().elementType in DECLARATIONS) {
- createSpacing(0, minLineFeeds = 2, keepBlankLines = settings.KEEP_BLANK_LINES_IN_DECLARATIONS)
+ createSpacing(0, minLineFeeds = 2, keepBlankLines = kotlinCommonSettings.KEEP_BLANK_LINES_IN_DECLARATIONS)
} else null
}
diff --git a/idea/resources-en/messages/KotlinBundle.properties b/idea/resources-en/messages/KotlinBundle.properties
index 11d6bf8474c..b4440042213 100644
--- a/idea/resources-en/messages/KotlinBundle.properties
+++ b/idea/resources-en/messages/KotlinBundle.properties
@@ -519,6 +519,7 @@ formatter.title.align.when.branches.in.columns=Align 'when' branches in columns
formatter.title.around.arrow.in.function.types=Around arrow in function types
formatter.title.around.arrow.in=Around arrow in "when" clause
formatter.title.around.when.branches.with=Around 'when' branches with {}
+formatter.title.before.declaration.with.comment.or.annotation=Before declaration with comment or annotation
formatter.title.before.colon.after.declaration.name=Before colon, after declaration name
formatter.title.before.colon.in.new.type.definition=Before colon in new type definition
formatter.title.before.lambda.arrow=Before lambda arrow
diff --git a/idea/resources-en/search/searchableOptions.xml b/idea/resources-en/search/searchableOptions.xml
index d1e03083c41..663837242d9 100644
--- a/idea/resources-en/search/searchableOptions.xml
+++ b/idea/resources-en/search/searchableOptions.xml
@@ -598,6 +598,12 @@
+
+
+
+
+
+
@@ -1307,10 +1313,6 @@
-
-
-
-
diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt
index d6c5fed5a08..04a9e53a2cf 100644
--- a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt
@@ -258,11 +258,18 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
"KEEP_BLANK_LINES_BEFORE_RBRACE",
"BLANK_LINES_AFTER_CLASS_HEADER"
)
+
showCustomOption(
KotlinCodeStyleSettings::BLANK_LINES_AROUND_BLOCK_WHEN_BRANCHES,
KotlinBundle.message("formatter.title.around.when.branches.with"),
CodeStyleSettingsCustomizable.BLANK_LINES
)
+
+ showCustomOption(
+ KotlinCodeStyleSettings::BLANK_LINES_BEFORE_DECLARATION_WITH_COMMENT_OR_ANNOTATION_ON_SEPARATE_LINE,
+ KotlinBundle.message("formatter.title.before.declaration.with.comment.or.annotation"),
+ CodeStyleSettingsCustomizable.BLANK_LINES
+ )
}
SettingsType.COMMENTER_SETTINGS -> {
consumer.showAllStandardOptions()
@@ -376,7 +383,24 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
}
fun run(f: () -> Unit) {
f()
- }""".trimIndent()
+ }
+
+ class Bar {
+ @Annotation
+ val a = 42
+ @Annotation
+ val b = 43
+ fun c() {
+ a + b
+ }
+ fun d() = Unit
+ // smth
+ fun e() {
+ d()
+ }
+ fun f() = d()
+ }
+ """.trimIndent()
else -> """open class Some {
private val f: (Int)->Int = { a: Int -> a * 2 }
diff --git a/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationTwo.after.kt b/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationTwo.after.kt
new file mode 100644
index 00000000000..8ea5091f089
--- /dev/null
+++ b/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationTwo.after.kt
@@ -0,0 +1,376 @@
+interface Some {
+ fun f1()
+ fun f2()
+ fun f3()
+
+
+ /* test */
+ fun f4()
+ /* test */ fun f5()
+
+
+ /**
+ * test
+ * 2
+ */
+ fun f6()
+ fun f7()
+
+
+ @NotNull
+ fun f8()
+ fun f9()
+}
+
+interface Some2 {
+ fun f1()
+ fun f2()
+ fun f3()
+
+
+ @Ann
+ fun f4()
+ @Ann
+ fun f5()
+
+
+ @Ann(
+ 42
+ )
+ fun f6()
+ fun f7()
+
+
+ @NotNull
+ fun f8()
+ fun f9()
+}
+
+abstract class Abstract() {
+ abstract fun f1()
+ abstract fun f2()
+
+
+ // test
+ abstract fun f3()
+
+
+ // test
+ /* test */ abstract fun f4()
+ abstract fun f5()
+ abstract fun f6()
+ /* test */ abstract fun f7()
+}
+
+abstract class Abstract() {
+ abstract fun f1()
+ abstract fun f2()
+
+
+ @Ann
+ abstract fun f3()
+
+
+ @Ann
+ @Ann
+ abstract fun f4()
+ abstract fun f5()
+ abstract fun f6()
+ @Ann
+ abstract fun f7()
+}
+
+fun f1() {}
+class C1 {}
+
+// -----
+
+fun f2() {}
+class C2
+
+// -----
+
+// test
+fun f3 = 1
+class C3 {}
+
+// -----
+
+/*test*/
+fun f4 = 2
+class C4
+
+// -----
+
+@Ann
+fun f3 = 1
+class C3 {}
+
+// -----
+
+@Ann
+fun f4 = 2
+class C4
+
+// -----
+
+class C5 {}
+
+fun f5() {}
+
+// -----
+
+class C6
+
+fun f6() {}
+
+// -----
+
+class C7 {}
+
+fun f7 = 1
+
+// -----
+
+class D {
+
+}
+
+class E
+ : Some
+
+class F
+
+
+@Ann
+fun some() = 1
+class G
+
+fun some() = 1
+
+val a = 1
+
+class H
+
+val b = 1
+
+
+// No lines
+fun f1() {}
+val p1 = 1
+fun f2() {}
+
+
+@Ann
+fun f3() = 1
+val p2 = 1
+fun f4() = 1
+
+fun f4() {}
+val p3: Int
+ get() = 1
+
+fun f5() = 1
+
+class OneLine {
+ fun f1() {}
+
+ val p1 = 1
+
+ fun f2() {}
+
+ fun f3() = 1
+
+ val p2 = 1
+
+ fun f4() = 1
+
+ fun f4() {}
+
+ val p3: Int
+ get() = 1
+
+ fun f5() = 1
+}
+
+class TwoLines {
+ fun f1() {}
+
+
+ val p1 = 1
+
+
+ fun f2() {}
+
+
+ fun f3() = 1
+
+
+ val p2 = 1
+
+
+ fun f4() = 1
+
+
+ fun f4() {}
+
+
+ val p3: Int
+ get() = 1
+
+
+ fun f5() = 1
+}
+
+// No lines between
+
+fun f2() {}
+fun f1() {}
+fun f3() = 1
+fun f4() {}
+fun f5() {
+}
+
+fun f6() = 1
+fun f7() = 8
+
+// One line
+
+fun f2() {}
+
+fun f1() {}
+
+fun f3() = 1
+
+fun f4() {}
+
+fun f5() {
+}
+
+fun f6() = 1
+
+fun f7() = 8
+
+
+// test
+fun f8() = 42
+
+
+// Two lines between
+fun l1() {}
+
+
+fun l2() {}
+
+
+fun l3() = 1
+
+
+fun l4() {}
+
+
+fun l5() {
+}
+
+
+fun l6() = 1
+
+
+fun l7() = 8
+
+
+// test
+val p1 by Some
+val p2 = 1
+val p3: Int get() = 3
+val p4: Int
+ get() {
+ return 1
+ }
+val p5: Int
+
+class OneLine {
+ val p1 by Some
+
+ val p2 = 1
+
+ val p3: Int get() = 3
+
+ val p4: Int
+ get() {
+ return 1
+ }
+
+ val p5: Int
+}
+
+class TwoLines {
+ val p1 by Some
+
+
+ val p2 = 1
+
+
+ val p3: Int get() = 3
+
+
+ val p4: Int
+ get() {
+ return 1
+ }
+
+
+ val p5: Int
+}
+
+class Some(b: Boolean) {
+ // Comment.
+ constructor(b: Int) : this(b == 0)
+
+
+ /**
+ * test
+ * 2
+ */
+ constructor(b: String) : this(b.isEmpty())
+ constructor(b: Long) : this(b == 0L)
+
+
+ @Ann
+ constructor(b: Int) : this(b == 0)
+
+
+ @Ann(
+ 42
+ )
+ constructor(b: String) : this(b.isEmpty())
+ constructor(b: Long) : this(b == 0L)
+}
+
+enum class TestEnum {
+ /** A comment for the item #1. */
+ ITEM1,
+
+
+ /** A comment for the item #2. */
+ ITEM2,
+
+
+ /** A comment for the item #3. */
+ ITEM3
+}
+
+class Foo {
+ @Inject
+ lateinit var logger: Logger
+
+
+ @Inject
+ lateinit var userService: UserService
+
+
+ @Inject
+ override lateinit var configBridge: ConfigBridge
+}
+
+// SET_INT: BLANK_LINES_BEFORE_DECLARATION_WITH_COMMENT_OR_ANNOTATION_ON_SEPARATE_LINE = 2
\ No newline at end of file
diff --git a/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationTwo.kt b/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationTwo.kt
new file mode 100644
index 00000000000..129543e6a4d
--- /dev/null
+++ b/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationTwo.kt
@@ -0,0 +1,316 @@
+interface Some {
+ fun f1()
+ fun f2()
+ fun f3()
+ /* test */
+ fun f4()
+ /* test */ fun f5()
+ /**
+ * test
+ * 2
+ */
+ fun f6()
+ fun f7()
+ @NotNull
+ fun f8()
+ fun f9()
+}
+
+interface Some2 {
+ fun f1()
+ fun f2()
+ fun f3()
+ @Ann
+ fun f4()
+ @Ann fun f5()
+ @Ann(
+ 42
+ )
+ fun f6()
+ fun f7()
+ @NotNull
+ fun f8()
+ fun f9()
+}
+
+abstract class Abstract() {
+ abstract fun f1()
+ abstract fun f2()
+ // test
+ abstract fun f3()
+ // test
+ /* test */ abstract fun f4()
+ abstract fun f5()
+ abstract fun f6()
+ /* test */ abstract fun f7()
+}
+
+abstract class Abstract() {
+ abstract fun f1()
+ abstract fun f2()
+ @Ann
+ abstract fun f3()
+ @Ann
+ @Ann abstract fun f4()
+ abstract fun f5()
+ abstract fun f6()
+ @Ann abstract fun f7()
+}
+
+fun f1() {}
+class C1 {}
+
+// -----
+
+fun f2() {}
+class C2
+
+// -----
+
+// test
+fun f3 = 1
+class C3 {}
+
+// -----
+
+/*test*/
+fun f4 = 2
+class C4
+
+// -----
+
+@Ann
+fun f3 = 1
+class C3 {}
+
+// -----
+
+@Ann
+fun f4 = 2
+class C4
+
+// -----
+
+class C5 {}
+fun f5() {}
+
+// -----
+
+class C6
+fun f6() {}
+
+// -----
+
+class C7 {}
+fun f7 = 1
+
+// -----
+
+class D {
+
+}
+class E
+ : Some
+class F
+
+@Ann
+fun some() = 1
+class G
+fun some() = 1
+
+val a = 1
+class H
+val b = 1
+
+// No lines
+fun f1() {}
+val p1 = 1
+fun f2() {}
+
+@Ann
+fun f3() = 1
+val p2 = 1
+fun f4() = 1
+
+fun f4() {}
+val p3: Int
+ get() = 1
+fun f5() = 1
+
+class OneLine {
+ fun f1() {}
+
+ val p1 = 1
+
+ fun f2() {}
+
+ fun f3() = 1
+
+ val p2 = 1
+
+ fun f4() = 1
+
+ fun f4() {}
+
+ val p3: Int
+ get() = 1
+
+ fun f5() = 1
+}
+
+class TwoLines {
+ fun f1() {}
+
+
+ val p1 = 1
+
+
+ fun f2() {}
+
+
+ fun f3() = 1
+
+
+ val p2 = 1
+
+
+ fun f4() = 1
+
+
+ fun f4() {}
+
+
+ val p3: Int
+ get() = 1
+
+
+ fun f5() = 1
+}
+
+// No lines between
+
+fun f2() {}
+fun f1() {}
+fun f3() = 1
+fun f4() {}
+fun f5() {
+}
+fun f6() = 1
+fun f7() = 8
+
+// One line
+
+fun f2() {}
+
+fun f1() {}
+
+fun f3() = 1
+
+fun f4() {}
+
+fun f5() {
+}
+
+fun f6() = 1
+
+fun f7() = 8
+// test
+fun f8() = 42
+
+// Two lines between
+fun l1() {}
+
+
+fun l2() {}
+
+
+fun l3() = 1
+
+
+fun l4() {}
+
+
+fun l5() {
+}
+
+
+fun l6() = 1
+
+
+fun l7() = 8
+
+// test
+val p1 by Some
+val p2 = 1
+val p3: Int get() = 3
+val p4: Int
+ get() { return 1 }
+val p5: Int
+
+class OneLine {
+ val p1 by Some
+
+ val p2 = 1
+
+ val p3: Int get() = 3
+
+ val p4: Int
+ get() { return 1 }
+
+ val p5: Int
+}
+
+class TwoLines {
+ val p1 by Some
+
+
+ val p2 = 1
+
+
+ val p3: Int get() = 3
+
+
+ val p4: Int
+ get() { return 1 }
+
+
+ val p5: Int
+}
+
+class Some(b: Boolean) {
+ // Comment.
+ constructor(b: Int) : this(b == 0)
+ /**
+ * test
+ * 2
+ */
+ constructor(b: String) : this(b.isEmpty())
+ constructor(b: Long) : this(b == 0L)
+ @Ann
+ constructor(b: Int) : this(b == 0)
+ @Ann(
+ 42
+ )
+ constructor(b: String) : this(b.isEmpty())
+ constructor(b: Long) : this(b == 0L)
+}
+
+enum class TestEnum {
+ /** A comment for the item #1. */
+ ITEM1,
+ /** A comment for the item #2. */
+ ITEM2,
+ /** A comment for the item #3. */
+ ITEM3
+}
+
+class Foo {
+ @Inject
+ lateinit var logger: Logger
+ @Inject
+ lateinit var userService: UserService
+ @Inject
+ override lateinit var configBridge: ConfigBridge
+}
+
+// SET_INT: BLANK_LINES_BEFORE_DECLARATION_WITH_COMMENT_OR_ANNOTATION_ON_SEPARATE_LINE = 2
\ No newline at end of file
diff --git a/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationZero.after.kt b/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationZero.after.kt
new file mode 100644
index 00000000000..e9d9b276587
--- /dev/null
+++ b/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationZero.after.kt
@@ -0,0 +1,335 @@
+interface Some {
+ fun f1()
+ fun f2()
+ fun f3()
+ /* test */
+ fun f4()
+ /* test */ fun f5()
+ /**
+ * test
+ * 2
+ */
+ fun f6()
+ fun f7()
+ @NotNull
+ fun f8()
+ fun f9()
+}
+
+interface Some2 {
+ fun f1()
+ fun f2()
+ fun f3()
+ @Ann
+ fun f4()
+ @Ann
+ fun f5()
+ @Ann(
+ 42
+ )
+ fun f6()
+ fun f7()
+ @NotNull
+ fun f8()
+ fun f9()
+}
+
+abstract class Abstract() {
+ abstract fun f1()
+ abstract fun f2()
+ // test
+ abstract fun f3()
+ // test
+ /* test */ abstract fun f4()
+ abstract fun f5()
+ abstract fun f6()
+ /* test */ abstract fun f7()
+}
+
+abstract class Abstract() {
+ abstract fun f1()
+ abstract fun f2()
+ @Ann
+ abstract fun f3()
+ @Ann
+ @Ann
+ abstract fun f4()
+ abstract fun f5()
+ abstract fun f6()
+ @Ann
+ abstract fun f7()
+}
+
+fun f1() {}
+class C1 {}
+
+// -----
+
+fun f2() {}
+class C2
+
+// -----
+
+// test
+fun f3 = 1
+class C3 {}
+
+// -----
+
+/*test*/
+fun f4 = 2
+class C4
+
+// -----
+
+@Ann
+fun f3 = 1
+class C3 {}
+
+// -----
+
+@Ann
+fun f4 = 2
+class C4
+
+// -----
+
+class C5 {}
+
+fun f5() {}
+
+// -----
+
+class C6
+
+fun f6() {}
+
+// -----
+
+class C7 {}
+
+fun f7 = 1
+
+// -----
+
+class D {
+
+}
+
+class E
+ : Some
+
+class F
+
+@Ann
+fun some() = 1
+class G
+
+fun some() = 1
+
+val a = 1
+
+class H
+
+val b = 1
+
+// No lines
+fun f1() {}
+val p1 = 1
+fun f2() {}
+
+@Ann
+fun f3() = 1
+val p2 = 1
+fun f4() = 1
+
+fun f4() {}
+val p3: Int
+ get() = 1
+
+fun f5() = 1
+
+class OneLine {
+ fun f1() {}
+
+ val p1 = 1
+
+ fun f2() {}
+
+ fun f3() = 1
+
+ val p2 = 1
+
+ fun f4() = 1
+
+ fun f4() {}
+
+ val p3: Int
+ get() = 1
+
+ fun f5() = 1
+}
+
+class TwoLines {
+ fun f1() {}
+
+
+ val p1 = 1
+
+
+ fun f2() {}
+
+
+ fun f3() = 1
+
+
+ val p2 = 1
+
+
+ fun f4() = 1
+
+
+ fun f4() {}
+
+
+ val p3: Int
+ get() = 1
+
+
+ fun f5() = 1
+}
+
+// No lines between
+
+fun f2() {}
+fun f1() {}
+fun f3() = 1
+fun f4() {}
+fun f5() {
+}
+
+fun f6() = 1
+fun f7() = 8
+
+// One line
+
+fun f2() {}
+
+fun f1() {}
+
+fun f3() = 1
+
+fun f4() {}
+
+fun f5() {
+}
+
+fun f6() = 1
+
+fun f7() = 8
+// test
+fun f8() = 42
+
+// Two lines between
+fun l1() {}
+
+
+fun l2() {}
+
+
+fun l3() = 1
+
+
+fun l4() {}
+
+
+fun l5() {
+}
+
+
+fun l6() = 1
+
+
+fun l7() = 8
+
+// test
+val p1 by Some
+val p2 = 1
+val p3: Int get() = 3
+val p4: Int
+ get() {
+ return 1
+ }
+val p5: Int
+
+class OneLine {
+ val p1 by Some
+
+ val p2 = 1
+
+ val p3: Int get() = 3
+
+ val p4: Int
+ get() {
+ return 1
+ }
+
+ val p5: Int
+}
+
+class TwoLines {
+ val p1 by Some
+
+
+ val p2 = 1
+
+
+ val p3: Int get() = 3
+
+
+ val p4: Int
+ get() {
+ return 1
+ }
+
+
+ val p5: Int
+}
+
+class Some(b: Boolean) {
+ // Comment.
+ constructor(b: Int) : this(b == 0)
+ /**
+ * test
+ * 2
+ */
+ constructor(b: String) : this(b.isEmpty())
+ constructor(b: Long) : this(b == 0L)
+ @Ann
+ constructor(b: Int) : this(b == 0)
+ @Ann(
+ 42
+ )
+ constructor(b: String) : this(b.isEmpty())
+ constructor(b: Long) : this(b == 0L)
+}
+
+enum class TestEnum {
+ /** A comment for the item #1. */
+ ITEM1,
+ /** A comment for the item #2. */
+ ITEM2,
+ /** A comment for the item #3. */
+ ITEM3
+}
+
+class Foo {
+ @Inject
+ lateinit var logger: Logger
+ @Inject
+ lateinit var userService: UserService
+ @Inject
+ override lateinit var configBridge: ConfigBridge
+}
+
+// SET_INT: BLANK_LINES_BEFORE_DECLARATION_WITH_COMMENT_OR_ANNOTATION_ON_SEPARATE_LINE = 0
\ No newline at end of file
diff --git a/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationZero.kt b/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationZero.kt
new file mode 100644
index 00000000000..3ac71373c66
--- /dev/null
+++ b/idea/testData/formatter/EmptyLineBetweeMultilineDeclarationZero.kt
@@ -0,0 +1,316 @@
+interface Some {
+ fun f1()
+ fun f2()
+ fun f3()
+ /* test */
+ fun f4()
+ /* test */ fun f5()
+ /**
+ * test
+ * 2
+ */
+ fun f6()
+ fun f7()
+ @NotNull
+ fun f8()
+ fun f9()
+}
+
+interface Some2 {
+ fun f1()
+ fun f2()
+ fun f3()
+ @Ann
+ fun f4()
+ @Ann fun f5()
+ @Ann(
+ 42
+ )
+ fun f6()
+ fun f7()
+ @NotNull
+ fun f8()
+ fun f9()
+}
+
+abstract class Abstract() {
+ abstract fun f1()
+ abstract fun f2()
+ // test
+ abstract fun f3()
+ // test
+ /* test */ abstract fun f4()
+ abstract fun f5()
+ abstract fun f6()
+ /* test */ abstract fun f7()
+}
+
+abstract class Abstract() {
+ abstract fun f1()
+ abstract fun f2()
+ @Ann
+ abstract fun f3()
+ @Ann
+ @Ann abstract fun f4()
+ abstract fun f5()
+ abstract fun f6()
+ @Ann abstract fun f7()
+}
+
+fun f1() {}
+class C1 {}
+
+// -----
+
+fun f2() {}
+class C2
+
+// -----
+
+// test
+fun f3 = 1
+class C3 {}
+
+// -----
+
+/*test*/
+fun f4 = 2
+class C4
+
+// -----
+
+@Ann
+fun f3 = 1
+class C3 {}
+
+// -----
+
+@Ann
+fun f4 = 2
+class C4
+
+// -----
+
+class C5 {}
+fun f5() {}
+
+// -----
+
+class C6
+fun f6() {}
+
+// -----
+
+class C7 {}
+fun f7 = 1
+
+// -----
+
+class D {
+
+}
+class E
+ : Some
+class F
+
+@Ann
+fun some() = 1
+class G
+fun some() = 1
+
+val a = 1
+class H
+val b = 1
+
+// No lines
+fun f1() {}
+val p1 = 1
+fun f2() {}
+
+@Ann
+fun f3() = 1
+val p2 = 1
+fun f4() = 1
+
+fun f4() {}
+val p3: Int
+ get() = 1
+fun f5() = 1
+
+class OneLine {
+ fun f1() {}
+
+ val p1 = 1
+
+ fun f2() {}
+
+ fun f3() = 1
+
+ val p2 = 1
+
+ fun f4() = 1
+
+ fun f4() {}
+
+ val p3: Int
+ get() = 1
+
+ fun f5() = 1
+}
+
+class TwoLines {
+ fun f1() {}
+
+
+ val p1 = 1
+
+
+ fun f2() {}
+
+
+ fun f3() = 1
+
+
+ val p2 = 1
+
+
+ fun f4() = 1
+
+
+ fun f4() {}
+
+
+ val p3: Int
+ get() = 1
+
+
+ fun f5() = 1
+}
+
+// No lines between
+
+fun f2() {}
+fun f1() {}
+fun f3() = 1
+fun f4() {}
+fun f5() {
+}
+fun f6() = 1
+fun f7() = 8
+
+// One line
+
+fun f2() {}
+
+fun f1() {}
+
+fun f3() = 1
+
+fun f4() {}
+
+fun f5() {
+}
+
+fun f6() = 1
+
+fun f7() = 8
+// test
+fun f8() = 42
+
+// Two lines between
+fun l1() {}
+
+
+fun l2() {}
+
+
+fun l3() = 1
+
+
+fun l4() {}
+
+
+fun l5() {
+}
+
+
+fun l6() = 1
+
+
+fun l7() = 8
+
+// test
+val p1 by Some
+val p2 = 1
+val p3: Int get() = 3
+val p4: Int
+ get() { return 1 }
+val p5: Int
+
+class OneLine {
+ val p1 by Some
+
+ val p2 = 1
+
+ val p3: Int get() = 3
+
+ val p4: Int
+ get() { return 1 }
+
+ val p5: Int
+}
+
+class TwoLines {
+ val p1 by Some
+
+
+ val p2 = 1
+
+
+ val p3: Int get() = 3
+
+
+ val p4: Int
+ get() { return 1 }
+
+
+ val p5: Int
+}
+
+class Some(b: Boolean) {
+ // Comment.
+ constructor(b: Int) : this(b == 0)
+ /**
+ * test
+ * 2
+ */
+ constructor(b: String) : this(b.isEmpty())
+ constructor(b: Long) : this(b == 0L)
+ @Ann
+ constructor(b: Int) : this(b == 0)
+ @Ann(
+ 42
+ )
+ constructor(b: String) : this(b.isEmpty())
+ constructor(b: Long) : this(b == 0L)
+}
+
+enum class TestEnum {
+ /** A comment for the item #1. */
+ ITEM1,
+ /** A comment for the item #2. */
+ ITEM2,
+ /** A comment for the item #3. */
+ ITEM3
+}
+
+class Foo {
+ @Inject
+ lateinit var logger: Logger
+ @Inject
+ lateinit var userService: UserService
+ @Inject
+ override lateinit var configBridge: ConfigBridge
+}
+
+// SET_INT: BLANK_LINES_BEFORE_DECLARATION_WITH_COMMENT_OR_ANNOTATION_ON_SEPARATE_LINE = 0
\ No newline at end of file
diff --git a/idea/testData/formatter/EmptyLineBetweenEnumEntries.after.inv.kt b/idea/testData/formatter/EmptyLineBetweenEnumEntries.after.inv.kt
index bccd3d5d8af..0b5984703d7 100644
--- a/idea/testData/formatter/EmptyLineBetweenEnumEntries.after.inv.kt
+++ b/idea/testData/formatter/EmptyLineBetweenEnumEntries.after.inv.kt
@@ -41,4 +41,15 @@ enum class E10 {
val x = 1
}
+enum class TestEnum {
+ /** A comment for the item #1. */
+ ITEM1,
+
+ /** A comment for the item #2. */
+ ITEM2,
+
+ /** A comment for the item #3. */
+ ITEM3
+}
+
// SET_TRUE: KEEP_LINE_BREAKS
\ No newline at end of file
diff --git a/idea/testData/formatter/EmptyLineBetweenEnumEntries.after.kt b/idea/testData/formatter/EmptyLineBetweenEnumEntries.after.kt
index 8bb5a518799..9f662d42253 100644
--- a/idea/testData/formatter/EmptyLineBetweenEnumEntries.after.kt
+++ b/idea/testData/formatter/EmptyLineBetweenEnumEntries.after.kt
@@ -43,4 +43,15 @@ enum class E10 {
val x = 1
}
+enum class TestEnum {
+ /** A comment for the item #1. */
+ ITEM1,
+
+ /** A comment for the item #2. */
+ ITEM2,
+
+ /** A comment for the item #3. */
+ ITEM3
+}
+
// SET_TRUE: KEEP_LINE_BREAKS
\ No newline at end of file
diff --git a/idea/testData/formatter/EmptyLineBetweenEnumEntries.kt b/idea/testData/formatter/EmptyLineBetweenEnumEntries.kt
index 01a4ffdf55c..bfee15da6a2 100644
--- a/idea/testData/formatter/EmptyLineBetweenEnumEntries.kt
+++ b/idea/testData/formatter/EmptyLineBetweenEnumEntries.kt
@@ -37,4 +37,13 @@ enum class E10 { F, S, T;
val x = 1
}
+enum class TestEnum {
+ /** A comment for the item #1. */
+ ITEM1,
+ /** A comment for the item #2. */
+ ITEM2,
+ /** A comment for the item #3. */
+ ITEM3
+}
+
// SET_TRUE: KEEP_LINE_BREAKS
\ No newline at end of file
diff --git a/idea/testData/formatter/EmptyLineBetweenProperties.after.kt b/idea/testData/formatter/EmptyLineBetweenProperties.after.kt
index d43bf7503d0..4a79171de72 100644
--- a/idea/testData/formatter/EmptyLineBetweenProperties.after.kt
+++ b/idea/testData/formatter/EmptyLineBetweenProperties.after.kt
@@ -40,4 +40,15 @@ class TwoLines {
val p5: Int
+}
+
+class Foo {
+ @Inject
+ lateinit var logger: Logger
+
+ @Inject
+ lateinit var userService: UserService
+
+ @Inject
+ override lateinit var configBridge: ConfigBridge
}
\ No newline at end of file
diff --git a/idea/testData/formatter/EmptyLineBetweenProperties.kt b/idea/testData/formatter/EmptyLineBetweenProperties.kt
index 6cdaedb3e39..7a3404e5352 100644
--- a/idea/testData/formatter/EmptyLineBetweenProperties.kt
+++ b/idea/testData/formatter/EmptyLineBetweenProperties.kt
@@ -34,4 +34,13 @@ class TwoLines {
val p5: Int
+}
+
+class Foo {
+ @Inject
+ lateinit var logger: Logger
+ @Inject
+ lateinit var userService: UserService
+ @Inject
+ override lateinit var configBridge: ConfigBridge
}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java
index 05da6eb8f2f..1495e2c96a7 100644
--- a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java
@@ -280,6 +280,16 @@ public class FormatterTestGenerated extends AbstractFormatterTest {
runTest("idea/testData/formatter/EmptyLineBetweeAbstractFunctions.after.kt");
}
+ @TestMetadata("EmptyLineBetweeMultilineDeclarationTwo.after.kt")
+ public void testEmptyLineBetweeMultilineDeclarationTwo() throws Exception {
+ runTest("idea/testData/formatter/EmptyLineBetweeMultilineDeclarationTwo.after.kt");
+ }
+
+ @TestMetadata("EmptyLineBetweeMultilineDeclarationZero.after.kt")
+ public void testEmptyLineBetweeMultilineDeclarationZero() throws Exception {
+ runTest("idea/testData/formatter/EmptyLineBetweeMultilineDeclarationZero.after.kt");
+ }
+
@TestMetadata("EmptyLineBetweeSecondaryConstructors.after.kt")
public void testEmptyLineBetweeSecondaryConstructors() throws Exception {
runTest("idea/testData/formatter/EmptyLineBetweeSecondaryConstructors.after.kt");