Inspection to replace !string.isBlank() with string.isNotBlank()

#KT-40769 Fixed
This commit is contained in:
Enterman
2020-08-07 15:51:14 +08:00
committed by Vladimir Dolzhenko
parent f9a2d01d57
commit d09b20f11d
19 changed files with 156 additions and 8 deletions
@@ -1,5 +1,5 @@
<html>
<body>
This inspection reports <b>!collection.isEmpty()/isNotEmpty()</b> call can be replaced with <b>collection.isNotEmpty()/isEmpty()</b>.
This inspection reports <b>!collection.isEmpty()/isNotEmpty()</b> or <b>!str.isBlank()/isNotBlank()</b> call can be replaced with <b>collection.isNotEmpty()/isEmpty()</b> or <b>str.isNotBlank()/isBlank()</b>.
</body>
</html>
@@ -2017,7 +2017,7 @@ inspection.kotlin.throwable.not.thrown.display.name=Throwable not thrown
inspection.redundant.require.not.null.call.display.name=Redundant 'requireNotNull' or 'checkNotNull' call
inspection.replace.range.start.end.inclusive.with.first.last.display.name=Replace Range 'start' or 'endInclusive' with 'first' or 'last'
inspection.redundant.enum.constructor.invocation.display.name=Redundant enum constructor invocation
inspection.replace.negated.is.empty.with.is.not.empty.display.name=Replace negated 'isEmpty' with 'isNotEmpty'
inspection.replace.negated.is.empty.with.is.not.empty.display.name=Replace negated 'isEmpty'/'isBlank' with 'isNotEmpty'/'isNotBlank'
inspection.function.with.lambda.expression.body.display.name=Function with `= { ... }` and inferred return type
inspection.suspend.function.on.coroutine.scope.display.name=Ambiguous coroutineContext due to CoroutineScope receiver of suspend function
inspection.boolean.literal.argument.display.name=Boolean literal argument without parameter name
@@ -45,10 +45,14 @@ class ReplaceNegatedIsEmptyWithIsNotEmptyInspection : AbstractKotlinInspection()
val calleeText = calleeExpression.text
val isEmptyCall = calleeText == "isEmpty"
val isNotEmptyCall = calleeText == "isNotEmpty"
if (!isEmptyCall && !isNotEmptyCall) return null
val isBlankCall = calleeText == "isBlank"
val isNotBlankCall = calleeText == "isNotBlank"
if (!isEmptyCall && !isNotEmptyCall && !isBlankCall && !isNotBlankCall) 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"
|| isNotEmptyCall && isNotEmptyFunctions.none { callExpression.isCalling(FqName(it)) }
|| isBlankCall && !callExpression.isCalling(FqName("kotlin.text.isBlank"))
|| isNotBlankCall && !callExpression.isCalling(FqName("kotlin.text.isNotBlank"))) return null
val to = if (isEmptyCall) "isNotEmpty" else if (isNotEmptyCall) "isEmpty" else if (isBlankCall) "isNotBlank" else "isBlank"
return KtPsiFactory(this).createExpressionByPattern(
"$0.$to()",
this.receiverExpression,
@@ -0,0 +1,5 @@
// PROBLEM: none
// WITH_RUNTIME
fun test(s: String) {
val b = s.isBlank<caret>()
}
@@ -0,0 +1,6 @@
// PROBLEM: Replace negated 'isBlank' with 'isNotBlank'
// FIX: Replace negated 'isBlank' with 'isNotBlank'
// WITH_RUNTIME
fun test(s: String) {
val b = !s.isBlank<caret>()
}
@@ -0,0 +1,6 @@
// PROBLEM: Replace negated 'isBlank' with 'isNotBlank'
// FIX: Replace negated 'isBlank' with 'isNotBlank'
// WITH_RUNTIME
fun test(s: String) {
val b = s.isNotBlank()
}
@@ -0,0 +1,6 @@
// PROBLEM: Replace negated 'isNotBlank' with 'isBlank'
// FIX: Replace negated 'isNotBlank' with 'isBlank'
// WITH_RUNTIME
fun test(s: String) {
val b = !s.isNotBlank<caret>()
}
@@ -0,0 +1,6 @@
// PROBLEM: Replace negated 'isNotBlank' with 'isBlank'
// FIX: Replace negated 'isNotBlank' with 'isBlank'
// WITH_RUNTIME
fun test(s: String) {
val b = s.isBlank()
}
+10
View File
@@ -0,0 +1,10 @@
// WITH_RUNTIME
fun foo(i: Int) {}
fun test(s: String) {
<caret>if (s.isBlank()) {
foo(1)
} else {
foo(2)
}
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
fun foo(i: Int) {}
fun test(s: String) {
<caret>if (s.isNotBlank()) {
foo(2)
} else {
foo(1)
}
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
fun foo(i: Int) {}
fun test(s: String) {
<caret>if (s.isNotBlank()) {
foo(1)
} else {
foo(2)
}
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
fun foo(i: Int) {}
fun test(s: String) {
<caret>if (s.isBlank()) {
foo(2)
} else {
foo(1)
}
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
fun foo(i: Int) {}
fun test(s: String) {
<caret>if (!s.isBlank()) {
foo(1)
} else {
foo(2)
}
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
fun foo(i: Int) {}
fun test(s: String) {
<caret>if (s.isBlank()) {
foo(2)
} else {
foo(1)
}
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
fun foo(i: Int) {}
fun test(s: String) {
<caret>if (!s.isNotBlank()) {
foo(1)
} else {
foo(2)
}
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
fun foo(i: Int) {}
fun test(s: String) {
<caret>if (s.isNotBlank()) {
foo(2)
} else {
foo(1)
}
}
@@ -11223,9 +11223,14 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/inspectionsLocal/replaceNegatedIsEmptyWithIsNotEmpty"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), null, true);
}
@TestMetadata("notNegate.kt")
public void testNotNegate() throws Exception {
runTest("idea/testData/inspectionsLocal/replaceNegatedIsEmptyWithIsNotEmpty/notNegate.kt");
@TestMetadata("notNegateBlank.kt")
public void testNotNegateBlank() throws Exception {
runTest("idea/testData/inspectionsLocal/replaceNegatedIsEmptyWithIsNotEmpty/notNegateBlank.kt");
}
@TestMetadata("notNegateEmpty.kt")
public void testNotNegateEmpty() throws Exception {
runTest("idea/testData/inspectionsLocal/replaceNegatedIsEmptyWithIsNotEmpty/notNegateEmpty.kt");
}
@TestMetadata("simple.kt")
@@ -11233,11 +11238,21 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
runTest("idea/testData/inspectionsLocal/replaceNegatedIsEmptyWithIsNotEmpty/simple.kt");
}
@TestMetadata("stringIsBlank.kt")
public void testStringIsBlank() throws Exception {
runTest("idea/testData/inspectionsLocal/replaceNegatedIsEmptyWithIsNotEmpty/stringIsBlank.kt");
}
@TestMetadata("stringIsEmpty.kt")
public void testStringIsEmpty() throws Exception {
runTest("idea/testData/inspectionsLocal/replaceNegatedIsEmptyWithIsNotEmpty/stringIsEmpty.kt");
}
@TestMetadata("stringIsNotBlank.kt")
public void testStringIsNotBlank() throws Exception {
runTest("idea/testData/inspectionsLocal/replaceNegatedIsEmptyWithIsNotEmpty/stringIsNotBlank.kt");
}
@TestMetadata("stringIsNotEmpty.kt")
public void testStringIsNotEmpty() throws Exception {
runTest("idea/testData/inspectionsLocal/replaceNegatedIsEmptyWithIsNotEmpty/stringIsNotEmpty.kt");
@@ -9940,11 +9940,21 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
runTest("idea/testData/intentions/invertIfCondition/is.kt");
}
@TestMetadata("isBlank.kt")
public void testIsBlank() throws Exception {
runTest("idea/testData/intentions/invertIfCondition/isBlank.kt");
}
@TestMetadata("isEmpty.kt")
public void testIsEmpty() throws Exception {
runTest("idea/testData/intentions/invertIfCondition/isEmpty.kt");
}
@TestMetadata("isNotBlank.kt")
public void testIsNotBlank() throws Exception {
runTest("idea/testData/intentions/invertIfCondition/isNotBlank.kt");
}
@TestMetadata("isNotEmpty.kt")
public void testIsNotEmpty() throws Exception {
runTest("idea/testData/intentions/invertIfCondition/isNotEmpty.kt");
@@ -10015,11 +10025,21 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
runTest("idea/testData/intentions/invertIfCondition/negatedExpression.kt");
}
@TestMetadata("negatedIsBlank.kt")
public void testNegatedIsBlank() throws Exception {
runTest("idea/testData/intentions/invertIfCondition/negatedIsBlank.kt");
}
@TestMetadata("negatedIsEmpty.kt")
public void testNegatedIsEmpty() throws Exception {
runTest("idea/testData/intentions/invertIfCondition/negatedIsEmpty.kt");
}
@TestMetadata("negatedIsNotBlank.kt")
public void testNegatedIsNotBlank() throws Exception {
runTest("idea/testData/intentions/invertIfCondition/negatedIsNotBlank.kt");
}
@TestMetadata("negatedIsNotEmpty.kt")
public void testNegatedIsNotEmpty() throws Exception {
runTest("idea/testData/intentions/invertIfCondition/negatedIsNotEmpty.kt");