From f3a3c0886f4629c3500692fb872d075e8aec4c1e Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Wed, 23 Mar 2016 12:11:56 +0300 Subject: [PATCH] J2K: Remove unnecessary casts of non-nullable expression to nullable type after conversion #KT-11543 Fixed --- .../kotlin/idea/j2k/J2kPostProcessings.kt | 22 +++++++++++++ .../nullability/notNullCast.java | 32 +++++++++++++++++++ .../fileOrElement/nullability/notNullCast.kt | 31 ++++++++++++++++++ ...otlinConverterForWebDemoTestGenerated.java | 6 ++++ ...otlinConverterSingleFileTestGenerated.java | 6 ++++ 5 files changed, 97 insertions(+) create mode 100644 j2k/testData/fileOrElement/nullability/notNullCast.java create mode 100644 j2k/testData/fileOrElement/nullability/notNullCast.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt index c9f155c3916..d0e026876a2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt +++ b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt @@ -21,6 +21,7 @@ import com.intellij.psi.search.searches.ReferencesSearch import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.idea.caches.resolve.analyzeAndGetResult import org.jetbrains.kotlin.idea.core.setVisibility import org.jetbrains.kotlin.idea.inspections.RedundantSamConstructorInspection import org.jetbrains.kotlin.idea.intentions.* @@ -34,6 +35,7 @@ import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import java.util.* @@ -54,6 +56,7 @@ object J2KPostProcessingRegistrar { _processings.add(ConvertToStringTemplateProcessing()) _processings.add(UsePropertyAccessSyntaxProcessing()) _processings.add(RemoveRedundantSamAdaptersProcessing()) + _processings.add(RemoveRedundantCastToNullableProcessing()) registerIntentionBasedProcessing(ConvertToExpressionBodyIntention()) { it is KtPropertyAccessor } registerIntentionBasedProcessing(IfThenToSafeAccessIntention()) @@ -219,4 +222,23 @@ object J2KPostProcessingRegistrar { } } } + + private class RemoveRedundantCastToNullableProcessing : J2kPostProcessing { + override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { + if (element !is KtBinaryExpressionWithTypeRHS) return null + + val context = element.analyzeAndGetResult().bindingContext + val leftType = context.getType(element.left) ?: return null + val rightType = context.get(BindingContext.TYPE, element.right) ?: return null + + if (!leftType.isMarkedNullable && rightType.isMarkedNullable) { + return { + val type = element.right?.typeElement as? KtNullableType + type?.replace(type.innerType!!) + } + } + + return null + } + } } \ No newline at end of file diff --git a/j2k/testData/fileOrElement/nullability/notNullCast.java b/j2k/testData/fileOrElement/nullability/notNullCast.java new file mode 100644 index 00000000000..29d26b54c39 --- /dev/null +++ b/j2k/testData/fileOrElement/nullability/notNullCast.java @@ -0,0 +1,32 @@ +public class Passenger { + public static class PassParent { + } + + public static class PassChild extends PassParent { + } + + public PassParent provideNullable(int p) { + return p > 0 ? new PassChild() : null; + } + + public void test1() { + PassParent pass = provideNullable(1); + assert pass != null; + accept1((PassChild) pass); + } + + public void test2() { + PassParent pass = provideNullable(1); + if (1 == 2) { + assert pass != null; + accept2((PassChild) pass); + } + accept2((PassChild) pass); + } + + public void accept1(PassChild p) { + } + + public void accept2(PassChild p) { + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/nullability/notNullCast.kt b/j2k/testData/fileOrElement/nullability/notNullCast.kt new file mode 100644 index 00000000000..b81a0db3eee --- /dev/null +++ b/j2k/testData/fileOrElement/nullability/notNullCast.kt @@ -0,0 +1,31 @@ +// ERROR: Type mismatch: inferred type is Passenger.PassChild? but Passenger.PassChild was expected +// ERROR: Type mismatch: inferred type is Passenger.PassChild? but Passenger.PassChild was expected +class Passenger { + open class PassParent + + class PassChild : PassParent() + + fun provideNullable(p: Int): PassParent? { + return if (p > 0) PassChild() else null + } + + fun test1() { + val pass = provideNullable(1)!! + accept1(pass as PassChild) + } + + fun test2() { + val pass = provideNullable(1) + if (1 == 2) { + assert(pass != null) + accept2(pass as PassChild?) + } + accept2(pass as PassChild?) + } + + fun accept1(p: PassChild) { + } + + fun accept2(p: PassChild) { + } +} \ No newline at end of file diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java index 5e6da586d87..5adc9aec53c 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java @@ -3505,6 +3505,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("notNullCast.java") + public void testNotNullCast() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/nullability/notNullCast.java"); + doTest(fileName); + } + @TestMetadata("nullableField.java") public void testNullableField() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/nullability/nullableField.java"); diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java index d85ae2f6f09..dafcc87fe01 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java @@ -3505,6 +3505,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("notNullCast.java") + public void testNotNullCast() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/nullability/notNullCast.java"); + doTest(fileName); + } + @TestMetadata("nullableField.java") public void testNullableField() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/nullability/nullableField.java");