KT-11870 "Replace with Elvis" refactoring doesn't change the variable type from T? to T

#KT-11870 Fixed
This commit is contained in:
Valentin Kipyatkov
2016-04-18 19:33:29 +03:00
parent 6bdf3622ed
commit e72e6bf7db
6 changed files with 57 additions and 6 deletions
@@ -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<KtIfExpression>(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<KtIfExpression>(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)
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(): String? = null
fun bar() {
val v: String? = foo()
<caret>if (v == null) throw Exception()
v.length
}
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun foo(): String? = null
fun bar() {
val v: String = foo() ?: throw Exception()
v.length
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
fun foo(): String? = null
fun bar() {
var v: String? = foo()
<caret>if (v == null) throw Exception()
v = null
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(): String? = null
fun bar() {
var v: String? = foo() ?: throw Exception()
v = null
}
@@ -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");