If then to elvis: now not applicable for calls with nullable result #KT-14542 Fixed

This commit is contained in:
Mikhail Glukhikh
2016-10-27 14:21:57 +03:00
parent f390b9159a
commit 89e908dab5
3 changed files with 21 additions and 1 deletions

View File

@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.idea.intentions.SelfTargetingOffsetIndependentIntention
@@ -26,6 +27,10 @@ import org.jetbrains.kotlin.idea.intentions.getLeftMostReceiverExpression
import org.jetbrains.kotlin.idea.intentions.replaceFirstReceiver
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode.Companion.PARTIAL
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
import org.jetbrains.kotlin.types.typeUtil.nullability
class IfThenToElvisInspection : IntentionBasedInspection<KtIfExpression>(IfThenToElvisIntention::class)
@@ -36,7 +41,7 @@ class IfThenToElvisIntention : SelfTargetingOffsetIndependentIntention<KtIfExpre
private fun KtExpression.clausesReplaceableByElvis(firstClause: KtExpression, secondClause: KtExpression) =
!firstClause.isNullOrBlockExpression() &&
(secondClause.evaluatesTo(this) || secondClause.hasFirstReceiverOf(this)) &&
(secondClause.evaluatesTo(this) || secondClause.hasFirstReceiverOf(this) && !secondClause.isNullableExpression()) &&
!(firstClause is KtThrowExpression && firstClause.throwsNullPointerExceptionWithNoArguments())
private fun KtExpression.checkedExpression() = when (this) {
@@ -72,6 +77,8 @@ class IfThenToElvisIntention : SelfTargetingOffsetIndependentIntention<KtIfExpre
return innerExpression is KtBlockExpression || innerExpression.node.elementType == KtNodeTypes.NULL
}
private fun KtExpression.isNullableExpression() = getType(analyze(PARTIAL))?.nullability() != TypeNullability.NOT_NULL
private fun KtExpression.hasFirstReceiverOf(receiver: KtExpression): Boolean {
val actualReceiver = (unwrapBlockOrParenthesis() as? KtDotQualifiedExpression)?.getLeftMostReceiverExpression() ?: return false
return actualReceiver.evaluatesTo(receiver)

View File

@@ -0,0 +1,7 @@
// IS_APPLICABLE: false
fun foo(p: String?): String? {
return <caret>if (p != null) p.bar() else "a"
}
fun String.bar(): String? = null

View File

@@ -1404,6 +1404,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
doTest(fileName);
}
@TestMetadata("nullableThen.kt")
public void testNullableThen() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/ifThenToElvis/nullableThen.kt");
doTest(fileName);
}
@TestMetadata("otherBlockHasMoreThanOneStatement.kt")
public void testOtherBlockHasMoreThanOneStatement() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/branched/ifThenToElvis/otherBlockHasMoreThanOneStatement.kt");