diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/FoldInitializerAndIfToElvisIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/FoldInitializerAndIfToElvisIntention.kt index 53ce7b632b9..b3c5fa1a9bf 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/FoldInitializerAndIfToElvisIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/FoldInitializerAndIfToElvisIntention.kt @@ -35,9 +35,11 @@ import org.jetbrains.kotlin.psi.psiUtil.PsiChildRange 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.BindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.typeUtil.isNothing +import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull @@ -143,6 +145,16 @@ class FoldInitializerAndIfToElvisIntention : val then = ifExpression.then ?: return null val typeReference = (operationExpression as? KtIsExpression)?.typeReference + if (typeReference != null) { + val checkedType = ifExpression.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, typeReference] + val variableTypeReference = prevStatement.typeReference + val variableType = if (variableTypeReference != null) + prevStatement.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, variableTypeReference] + else + SpecifyTypeExplicitlyIntention.getTypeForDeclaration(prevStatement) + if (checkedType != null && variableType != null && !checkedType.isSubtypeOf(variableType)) return null + } + val statement = if (then is KtBlockExpression) then.statements.singleOrNull() else then statement ?: return null diff --git a/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSameType.kt b/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSameType.kt new file mode 100644 index 00000000000..d2f183fd717 --- /dev/null +++ b/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSameType.kt @@ -0,0 +1,13 @@ +open class A + +open class B : A() { + fun b() {} +} + +fun test() { + val b = B() + if (b !is B) { + return + } + b.b() +} \ No newline at end of file diff --git a/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSameType.kt.after b/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSameType.kt.after new file mode 100644 index 00000000000..18019b888a5 --- /dev/null +++ b/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSameType.kt.after @@ -0,0 +1,10 @@ +open class A + +open class B : A() { + fun b() {} +} + +fun test() { + val b = B() as? B ?: return + b.b() +} \ No newline at end of file diff --git a/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSubType.kt b/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSubType.kt new file mode 100644 index 00000000000..004b41f9464 --- /dev/null +++ b/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSubType.kt @@ -0,0 +1,17 @@ +open class A + +open class B : A() { + fun b() {} +} + +open class C : B() { + fun c() {} +} + +fun test() { + val b = B() + if (b !is C) { + return + } + b.b() +} \ No newline at end of file diff --git a/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSubType.kt.after b/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSubType.kt.after new file mode 100644 index 00000000000..219802f019d --- /dev/null +++ b/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSubType.kt.after @@ -0,0 +1,14 @@ +open class A + +open class B : A() { + fun b() {} +} + +open class C : B() { + fun c() {} +} + +fun test() { + val b = B() as? C ?: return + b.b() +} \ No newline at end of file diff --git a/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSuperType.kt b/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSuperType.kt new file mode 100644 index 00000000000..ebaeb60c1ff --- /dev/null +++ b/idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSuperType.kt @@ -0,0 +1,14 @@ +// IS_APPLICABLE: false +open class A + +open class B : A() { + fun b() {} +} + +fun test() { + val b = B() + if (b !is A) { + return + } + b.b() +} \ 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 5af9feff561..8de178a7a86 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -8749,6 +8749,21 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/foldInitializerAndIfToElvis/NotIsNullableType.kt"); } + @TestMetadata("NotIsSameType.kt") + public void testNotIsSameType() throws Exception { + runTest("idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSameType.kt"); + } + + @TestMetadata("NotIsSubType.kt") + public void testNotIsSubType() throws Exception { + runTest("idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSubType.kt"); + } + + @TestMetadata("NotIsSuperType.kt") + public void testNotIsSuperType() throws Exception { + runTest("idea/testData/intentions/foldInitializerAndIfToElvis/NotIsSuperType.kt"); + } + @TestMetadata("OtherVar1.kt") public void testOtherVar1() throws Exception { runTest("idea/testData/intentions/foldInitializerAndIfToElvis/OtherVar1.kt");