Introduce "Simplify when" intention where one branch is always true
So #KT-20492 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
26ba2ab3db
commit
df86ff7115
+1
@@ -0,0 +1 @@
|
|||||||
|
val foo = "foo"
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
val foo = when {
|
||||||
|
true -> "foo"
|
||||||
|
false -> "bar"
|
||||||
|
else -> "baz"
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
This intention simplifies a when expression that has branch conditions which are true or false
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1645,12 +1645,17 @@
|
|||||||
<category>Kotlin</category>
|
<category>Kotlin</category>
|
||||||
</intentionAction>
|
</intentionAction>
|
||||||
|
|
||||||
<intentionAction>
|
<intentionAction>
|
||||||
<className>org.jetbrains.kotlin.idea.intentions.MoveMemberToTopLevelIntention</className>
|
<className>org.jetbrains.kotlin.idea.intentions.MoveMemberToTopLevelIntention</className>
|
||||||
<category>Kotlin</category>
|
<category>Kotlin</category>
|
||||||
</intentionAction>
|
</intentionAction>
|
||||||
|
|
||||||
<localInspection implementationClass="org.jetbrains.kotlin.idea.intentions.ObjectLiteralToLambdaInspection"
|
<intentionAction>
|
||||||
|
<className>org.jetbrains.kotlin.idea.inspections.SimplifyWhenWithBooleanConstantConditionIntention</className>
|
||||||
|
<category>Kotlin</category>
|
||||||
|
</intentionAction>
|
||||||
|
|
||||||
|
<localInspection implementationClass="org.jetbrains.kotlin.idea.intentions.ObjectLiteralToLambdaInspection"
|
||||||
displayName="Object literal can be converted to lambda"
|
displayName="Object literal can be converted to lambda"
|
||||||
groupPath="Kotlin"
|
groupPath="Kotlin"
|
||||||
groupName="Style issues"
|
groupName="Style issues"
|
||||||
@@ -2626,7 +2631,7 @@
|
|||||||
level="WARNING"
|
level="WARNING"
|
||||||
language="kotlin"
|
language="kotlin"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.ExplicitThisInspection"
|
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.ExplicitThisInspection"
|
||||||
displayName="Redundant explicit 'this'"
|
displayName="Redundant explicit 'this'"
|
||||||
groupPath="Kotlin"
|
groupPath="Kotlin"
|
||||||
|
|||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.intentions
|
||||||
|
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.inspections.replaceWithBranch
|
||||||
|
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.isFalseConstant
|
||||||
|
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.isTrueConstant
|
||||||
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
|
import org.jetbrains.kotlin.psi.KtWhenConditionWithExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtWhenEntry
|
||||||
|
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||||
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||||
|
|
||||||
|
class SimplifyWhenWithBooleanConstantConditionIntention : SelfTargetingRangeIntention<KtWhenExpression>(KtWhenExpression::class.java, "Simplify when expression") {
|
||||||
|
|
||||||
|
override fun applicabilityRange(element: KtWhenExpression): TextRange? {
|
||||||
|
if (element.closeBrace == null) return null
|
||||||
|
if (element.subjectExpression != null) return null
|
||||||
|
if (element.entries.none { it.isTrueConstantCondition() || it.isFalseConstantCondition() }) return null
|
||||||
|
return element.whenKeyword.textRange
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyTo(element: KtWhenExpression, editor: Editor?) {
|
||||||
|
val closeBrace = element.closeBrace ?: return
|
||||||
|
val project = editor?.project ?: return
|
||||||
|
val factory = KtPsiFactory(project)
|
||||||
|
val usedAsExpression = element.isUsedAsExpression(element.analyze())
|
||||||
|
element.deleteFalseEntry(usedAsExpression)
|
||||||
|
element.replaceTrueEntry(usedAsExpression, closeBrace, factory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtWhenExpression.deleteFalseEntry(usedAsExpression: Boolean) {
|
||||||
|
for (entry in entries) {
|
||||||
|
if (entry.isFalseConstantCondition()) {
|
||||||
|
entry.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries.isEmpty() && !usedAsExpression) {
|
||||||
|
delete()
|
||||||
|
}
|
||||||
|
else if (entries.singleOrNull()?.isElse == true) {
|
||||||
|
elseExpression?.let { replaceWithBranch(it, usedAsExpression) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtWhenExpression.replaceTrueEntry(usedAsExpression: Boolean, closeBrace: PsiElement, factory: KtPsiFactory) {
|
||||||
|
val trueIndex = entries.indexOfFirst { it.isTrueConstantCondition() }
|
||||||
|
if (trueIndex == -1) return
|
||||||
|
|
||||||
|
val expression = entries[trueIndex].expression ?: return
|
||||||
|
|
||||||
|
if (trueIndex == 0) {
|
||||||
|
replaceWithBranch(expression, usedAsExpression)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val elseEntry = factory.createWhenEntry("else -> ${expression.text}")
|
||||||
|
for (index in trueIndex until entries.size) {
|
||||||
|
entries[index].delete()
|
||||||
|
}
|
||||||
|
addBefore(elseEntry, closeBrace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtWhenEntry.isTrueConstantCondition(): Boolean =
|
||||||
|
(conditions.singleOrNull() as? KtWhenConditionWithExpression)?.expression.isTrueConstant()
|
||||||
|
|
||||||
|
private fun KtWhenEntry.isFalseConstantCondition(): Boolean =
|
||||||
|
(conditions.singleOrNull() as? KtWhenConditionWithExpression)?.expression.isFalseConstant()
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
org.jetbrains.kotlin.idea.intentions.SimplifyWhenWithBooleanConstantConditionIntention
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
fun test() {
|
||||||
|
val x = <caret>when {
|
||||||
|
false -> 1
|
||||||
|
else -> 2
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun test() {
|
||||||
|
val x = 2
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
val x = <caret>when {
|
||||||
|
false -> {
|
||||||
|
println(1)
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
println(2)
|
||||||
|
2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
val x = run {
|
||||||
|
println(2)
|
||||||
|
2
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
<caret>when {
|
||||||
|
false -> {
|
||||||
|
println(1)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
println(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
println(2)
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// ERROR: 'when' expression must be exhaustive, add necessary 'else' branch
|
||||||
|
fun test() {
|
||||||
|
val x = <caret>when {
|
||||||
|
false -> 1
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// ERROR: 'when' expression must be exhaustive, add necessary 'else' branch
|
||||||
|
fun test() {
|
||||||
|
val x = when {
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// ERROR: 'when' expression must be exhaustive, add necessary 'else' branch
|
||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
val x = <caret>when {
|
||||||
|
false -> {
|
||||||
|
println(1)
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// ERROR: 'when' expression must be exhaustive, add necessary 'else' branch
|
||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
val x = when {
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
<caret>when {
|
||||||
|
false -> {
|
||||||
|
println(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
// WITH_RUNTIME
|
||||||
|
fun test(b: Boolean) {
|
||||||
|
<caret>when(b) {
|
||||||
|
true -> println(1)
|
||||||
|
false -> println(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
// WITH_RUNTIME
|
||||||
|
fun test(i: Int) {
|
||||||
|
<caret>when {
|
||||||
|
i == 1 -> println(1)
|
||||||
|
else -> println(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
fun test(i: Int) {
|
||||||
|
val x = <caret>when {
|
||||||
|
i == 1 -> 1
|
||||||
|
false -> 2
|
||||||
|
true -> 3
|
||||||
|
else -> 4
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
fun test(i: Int) {
|
||||||
|
val x = when {
|
||||||
|
i == 1 -> 1
|
||||||
|
else -> 3
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test(i: Int) {
|
||||||
|
val x = <caret>when {
|
||||||
|
i == 1 -> {
|
||||||
|
println(1)
|
||||||
|
1
|
||||||
|
}
|
||||||
|
false -> {
|
||||||
|
println(2)
|
||||||
|
2
|
||||||
|
}
|
||||||
|
true -> {
|
||||||
|
println(3)
|
||||||
|
3
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
println(4)
|
||||||
|
4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test(i: Int) {
|
||||||
|
val x = when {
|
||||||
|
i == 1 -> {
|
||||||
|
println(1)
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
println(3)
|
||||||
|
3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test(i: Int) {
|
||||||
|
<caret>when {
|
||||||
|
i == 1 -> {
|
||||||
|
println(1)
|
||||||
|
}
|
||||||
|
false -> {
|
||||||
|
println(2)
|
||||||
|
}
|
||||||
|
true -> {
|
||||||
|
println(3)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
println(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test(i: Int) {
|
||||||
|
when {
|
||||||
|
i == 1 -> {
|
||||||
|
println(1)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
println(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
fun test() {
|
||||||
|
val x = <caret>when {
|
||||||
|
true -> 1
|
||||||
|
else -> 2
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun test() {
|
||||||
|
val x = 1
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
val x = <caret>when {
|
||||||
|
true -> {
|
||||||
|
println(1)
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
println(2)
|
||||||
|
2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
val x = run {
|
||||||
|
println(1)
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
when<caret> {
|
||||||
|
true -> {
|
||||||
|
println(1)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
println(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun test() {
|
||||||
|
println(1)
|
||||||
|
}
|
||||||
@@ -15216,6 +15216,99 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class SimplifyWhenWithBooleanConstantCondition extends AbstractIntentionTest {
|
||||||
|
public void testAllFilesPresentInSimplifyWhenWithBooleanConstantCondition() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("falseAndElse1.kt")
|
||||||
|
public void testFalseAndElse1() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/falseAndElse1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("falseAndElse2.kt")
|
||||||
|
public void testFalseAndElse2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/falseAndElse2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("falseAndElse3.kt")
|
||||||
|
public void testFalseAndElse3() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/falseAndElse3.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("falseOnly1.kt")
|
||||||
|
public void testFalseOnly1() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/falseOnly1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("falseOnly2.kt")
|
||||||
|
public void testFalseOnly2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/falseOnly2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("falseOnly3.kt")
|
||||||
|
public void testFalseOnly3() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/falseOnly3.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("hasSubject.kt")
|
||||||
|
public void testHasSubject() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/hasSubject.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("noBooolean.kt")
|
||||||
|
public void testNoBooolean() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/noBooolean.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("trueIsNotTop1.kt")
|
||||||
|
public void testTrueIsNotTop1() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/trueIsNotTop1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("trueIsNotTop2.kt")
|
||||||
|
public void testTrueIsNotTop2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/trueIsNotTop2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("trueIsNotTop3.kt")
|
||||||
|
public void testTrueIsNotTop3() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/trueIsNotTop3.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("trueIsTop1.kt")
|
||||||
|
public void testTrueIsTop1() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/trueIsTop1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("trueIsTop2.kt")
|
||||||
|
public void testTrueIsTop2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/trueIsTop2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("trueIsTop3.kt")
|
||||||
|
public void testTrueIsTop3() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyWhenWithBooleanConstantCondition/trueIsTop3.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/intentions/specifyExplicitLambdaSignature")
|
@TestMetadata("idea/testData/intentions/specifyExplicitLambdaSignature")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user