"Put/Join arguments/parameters" intention: don't suggest on nested argument list
#KT-31020 Fixed
This commit is contained in:
committed by
Yan Zhulanow
parent
be194c3460
commit
4a328981c6
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user