Invert if condition intention: 'isEmpty' <-> 'isNotEmpty'
#KT-34593 Fixed
This commit is contained in:
committed by
Vladimir Dolzhenko
parent
79c15e49b6
commit
d5e71ebef1
+23
-14
@@ -24,20 +24,10 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
class ReplaceNegatedIsEmptyWithIsNotEmptyInspection : AbstractKotlinInspection() {
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||
return qualifiedExpressionVisitor(fun(expression) {
|
||||
val callExpression = expression.callExpression ?: return
|
||||
val calleeExpression = callExpression.calleeExpression ?: return
|
||||
val calleeText = calleeExpression.text
|
||||
val isEmptyCall = calleeText == "isEmpty"
|
||||
val isNotEmptyCall = calleeText == "isNotEmpty"
|
||||
if (!isEmptyCall && !isNotEmptyCall) return
|
||||
|
||||
val prefixExpression = expression.getWrappingPrefixExpressionIfAny() ?: return
|
||||
if (prefixExpression.operationToken != KtTokens.EXCL) return
|
||||
|
||||
if (isEmptyCall && isEmptyFunctions.none { callExpression.isCalling(FqName(it)) }
|
||||
|| isNotEmptyCall && isNotEmptyFunctions.none { callExpression.isCalling(FqName(it)) }) return
|
||||
|
||||
val (from, to) = if (isEmptyCall) "isEmpty" to "isNotEmpty" else "isNotEmpty" to "isEmpty"
|
||||
if (expression.getWrappingPrefixExpressionIfAny()?.operationToken != KtTokens.EXCL) return
|
||||
val calleeExpression = expression.callExpression?.calleeExpression ?: return
|
||||
val from = calleeExpression.text
|
||||
val to = expression.invertSelectorFunction()?.callExpression?.calleeExpression?.text ?: return
|
||||
holder.registerProblem(
|
||||
calleeExpression,
|
||||
"Replace negated '$from' with '$to'",
|
||||
@@ -46,6 +36,25 @@ class ReplaceNegatedIsEmptyWithIsNotEmptyInspection : AbstractKotlinInspection()
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun KtQualifiedExpression.invertSelectorFunction(): KtQualifiedExpression? {
|
||||
val callExpression = this.callExpression ?: return null
|
||||
val calleeExpression = callExpression.calleeExpression ?: return null
|
||||
val calleeText = calleeExpression.text
|
||||
val isEmptyCall = calleeText == "isEmpty"
|
||||
val isNotEmptyCall = calleeText == "isNotEmpty"
|
||||
if (!isEmptyCall && !isNotEmptyCall) return null
|
||||
if (isEmptyCall && isEmptyFunctions.none { callExpression.isCalling(FqName(it)) }
|
||||
|| isNotEmptyCall && isNotEmptyFunctions.none { callExpression.isCalling(FqName(it)) }) return null
|
||||
val to = if (isEmptyCall) "isNotEmpty" else "isEmpty"
|
||||
return KtPsiFactory(this).createExpressionByPattern(
|
||||
"$0.$to()",
|
||||
this.receiverExpression,
|
||||
reformat = false
|
||||
) as? KtQualifiedExpression
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ReplaceNegatedIsEmptyWithIsNotEmptyQuickFix(private val from: String, private val to: String) : LocalQuickFix {
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.core.moveCaret
|
||||
import org.jetbrains.kotlin.idea.core.replaced
|
||||
import org.jetbrains.kotlin.idea.core.unblockDocument
|
||||
import org.jetbrains.kotlin.idea.inspections.ReplaceNegatedIsEmptyWithIsNotEmptyInspection.Companion.invertSelectorFunction
|
||||
import org.jetbrains.kotlin.idea.refactoring.getLineNumber
|
||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches
|
||||
@@ -39,7 +40,8 @@ class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>(KtIfEx
|
||||
element.nextEolCommentOnSameLine()?.delete()
|
||||
}
|
||||
|
||||
val newCondition = element.condition!!.negate()
|
||||
val condition = element.condition!!
|
||||
val newCondition = (condition as? KtQualifiedExpression)?.invertSelectorFunction() ?: condition.negate()
|
||||
|
||||
val newIf = handleSpecialCases(element, newCondition) ?: handleStandardCase(element, newCondition)
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// WITH_RUNTIME
|
||||
fun foo(i: Int) {}
|
||||
|
||||
fun test(s: String) {
|
||||
<caret>if (s.isEmpty()) {
|
||||
foo(1)
|
||||
} else {
|
||||
foo(2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// WITH_RUNTIME
|
||||
fun foo(i: Int) {}
|
||||
|
||||
fun test(s: String) {
|
||||
<caret>if (s.isNotEmpty()) {
|
||||
foo(2)
|
||||
} else {
|
||||
foo(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// WITH_RUNTIME
|
||||
fun foo(i: Int) {}
|
||||
|
||||
fun test(s: String) {
|
||||
<caret>if (s.isNotEmpty()) {
|
||||
foo(1)
|
||||
} else {
|
||||
foo(2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// WITH_RUNTIME
|
||||
fun foo(i: Int) {}
|
||||
|
||||
fun test(s: String) {
|
||||
<caret>if (s.isEmpty()) {
|
||||
foo(2)
|
||||
} else {
|
||||
foo(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// WITH_RUNTIME
|
||||
fun foo(i: Int) {}
|
||||
|
||||
fun test(s: String) {
|
||||
<caret>if (!s.isEmpty()) {
|
||||
foo(1)
|
||||
} else {
|
||||
foo(2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// WITH_RUNTIME
|
||||
fun foo(i: Int) {}
|
||||
|
||||
fun test(s: String) {
|
||||
<caret>if (s.isEmpty()) {
|
||||
foo(2)
|
||||
} else {
|
||||
foo(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// WITH_RUNTIME
|
||||
fun foo(i: Int) {}
|
||||
|
||||
fun test(s: String) {
|
||||
<caret>if (!s.isNotEmpty()) {
|
||||
foo(1)
|
||||
} else {
|
||||
foo(2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// WITH_RUNTIME
|
||||
fun foo(i: Int) {}
|
||||
|
||||
fun test(s: String) {
|
||||
<caret>if (s.isNotEmpty()) {
|
||||
foo(2)
|
||||
} else {
|
||||
foo(1)
|
||||
}
|
||||
}
|
||||
@@ -9494,6 +9494,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
runTest("idea/testData/intentions/invertIfCondition/is.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("isEmpty.kt")
|
||||
public void testIsEmpty() throws Exception {
|
||||
runTest("idea/testData/intentions/invertIfCondition/isEmpty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("isNotEmpty.kt")
|
||||
public void testIsNotEmpty() throws Exception {
|
||||
runTest("idea/testData/intentions/invertIfCondition/isNotEmpty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaNonLocalAndLocalReturn.kt")
|
||||
public void testLambdaNonLocalAndLocalReturn() throws Exception {
|
||||
runTest("idea/testData/intentions/invertIfCondition/lambdaNonLocalAndLocalReturn.kt");
|
||||
@@ -9559,6 +9569,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
runTest("idea/testData/intentions/invertIfCondition/negatedExpression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("negatedIsEmpty.kt")
|
||||
public void testNegatedIsEmpty() throws Exception {
|
||||
runTest("idea/testData/intentions/invertIfCondition/negatedIsEmpty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("negatedIsNotEmpty.kt")
|
||||
public void testNegatedIsNotEmpty() throws Exception {
|
||||
runTest("idea/testData/intentions/invertIfCondition/negatedIsNotEmpty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedIfWithReturn.kt")
|
||||
public void testNestedIfWithReturn() throws Exception {
|
||||
runTest("idea/testData/intentions/invertIfCondition/nestedIfWithReturn.kt");
|
||||
|
||||
Reference in New Issue
Block a user