diff --git a/ChangeLog.md b/ChangeLog.md index 3adfae1c50b..297fefbcf08 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -11,6 +11,9 @@ - [`KT-12903`](https://youtrack.jetbrains.com/issue/KT-12903) Implement "Inline type alias" refactoring - [`KT-12902`](https://youtrack.jetbrains.com/issue/KT-12902) Implement "Introduce type alias" refactoring +###### Issues fixed +- [`KT-13383`](https://youtrack.jetbrains.com/issue/KT-13383), [`KT-13379`](https://youtrack.jetbrains.com/issue/KT-13379) Override/Implement Members: Do not make return type non-nullable if base return type is explicitly nullable + ## 1.1-M01 (EAP-1) ### Language features diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMemberChooserObject.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMemberChooserObject.kt index 0fc99583f34..0bb3261288c 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMemberChooserObject.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/overrideImplement/OverrideMemberChooserObject.kt @@ -35,6 +35,8 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.findDocComment.findDocComment import org.jetbrains.kotlin.renderer.* import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.isFlexible import org.jetbrains.kotlin.types.typeUtil.makeNotNullable interface OverrideMemberChooserObject : ClassMember { @@ -158,7 +160,10 @@ private fun generateConstructorParameter(project: Project, descriptor: PropertyD private fun generateFunction(project: Project, descriptor: FunctionDescriptor, bodyType: OverrideMemberChooserObject.BodyType): KtNamedFunction { val newDescriptor = object : FunctionDescriptor by descriptor { override fun getModality() = Modality.OPEN - override fun getReturnType() = descriptor.returnType?.makeNotNullable() + override fun getReturnType(): KotlinType? { + val originalType = descriptor.returnType ?: return null + return if (originalType.isFlexible()) originalType.makeNotNullable() else originalType + } override fun getOverriddenDescriptors() = listOf(descriptor) override fun accept(visitor: DeclarationDescriptorVisitor, data: D) = visitor.visitFunctionDescriptor(this, data) } diff --git a/idea/testData/codeInsight/overrideImplement/nullableJavaType/foo/A.java b/idea/testData/codeInsight/overrideImplement/nullableJavaType/foo/A.java new file mode 100644 index 00000000000..b4a6d6504b8 --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/nullableJavaType/foo/A.java @@ -0,0 +1,9 @@ +package foo; + +import org.jetbrains.annotations.Nullable; + +public class A { + public @Nullable String foo(String s) { + return null; + } +} diff --git a/idea/testData/codeInsight/overrideImplement/nullableJavaType/foo/Impl.kt b/idea/testData/codeInsight/overrideImplement/nullableJavaType/foo/Impl.kt new file mode 100644 index 00000000000..4cfd67ae82c --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/nullableJavaType/foo/Impl.kt @@ -0,0 +1,5 @@ +import foo.A + +class B : A() { + +} diff --git a/idea/testData/codeInsight/overrideImplement/nullableJavaType/foo/Impl.kt.after b/idea/testData/codeInsight/overrideImplement/nullableJavaType/foo/Impl.kt.after new file mode 100644 index 00000000000..e0e18c01c41 --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/nullableJavaType/foo/Impl.kt.after @@ -0,0 +1,7 @@ +import foo.A + +class B : A() { + override fun foo(s: String?): String? { + return super.foo(s) + } +} diff --git a/idea/testData/codeInsight/overrideImplement/nullableKotlinType/foo/Impl.kt b/idea/testData/codeInsight/overrideImplement/nullableKotlinType/foo/Impl.kt new file mode 100644 index 00000000000..f1a280bc979 --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/nullableKotlinType/foo/Impl.kt @@ -0,0 +1,7 @@ +interface IBase { + fun foo(): Any? +} + +class C : IBase { + +} \ No newline at end of file diff --git a/idea/testData/codeInsight/overrideImplement/nullableKotlinType/foo/Impl.kt.after b/idea/testData/codeInsight/overrideImplement/nullableKotlinType/foo/Impl.kt.after new file mode 100644 index 00000000000..968af4ef22c --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/nullableKotlinType/foo/Impl.kt.after @@ -0,0 +1,9 @@ +interface IBase { + fun foo(): Any? +} + +class C : IBase { + override fun foo(): Any? { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt index 4178cd2ee58..172357f4bdf 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt @@ -248,6 +248,14 @@ class OverrideImplementTest : AbstractOverrideImplementTest() { doOverrideDirectoryTest("foo") } + fun testNullableJavaType() { + doOverrideDirectoryTest("foo") + } + + fun testNullableKotlinType() { + doOverrideDirectoryTest("foo") + } + fun testAbstractAndNonAbstractInheritedFromInterface() { doImplementFileTest("getFoo") }