diff --git a/idea/resources/intentionDescriptions/JoinArgumentListIntention/after.kt.template b/idea/resources/intentionDescriptions/JoinArgumentListIntention/after.kt.template
new file mode 100644
index 00000000000..d7c0cd5caa6
--- /dev/null
+++ b/idea/resources/intentionDescriptions/JoinArgumentListIntention/after.kt.template
@@ -0,0 +1,3 @@
+fun foo() {
+ bar(1, "abcd", false)
+}
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/JoinArgumentListIntention/before.kt.template b/idea/resources/intentionDescriptions/JoinArgumentListIntention/before.kt.template
new file mode 100644
index 00000000000..2d719eff48b
--- /dev/null
+++ b/idea/resources/intentionDescriptions/JoinArgumentListIntention/before.kt.template
@@ -0,0 +1,7 @@
+fun foo() {
+ bar(
+ 1,
+ "abcd",
+ false
+ )
+}
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/JoinArgumentListIntention/description.html b/idea/resources/intentionDescriptions/JoinArgumentListIntention/description.html
new file mode 100644
index 00000000000..ec693132c2c
--- /dev/null
+++ b/idea/resources/intentionDescriptions/JoinArgumentListIntention/description.html
@@ -0,0 +1,5 @@
+
+
+This intention formats a function call placing all arguments on a single line.
+
+
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/JoinParameterListIntention/after.kt.template b/idea/resources/intentionDescriptions/JoinParameterListIntention/after.kt.template
new file mode 100644
index 00000000000..7750583e605
--- /dev/null
+++ b/idea/resources/intentionDescriptions/JoinParameterListIntention/after.kt.template
@@ -0,0 +1,3 @@
+fun foo(param1: String, param2: Int, param3: Any) {
+ bar()
+}
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/JoinParameterListIntention/before.kt.template b/idea/resources/intentionDescriptions/JoinParameterListIntention/before.kt.template
new file mode 100644
index 00000000000..190a75155f9
--- /dev/null
+++ b/idea/resources/intentionDescriptions/JoinParameterListIntention/before.kt.template
@@ -0,0 +1,7 @@
+fun foo(
+ param1: String,
+ param2: Int,
+ param3: Any
+) {
+ bar()
+}
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/JoinParameterListIntention/description.html b/idea/resources/intentionDescriptions/JoinParameterListIntention/description.html
new file mode 100644
index 00000000000..3729dc1d076
--- /dev/null
+++ b/idea/resources/intentionDescriptions/JoinParameterListIntention/description.html
@@ -0,0 +1,5 @@
+
+
+This intention formats parameters of a declaration placing all parameters on a single line.
+
+
\ No newline at end of file
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index de6b8dc6492..6b3675727a7 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -1572,6 +1572,16 @@
Kotlin
+
+ org.jetbrains.kotlin.idea.intentions.JoinParameterListIntention
+ Kotlin
+
+
+
+ org.jetbrains.kotlin.idea.intentions.JoinArgumentListIntention
+ Kotlin
+
+
(
- private val listClass: Class,
- private val elementClass: Class,
- text: String
+ private val listClass: Class,
+ private val elementClass: Class,
+ text: String
) : SelfTargetingOffsetIndependentIntention(listClass, text), LowPriorityAction {
override fun isApplicableTo(element: TList): Boolean {
@@ -41,20 +41,20 @@ abstract class AbstractChopListIntention {
+ protected fun hasLineBreakBefore(element: TElement): Boolean {
+ return prevBreak(element) != null
+ }
+
+ protected fun prevBreak(element: TElement): PsiWhiteSpace? {
+ return element
+ .siblings(withItself = false, forward = false)
+ .takeWhile { !elementClass.isInstance(it) }
+ .firstOrNull { it is PsiWhiteSpace && it.textContains('\n') } as? PsiWhiteSpace
+ }
+
+ protected fun TList.elements(): List {
return allChildren
- .filter { elementClass.isInstance(it) }
- .map {
- @Suppress("UNCHECKED_CAST")
- it as TElement
- }
- .toList()
+ .filter { elementClass.isInstance(it) }
+ .map {
+ @Suppress("UNCHECKED_CAST")
+ it as TElement
+ }
+ .toList()
}
}
class ChopParameterListIntention : AbstractChopListIntention(
- KtParameterList::class.java,
- KtParameter::class.java,
- "Put parameters on separate lines"
+ KtParameterList::class.java,
+ KtParameter::class.java,
+ "Put parameters on separate lines"
) {
override fun isApplicableTo(element: KtParameterList): Boolean {
if (element.parent is KtFunctionLiteral) return false
@@ -102,7 +110,7 @@ class ChopParameterListIntention : AbstractChopListIntention(
- KtValueArgumentList::class.java,
- KtValueArgument::class.java,
- "Put arguments on separate lines"
+ KtValueArgumentList::class.java,
+ KtValueArgument::class.java,
+ "Put arguments on separate lines"
)
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/JoinParameterListIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/JoinParameterListIntention.kt
new file mode 100644
index 00000000000..d9b3791ebde
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/JoinParameterListIntention.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
+ * that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.idea.intentions
+
+import com.intellij.openapi.editor.Editor
+import org.jetbrains.kotlin.psi.*
+
+abstract class AbstractJoinListIntention(
+ listClass: Class,
+ elementClass: Class,
+ text: String
+) : AbstractChopListIntention(listClass, elementClass, text) {
+
+ override fun isApplicableTo(element: TList): Boolean {
+ val elements = element.elements()
+ if (elements.isEmpty()) return false
+ return hasLineBreakBefore(elements.first()) || elements.any { hasLineBreakAfter(it) }
+ }
+
+ override fun applyTo(element: TList, editor: Editor?) {
+ val elements = element.elements()
+ prevBreak(elements.first())?.delete()
+ elements.forEach { nextBreak(it)?.delete() }
+ }
+
+}
+
+class JoinParameterListIntention : AbstractJoinListIntention(
+ KtParameterList::class.java,
+ KtParameter::class.java,
+ "Put parameters on one line"
+) {
+ override fun isApplicableTo(element: KtParameterList): Boolean {
+ if (element.parent is KtFunctionLiteral) return false
+ return super.isApplicableTo(element)
+ }
+}
+
+class JoinArgumentListIntention : AbstractJoinListIntention(
+ KtValueArgumentList::class.java,
+ KtValueArgument::class.java,
+ "Put arguments on one line"
+)
diff --git a/idea/testData/intentions/joinArgumentList/.intention b/idea/testData/intentions/joinArgumentList/.intention
new file mode 100644
index 00000000000..2898110acae
--- /dev/null
+++ b/idea/testData/intentions/joinArgumentList/.intention
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.intentions.JoinArgumentListIntention
diff --git a/idea/testData/intentions/joinArgumentList/hasLineBreakBeforeFirstArg.kt b/idea/testData/intentions/joinArgumentList/hasLineBreakBeforeFirstArg.kt
new file mode 100644
index 00000000000..59a67a87ee0
--- /dev/null
+++ b/idea/testData/intentions/joinArgumentList/hasLineBreakBeforeFirstArg.kt
@@ -0,0 +1,6 @@
+fun foo(a: Int = 1, b: Int = 1, c: Int = 1) {}
+
+fun bar(a: Int, b: Int, c: Int) {
+ foo(
+ a, b, c)
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinArgumentList/hasLineBreakBeforeFirstArg.kt.after b/idea/testData/intentions/joinArgumentList/hasLineBreakBeforeFirstArg.kt.after
new file mode 100644
index 00000000000..a74604d207b
--- /dev/null
+++ b/idea/testData/intentions/joinArgumentList/hasLineBreakBeforeFirstArg.kt.after
@@ -0,0 +1,5 @@
+fun foo(a: Int = 1, b: Int = 1, c: Int = 1) {}
+
+fun bar(a: Int, b: Int, c: Int) {
+ foo(a, b, c)
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinArgumentList/hasLineBreaks.kt b/idea/testData/intentions/joinArgumentList/hasLineBreaks.kt
new file mode 100644
index 00000000000..b47b6402cdf
--- /dev/null
+++ b/idea/testData/intentions/joinArgumentList/hasLineBreaks.kt
@@ -0,0 +1,11 @@
+// INTENTION_TEXT: "Put arguments on one line"
+
+fun foo(a: Int = 1, b: Int = 1, c: Int = 1) {}
+
+fun bar(a: Int, b: Int, c: Int) {
+ foo(
+ a,
+ b,
+ c
+ )
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinArgumentList/hasLineBreaks.kt.after b/idea/testData/intentions/joinArgumentList/hasLineBreaks.kt.after
new file mode 100644
index 00000000000..8e332a8eb48
--- /dev/null
+++ b/idea/testData/intentions/joinArgumentList/hasLineBreaks.kt.after
@@ -0,0 +1,7 @@
+// INTENTION_TEXT: "Put arguments on one line"
+
+fun foo(a: Int = 1, b: Int = 1, c: Int = 1) {}
+
+fun bar(a: Int, b: Int, c: Int) {
+ foo(a, b, c)
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinArgumentList/noArg.kt b/idea/testData/intentions/joinArgumentList/noArg.kt
new file mode 100644
index 00000000000..a2a03cf08f8
--- /dev/null
+++ b/idea/testData/intentions/joinArgumentList/noArg.kt
@@ -0,0 +1,7 @@
+// IS_APPLICABLE: false
+
+fun foo(a: Int = 1, b: Int = 1, c: Int = 1) {}
+
+fun bar(a: Int, b: Int, c: Int) {
+ foo()
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinArgumentList/noLineBreak.kt b/idea/testData/intentions/joinArgumentList/noLineBreak.kt
new file mode 100644
index 00000000000..a93dd7716ed
--- /dev/null
+++ b/idea/testData/intentions/joinArgumentList/noLineBreak.kt
@@ -0,0 +1,7 @@
+// IS_APPLICABLE: false
+
+fun foo(a: Int = 1, b: Int = 1, c: Int = 1) {}
+
+fun bar(a: Int, b: Int, c: Int) {
+ foo(a, b, c)
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinArgumentList/oneArg.kt b/idea/testData/intentions/joinArgumentList/oneArg.kt
new file mode 100644
index 00000000000..16016c2163a
--- /dev/null
+++ b/idea/testData/intentions/joinArgumentList/oneArg.kt
@@ -0,0 +1,7 @@
+fun foo(a: Int = 1, b: Int = 1, c: Int = 1) {}
+
+fun bar(a: Int, b: Int, c: Int) {
+ foo(
+ a
+ )
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinArgumentList/oneArg.kt.after b/idea/testData/intentions/joinArgumentList/oneArg.kt.after
new file mode 100644
index 00000000000..8c23f9213b0
--- /dev/null
+++ b/idea/testData/intentions/joinArgumentList/oneArg.kt.after
@@ -0,0 +1,5 @@
+fun foo(a: Int = 1, b: Int = 1, c: Int = 1) {}
+
+fun bar(a: Int, b: Int, c: Int) {
+ foo(a)
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinParameterList/.intention b/idea/testData/intentions/joinParameterList/.intention
new file mode 100644
index 00000000000..8b7bd760e10
--- /dev/null
+++ b/idea/testData/intentions/joinParameterList/.intention
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.intentions.JoinParameterListIntention
diff --git a/idea/testData/intentions/joinParameterList/hasLineBreakBeforeFirstParam.kt b/idea/testData/intentions/joinParameterList/hasLineBreakBeforeFirstParam.kt
new file mode 100644
index 00000000000..1cf293711d5
--- /dev/null
+++ b/idea/testData/intentions/joinParameterList/hasLineBreakBeforeFirstParam.kt
@@ -0,0 +1,2 @@
+fun test(
+ a: Int, b: Int, c: Int) {}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinParameterList/hasLineBreakBeforeFirstParam.kt.after b/idea/testData/intentions/joinParameterList/hasLineBreakBeforeFirstParam.kt.after
new file mode 100644
index 00000000000..7ad8b2ff6fb
--- /dev/null
+++ b/idea/testData/intentions/joinParameterList/hasLineBreakBeforeFirstParam.kt.after
@@ -0,0 +1 @@
+fun test(a: Int, b: Int, c: Int) {}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinParameterList/hasLineBreaks.kt b/idea/testData/intentions/joinParameterList/hasLineBreaks.kt
new file mode 100644
index 00000000000..9a69c7b2325
--- /dev/null
+++ b/idea/testData/intentions/joinParameterList/hasLineBreaks.kt
@@ -0,0 +1,7 @@
+// INTENTION_TEXT: "Put parameters on one line"
+
+fun test(
+ a: Int,
+ b: Int,
+ c: Int
+) {}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinParameterList/hasLineBreaks.kt.after b/idea/testData/intentions/joinParameterList/hasLineBreaks.kt.after
new file mode 100644
index 00000000000..9739b3502ed
--- /dev/null
+++ b/idea/testData/intentions/joinParameterList/hasLineBreaks.kt.after
@@ -0,0 +1,3 @@
+// INTENTION_TEXT: "Put parameters on one line"
+
+fun test(a: Int, b: Int, c: Int) {}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinParameterList/noLineBreak.kt b/idea/testData/intentions/joinParameterList/noLineBreak.kt
new file mode 100644
index 00000000000..ebef9cbe491
--- /dev/null
+++ b/idea/testData/intentions/joinParameterList/noLineBreak.kt
@@ -0,0 +1,3 @@
+// IS_APPLICABLE: false
+
+fun test(a: Int, b: Int, c: Int) {}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinParameterList/noParam.kt b/idea/testData/intentions/joinParameterList/noParam.kt
new file mode 100644
index 00000000000..d35cb73b60e
--- /dev/null
+++ b/idea/testData/intentions/joinParameterList/noParam.kt
@@ -0,0 +1,3 @@
+// IS_APPLICABLE: false
+
+fun test() {}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinParameterList/oneParam.kt b/idea/testData/intentions/joinParameterList/oneParam.kt
new file mode 100644
index 00000000000..4d36416cbae
--- /dev/null
+++ b/idea/testData/intentions/joinParameterList/oneParam.kt
@@ -0,0 +1,3 @@
+fun test(
+ a: Int
+) {}
\ No newline at end of file
diff --git a/idea/testData/intentions/joinParameterList/oneParam.kt.after b/idea/testData/intentions/joinParameterList/oneParam.kt.after
new file mode 100644
index 00000000000..08511c22773
--- /dev/null
+++ b/idea/testData/intentions/joinParameterList/oneParam.kt.after
@@ -0,0 +1 @@
+fun test(a: Int) {}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
index ce1271dc223..9a2de2e5997 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
@@ -10048,6 +10048,45 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
}
}
+ @TestMetadata("idea/testData/intentions/joinArgumentList")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class JoinArgumentList extends AbstractIntentionTest {
+ public void testAllFilesPresentInJoinArgumentList() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/joinArgumentList"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("hasLineBreakBeforeFirstArg.kt")
+ public void testHasLineBreakBeforeFirstArg() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinArgumentList/hasLineBreakBeforeFirstArg.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("hasLineBreaks.kt")
+ public void testHasLineBreaks() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinArgumentList/hasLineBreaks.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("noArg.kt")
+ public void testNoArg() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinArgumentList/noArg.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("noLineBreak.kt")
+ public void testNoLineBreak() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinArgumentList/noLineBreak.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("oneArg.kt")
+ public void testOneArg() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinArgumentList/oneArg.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("idea/testData/intentions/joinDeclarationAndAssignment")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -10201,6 +10240,45 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
}
}
+ @TestMetadata("idea/testData/intentions/joinParameterList")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class JoinParameterList extends AbstractIntentionTest {
+ public void testAllFilesPresentInJoinParameterList() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/joinParameterList"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("hasLineBreakBeforeFirstParam.kt")
+ public void testHasLineBreakBeforeFirstParam() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinParameterList/hasLineBreakBeforeFirstParam.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("hasLineBreaks.kt")
+ public void testHasLineBreaks() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinParameterList/hasLineBreaks.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("noLineBreak.kt")
+ public void testNoLineBreak() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinParameterList/noLineBreak.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("noParam.kt")
+ public void testNoParam() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinParameterList/noParam.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("oneParam.kt")
+ public void testOneParam() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinParameterList/oneParam.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("idea/testData/intentions/loopToCallChain")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)