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() {
|
class ReplaceNegatedIsEmptyWithIsNotEmptyInspection : AbstractKotlinInspection() {
|
||||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||||
return qualifiedExpressionVisitor(fun(expression) {
|
return qualifiedExpressionVisitor(fun(expression) {
|
||||||
val callExpression = expression.callExpression ?: return
|
if (expression.getWrappingPrefixExpressionIfAny()?.operationToken != KtTokens.EXCL) return
|
||||||
val calleeExpression = callExpression.calleeExpression ?: return
|
val calleeExpression = expression.callExpression?.calleeExpression ?: return
|
||||||
val calleeText = calleeExpression.text
|
val from = calleeExpression.text
|
||||||
val isEmptyCall = calleeText == "isEmpty"
|
val to = expression.invertSelectorFunction()?.callExpression?.calleeExpression?.text ?: return
|
||||||
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"
|
|
||||||
holder.registerProblem(
|
holder.registerProblem(
|
||||||
calleeExpression,
|
calleeExpression,
|
||||||
"Replace negated '$from' with '$to'",
|
"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 {
|
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.moveCaret
|
||||||
import org.jetbrains.kotlin.idea.core.replaced
|
import org.jetbrains.kotlin.idea.core.replaced
|
||||||
import org.jetbrains.kotlin.idea.core.unblockDocument
|
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.refactoring.getLineNumber
|
||||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches
|
import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches
|
||||||
@@ -39,7 +40,8 @@ class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>(KtIfEx
|
|||||||
element.nextEolCommentOnSameLine()?.delete()
|
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)
|
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");
|
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")
|
@TestMetadata("lambdaNonLocalAndLocalReturn.kt")
|
||||||
public void testLambdaNonLocalAndLocalReturn() throws Exception {
|
public void testLambdaNonLocalAndLocalReturn() throws Exception {
|
||||||
runTest("idea/testData/intentions/invertIfCondition/lambdaNonLocalAndLocalReturn.kt");
|
runTest("idea/testData/intentions/invertIfCondition/lambdaNonLocalAndLocalReturn.kt");
|
||||||
@@ -9559,6 +9569,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
runTest("idea/testData/intentions/invertIfCondition/negatedExpression.kt");
|
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")
|
@TestMetadata("nestedIfWithReturn.kt")
|
||||||
public void testNestedIfWithReturn() throws Exception {
|
public void testNestedIfWithReturn() throws Exception {
|
||||||
runTest("idea/testData/intentions/invertIfCondition/nestedIfWithReturn.kt");
|
runTest("idea/testData/intentions/invertIfCondition/nestedIfWithReturn.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user