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>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.intentions.MoveMemberToTopLevelIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.intentions.MoveMemberToTopLevelIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</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"
|
||||
groupPath="Kotlin"
|
||||
groupName="Style issues"
|
||||
@@ -2626,7 +2631,7 @@
|
||||
level="WARNING"
|
||||
language="kotlin"
|
||||
/>
|
||||
|
||||
|
||||
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.ExplicitThisInspection"
|
||||
displayName="Redundant explicit 'this'"
|
||||
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")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user