diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/PsiLinesUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/PsiLinesUtils.kt
index b9a1112d8d7..93dee301d46 100644
--- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/PsiLinesUtils.kt
+++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/PsiLinesUtils.kt
@@ -5,11 +5,13 @@
package org.jetbrains.kotlin.idea.core.util
+import com.intellij.openapi.editor.Document
import com.intellij.openapi.util.TextRange
import com.intellij.psi.*
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
+import kotlin.math.abs
fun PsiFile.getLineStartOffset(line: Int): Int? {
return getLineStartOffset(line, skipWhitespace = true)
@@ -56,4 +58,8 @@ fun PsiElement.getLineCount(): Int {
return (text ?: "").count { it == '\n' } + 1
}
-fun PsiElement.isMultiLine(): Boolean = getLineCount() > 1
\ No newline at end of file
+fun PsiElement.isMultiLine(): Boolean = getLineCount() > 1
+
+fun Document.getLineCountInRange(textRange: TextRange): Int = abs(getLineNumber(textRange.startOffset) - getLineNumber(textRange.endOffset))
+
+fun Document.containsLineBreakInRange(textRange: TextRange): Boolean = getLineCountInRange(textRange) != 0
\ No newline at end of file
diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml
index d90e7248458..eedcf5fb0ba 100644
--- a/idea/resources/META-INF/plugin-common.xml
+++ b/idea/resources/META-INF/plugin-common.xml
@@ -813,6 +813,7 @@
+
+ b,) = 1 to 2
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/destructionDeclaration.kt.after b/idea/testData/joinLines/removeTrailingComma/destructionDeclaration.kt.after
new file mode 100644
index 00000000000..760e08b57da
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/destructionDeclaration.kt.after
@@ -0,0 +1,3 @@
+fun a() {
+ val (a, b) = 1 to 2
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/destructionDeclarationInLambda.kt b/idea/testData/joinLines/removeTrailingComma/destructionDeclarationInLambda.kt
new file mode 100644
index 00000000000..c71d9d1c9b0
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/destructionDeclarationInLambda.kt
@@ -0,0 +1,4 @@
+fun a() {
+ val a = { (a, b // awd
+ ,/**/), c, -> }
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/destructionDeclarationInLambda.kt.after b/idea/testData/joinLines/removeTrailingComma/destructionDeclarationInLambda.kt.after
new file mode 100644
index 00000000000..88a4d7e961c
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/destructionDeclarationInLambda.kt.after
@@ -0,0 +1,3 @@
+fun a() {
+ val a = { (a, b /* awd*//**/), c -> }
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/inner.kt b/idea/testData/joinLines/removeTrailingComma/inner.kt
new file mode 100644
index 00000000000..f4f73ddc1b8
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/inner.kt
@@ -0,0 +1,4 @@
+fun a(
+ a: Int, b: Any = fun(a: Int,),) {
+
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/inner.kt.after b/idea/testData/joinLines/removeTrailingComma/inner.kt.after
new file mode 100644
index 00000000000..9ac3d04f849
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/inner.kt.after
@@ -0,0 +1,3 @@
+fun a(a: Int, b: Any = fun(a: Int)) {
+
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/lambda.kt b/idea/testData/joinLines/removeTrailingComma/lambda.kt
new file mode 100644
index 00000000000..d81bdee9c3e
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/lambda.kt
@@ -0,0 +1,6 @@
+fun a() {
+ val a = { a: Int,
+ b: Int, ->
+
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/lambda.kt.after b/idea/testData/joinLines/removeTrailingComma/lambda.kt.after
new file mode 100644
index 00000000000..ed316b9319b
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/lambda.kt.after
@@ -0,0 +1,5 @@
+fun a() {
+ val a = { a: Int, b: Int ->
+
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/simple.kt b/idea/testData/joinLines/removeTrailingComma/simple.kt
new file mode 100644
index 00000000000..2d13af5c61e
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/simple.kt
@@ -0,0 +1,4 @@
+fun a(
+ a: Int,) {
+
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/simple.kt.after b/idea/testData/joinLines/removeTrailingComma/simple.kt.after
new file mode 100644
index 00000000000..ab672a35c47
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/simple.kt.after
@@ -0,0 +1,3 @@
+fun a(a: Int) {
+
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/typeParameters.kt b/idea/testData/joinLines/removeTrailingComma/typeParameters.kt
new file mode 100644
index 00000000000..17931b22775
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/typeParameters.kt
@@ -0,0 +1,2 @@
+fun
+ B,> a() = Unit
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/typeParameters.kt.after b/idea/testData/joinLines/removeTrailingComma/typeParameters.kt.after
new file mode 100644
index 00000000000..5af5907fb67
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/typeParameters.kt.after
@@ -0,0 +1 @@
+fun > a() = Unit
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/whenEntry.kt b/idea/testData/joinLines/removeTrailingComma/whenEntry.kt
new file mode 100644
index 00000000000..806571b30be
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/whenEntry.kt
@@ -0,0 +1,7 @@
+fun a() {
+ when (val b = 5) {
+ 1, 2,
+ 3,
+ ->
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/whenEntry.kt.after b/idea/testData/joinLines/removeTrailingComma/whenEntry.kt.after
new file mode 100644
index 00000000000..3a0ec82825c
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/whenEntry.kt.after
@@ -0,0 +1,6 @@
+fun a() {
+ when (val b = 5) {
+ 1, 2,
+ 3, ->
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/whenEntry2.kt b/idea/testData/joinLines/removeTrailingComma/whenEntry2.kt
new file mode 100644
index 00000000000..7d8dc9694d3
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/whenEntry2.kt
@@ -0,0 +1,6 @@
+fun a() {
+ when (val b = 5) {
+ 1, 2,
+ 3, ->
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/joinLines/removeTrailingComma/whenEntry2.kt.after b/idea/testData/joinLines/removeTrailingComma/whenEntry2.kt.after
new file mode 100644
index 00000000000..a21eaba6047
--- /dev/null
+++ b/idea/testData/joinLines/removeTrailingComma/whenEntry2.kt.after
@@ -0,0 +1,5 @@
+fun a() {
+ when (val b = 5) {
+ 1, 2, 3 ->
+ }
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/declarations/JoinLinesTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/declarations/JoinLinesTestGenerated.java
index fa8d15f9a1c..cdb339aecca 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/intentions/declarations/JoinLinesTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/declarations/JoinLinesTestGenerated.java
@@ -393,6 +393,59 @@ public class JoinLinesTestGenerated extends AbstractJoinLinesTest {
}
}
+ @TestMetadata("idea/testData/joinLines/removeTrailingComma")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class RemoveTrailingComma extends AbstractJoinLinesTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+ }
+
+ public void testAllFilesPresentInRemoveTrailingComma() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/joinLines/removeTrailingComma"), Pattern.compile("^(.+)\\.kt$"), null, true);
+ }
+
+ @TestMetadata("destructionDeclaration.kt")
+ public void testDestructionDeclaration() throws Exception {
+ runTest("idea/testData/joinLines/removeTrailingComma/destructionDeclaration.kt");
+ }
+
+ @TestMetadata("destructionDeclarationInLambda.kt")
+ public void testDestructionDeclarationInLambda() throws Exception {
+ runTest("idea/testData/joinLines/removeTrailingComma/destructionDeclarationInLambda.kt");
+ }
+
+ @TestMetadata("inner.kt")
+ public void testInner() throws Exception {
+ runTest("idea/testData/joinLines/removeTrailingComma/inner.kt");
+ }
+
+ @TestMetadata("lambda.kt")
+ public void testLambda() throws Exception {
+ runTest("idea/testData/joinLines/removeTrailingComma/lambda.kt");
+ }
+
+ @TestMetadata("simple.kt")
+ public void testSimple() throws Exception {
+ runTest("idea/testData/joinLines/removeTrailingComma/simple.kt");
+ }
+
+ @TestMetadata("typeParameters.kt")
+ public void testTypeParameters() throws Exception {
+ runTest("idea/testData/joinLines/removeTrailingComma/typeParameters.kt");
+ }
+
+ @TestMetadata("whenEntry.kt")
+ public void testWhenEntry() throws Exception {
+ runTest("idea/testData/joinLines/removeTrailingComma/whenEntry.kt");
+ }
+
+ @TestMetadata("whenEntry2.kt")
+ public void testWhenEntry2() throws Exception {
+ runTest("idea/testData/joinLines/removeTrailingComma/whenEntry2.kt");
+ }
+ }
+
@TestMetadata("idea/testData/joinLines/stringTemplate")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)