"Put/Join arguments/parameters" intention: don't suggest on nested argument list

#KT-31020 Fixed
This commit is contained in:
Toshiaki Kameyama
2019-12-24 14:31:16 +09:00
committed by Yan Zhulanow
parent be194c3460
commit 4a328981c6
17 changed files with 237 additions and 11 deletions
@@ -8,31 +8,33 @@ package org.jetbrains.kotlin.idea.intentions
import com.intellij.application.options.CodeStyle
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.psi.codeStyle.CommonCodeStyleSettings
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.inspections.findExistingEditor
import org.jetbrains.kotlin.idea.formatter.kotlinCommonSettings
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.allChildren
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.psi.psiUtil.siblings
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi.psiUtil.*
abstract class AbstractChopListIntention<TList : KtElement, TElement : KtElement>(
listClass: Class<TList>,
private val elementClass: Class<TElement>,
textGetter: () -> String
) : SelfTargetingOffsetIndependentIntention<TList>(listClass, textGetter) {
) : SelfTargetingIntention<TList>(listClass, textGetter) {
override fun allowCaretInsideElement(element: PsiElement) =
element !is KtValueArgument && super.allowCaretInsideElement(element)
open fun leftParOnNewLine(commonCodeStyleSettings: CommonCodeStyleSettings): Boolean = false
open fun rightParOnNewLine(commonCodeStyleSettings: CommonCodeStyleSettings): Boolean = false
override fun isApplicableTo(element: TList): Boolean {
override fun isApplicableTo(element: TList, caretOffset: Int): Boolean {
val elements = element.elements()
if (elements.size <= 1) return false
if (!isApplicableCaretOffset(caretOffset, element)) return false
if (elements.dropLast(1).all { hasLineBreakAfter(it) }) return false
return true
}
@@ -82,6 +84,12 @@ abstract class AbstractChopListIntention<TList : KtElement, TElement : KtElement
it as TElement
}
.toList()
protected fun isApplicableCaretOffset(caretOffset: Int, element: TList): Boolean {
val elementBeforeCaret = element.containingFile.findElementAt(caretOffset - 1) ?: return true
if (elementBeforeCaret.node.elementType != KtTokens.RPAR) return true
return elementBeforeCaret.parent == element
}
}
class ChopParameterListIntention : AbstractChopListIntention<KtParameterList, KtParameter>(
@@ -89,9 +97,9 @@ class ChopParameterListIntention : AbstractChopListIntention<KtParameterList, Kt
KtParameter::class.java,
KotlinBundle.lazyMessage("put.parameters.on.separate.lines")
) {
override fun isApplicableTo(element: KtParameterList): Boolean {
override fun isApplicableTo(element: KtParameterList, caretOffset: Int): Boolean {
if (element.parent is KtFunctionLiteral) return false
return super.isApplicableTo(element)
return super.isApplicableTo(element, caretOffset)
}
override fun leftParOnNewLine(commonCodeStyleSettings: CommonCodeStyleSettings): Boolean {
@@ -22,9 +22,10 @@ abstract class AbstractJoinListIntention<TList : KtElement, TElement : KtElement
elementClass: Class<TElement>,
textGetter: () -> String
) : AbstractChopListIntention<TList, TElement>(listClass, elementClass, textGetter) {
override fun isApplicableTo(element: TList): Boolean {
override fun isApplicableTo(element: TList, caretOffset: Int): Boolean {
val elements = element.elements()
if (elements.isEmpty()) return false
if (!isApplicableCaretOffset(caretOffset, element)) return false
return (hasLineBreakBefore(elements.first()) || elements.any { hasLineBreakAfter(it) })
&& element.allChildren.none { it is PsiComment && it.node.elementType == KtTokens.EOL_COMMENT }
}
@@ -53,9 +54,9 @@ class JoinParameterListIntention : AbstractJoinListIntention<KtParameterList, Kt
KtParameter::class.java,
KotlinBundle.lazyMessage("put.parameters.on.one.line")
) {
override fun isApplicableTo(element: KtParameterList): Boolean {
override fun isApplicableTo(element: KtParameterList, caretOffset: Int): Boolean {
if (element.parent is KtFunctionLiteral) return false
return super.isApplicableTo(element)
return super.isApplicableTo(element, caretOffset)
}
}
@@ -0,0 +1,12 @@
// IS_APPLICABLE: false
fun foo() {
f(1, 2, g(<caret>
3,
4,
5
), 3)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,12 @@
// IS_APPLICABLE: false
fun foo() {
f(1, 2, g<caret>(
3,
4,
5
), 3)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,12 @@
// IS_APPLICABLE: false
fun foo() {
f(1, 2, g(
3,
4,
5
)<caret>, 3)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,12 @@
fun foo() {
f(
1,
2,
g(3, 4, 5)<caret>,
3
)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,16 @@
fun foo() {
f(
1,
2,
g(
3,
4,
5
),
3
)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,11 @@
fun foo() {
f(1, 2, g(
3,
4,
5
), 3)<caret>
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,16 @@
fun foo() {
f(
1,
2,
g(
3,
4,
5
),
3
)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,13 @@
// IS_APPLICABLE: false
fun foo() {
f(
1,
2,
g(<caret>3, 4, 5),
3
)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,13 @@
// IS_APPLICABLE: false
fun foo() {
f(
1,
2,
g<caret>(3, 4, 5),
3
)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,13 @@
// IS_APPLICABLE: false
fun foo() {
f(
1,
2,
g(3, 4, 5)<caret>,
3
)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,11 @@
fun foo() {
f(1, 2, g(
3,
4,
5
)<caret>, 3)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,7 @@
fun foo() {
f(1, 2, g(3, 4, 5), 3)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,12 @@
fun foo() {
f(
1,
2,
g(3, 4, 5),
3
)<caret>
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -0,0 +1,7 @@
fun foo() {
f(1, 2, g(3, 4, 5), 3)
}
fun f(a: Int, b: Int, c: Int, d: Int): Int = 0
fun g(a: Int, b: Int, c: Int): Int = 0
@@ -3763,6 +3763,31 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/intentions/chop/argumentList"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), null, true);
}
@TestMetadata("onNestedArgumentList.kt")
public void testOnNestedArgumentList() throws Exception {
runTest("idea/testData/intentions/chop/argumentList/onNestedArgumentList.kt");
}
@TestMetadata("onNestedArgumentList2.kt")
public void testOnNestedArgumentList2() throws Exception {
runTest("idea/testData/intentions/chop/argumentList/onNestedArgumentList2.kt");
}
@TestMetadata("onNestedArgumentList3.kt")
public void testOnNestedArgumentList3() throws Exception {
runTest("idea/testData/intentions/chop/argumentList/onNestedArgumentList3.kt");
}
@TestMetadata("onNestedArgumentList4.kt")
public void testOnNestedArgumentList4() throws Exception {
runTest("idea/testData/intentions/chop/argumentList/onNestedArgumentList4.kt");
}
@TestMetadata("onRightParenthesis.kt")
public void testOnRightParenthesis() throws Exception {
runTest("idea/testData/intentions/chop/argumentList/onRightParenthesis.kt");
}
@TestMetadata("leftParOnSameLine.kt")
public void testLeftParOnSameLine() throws Exception {
runTest("idea/testData/intentions/chop/argumentList/leftParOnSameLine.kt");
@@ -10668,6 +10693,31 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
runTest("idea/testData/intentions/joinArgumentList/noLineBreak.kt");
}
@TestMetadata("onNestedArgumentList.kt")
public void testOnNestedArgumentList() throws Exception {
runTest("idea/testData/intentions/joinArgumentList/onNestedArgumentList.kt");
}
@TestMetadata("onNestedArgumentList2.kt")
public void testOnNestedArgumentList2() throws Exception {
runTest("idea/testData/intentions/joinArgumentList/onNestedArgumentList2.kt");
}
@TestMetadata("onNestedArgumentList3.kt")
public void testOnNestedArgumentList3() throws Exception {
runTest("idea/testData/intentions/joinArgumentList/onNestedArgumentList3.kt");
}
@TestMetadata("onNestedArgumentList4.kt")
public void testOnNestedArgumentList4() throws Exception {
runTest("idea/testData/intentions/joinArgumentList/onNestedArgumentList4.kt");
}
@TestMetadata("onRightParenthesis.kt")
public void testOnRightParenthesis() throws Exception {
runTest("idea/testData/intentions/joinArgumentList/onRightParenthesis.kt");
}
@TestMetadata("oneArg.kt")
public void testOneArg() throws Exception {
runTest("idea/testData/intentions/joinArgumentList/oneArg.kt");