diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/IfNullToElvisIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/IfNullToElvisIntention.kt index b9ea92d4660..060f3a875f1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/IfNullToElvisIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/IfNullToElvisIntention.kt @@ -30,7 +30,9 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.siblings import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.typeUtil.isNothing +import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import java.util.* @@ -51,10 +53,15 @@ class IfNullToElvisIntention : SelfTargetingRangeIntention(KtIfE val (initializer, declaration, ifNullExpr) = calcData(element)!! val factory = KtPsiFactory(element) - val explicitTypeToAdd = if (declaration.isVar && declaration.typeReference == null) - initializer.analyze().getType(initializer) - else - null + val explicitTypeToSet = when { + // for var with no explicit type, add it so that the actual change won't change + declaration.isVar && declaration.typeReference == null -> initializer.analyze(BodyResolveMode.PARTIAL).getType(initializer) + + // for val with explicit type, change it to non-nullable + !declaration.isVar && declaration.typeReference != null -> initializer.analyze(BodyResolveMode.PARTIAL).getType(initializer)?.makeNotNullable() + + else -> null + } // do not loose any comments! val comments = element.extractComments(ifNullExpr) @@ -68,8 +75,8 @@ class IfNullToElvisIntention : SelfTargetingRangeIntention(KtIfE val newElvis = initializer.replaced(elvis) element.delete() - if (explicitTypeToAdd != null && !explicitTypeToAdd.isError) { - declaration.setType(explicitTypeToAdd) + if (explicitTypeToSet != null && !explicitTypeToSet.isError) { + declaration.setType(explicitTypeToSet) } editor?.caretModel?.moveToOffset(newElvis.right!!.textOffset) diff --git a/idea/testData/intentions/ifNullToElvis/ExplicitValType.kt b/idea/testData/intentions/ifNullToElvis/ExplicitValType.kt new file mode 100644 index 00000000000..cc424166c29 --- /dev/null +++ b/idea/testData/intentions/ifNullToElvis/ExplicitValType.kt @@ -0,0 +1,8 @@ +// WITH_RUNTIME +fun foo(): String? = null + +fun bar() { + val v: String? = foo() + if (v == null) throw Exception() + v.length +} \ No newline at end of file diff --git a/idea/testData/intentions/ifNullToElvis/ExplicitValType.kt.after b/idea/testData/intentions/ifNullToElvis/ExplicitValType.kt.after new file mode 100644 index 00000000000..932a4f07996 --- /dev/null +++ b/idea/testData/intentions/ifNullToElvis/ExplicitValType.kt.after @@ -0,0 +1,7 @@ +// WITH_RUNTIME +fun foo(): String? = null + +fun bar() { + val v: String = foo() ?: throw Exception() + v.length +} \ No newline at end of file diff --git a/idea/testData/intentions/ifNullToElvis/ExplicitVarType.kt b/idea/testData/intentions/ifNullToElvis/ExplicitVarType.kt new file mode 100644 index 00000000000..ac148c868d3 --- /dev/null +++ b/idea/testData/intentions/ifNullToElvis/ExplicitVarType.kt @@ -0,0 +1,9 @@ +// WITH_RUNTIME + +fun foo(): String? = null + +fun bar() { + var v: String? = foo() + if (v == null) throw Exception() + v = null +} \ No newline at end of file diff --git a/idea/testData/intentions/ifNullToElvis/ExplicitVarType.kt.after b/idea/testData/intentions/ifNullToElvis/ExplicitVarType.kt.after new file mode 100644 index 00000000000..55bc6f64aee --- /dev/null +++ b/idea/testData/intentions/ifNullToElvis/ExplicitVarType.kt.after @@ -0,0 +1,8 @@ +// WITH_RUNTIME + +fun foo(): String? = null + +fun bar() { + var v: String? = foo() ?: throw Exception() + v = null +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 3e6f560a177..49922dca436 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -5358,6 +5358,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("ExplicitValType.kt") + public void testExplicitValType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/ifNullToElvis/ExplicitValType.kt"); + doTest(fileName); + } + + @TestMetadata("ExplicitVarType.kt") + public void testExplicitVarType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/ifNullToElvis/ExplicitVarType.kt"); + doTest(fileName); + } + @TestMetadata("IfNotNull.kt") public void testIfNotNull() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/ifNullToElvis/IfNotNull.kt");