From 862966fd332fc591556c0b9f6c9a7dcfaebecabf Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Tue, 10 Jan 2017 20:07:03 +0300 Subject: [PATCH] Override/Implement Members: Support all nullability annotations respected by the Kotlin compiler #KT-12704 Fixed #KT-15583 Fixed --- ChangeLog.md | 1 + .../jetbrains/kotlin/idea/util/TypeUtils.kt | 7 ++--- .../ExtractableCodeDescriptor.kt | 4 ++- .../javaxNonnullJavaType/foo/A.java | 9 +++++++ .../javaxNonnullJavaType/foo/Impl.kt | 5 ++++ .../javaxNonnullJavaType/foo/Impl.kt.after | 7 +++++ .../javax/annotation/Nonnull.java | 26 +++++++++++++++++++ .../idea/codeInsight/OverrideImplementTest.kt | 4 +++ 8 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/foo/A.java create mode 100644 idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/foo/Impl.kt create mode 100644 idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/foo/Impl.kt.after create mode 100644 idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/javax/annotation/Nonnull.java diff --git a/ChangeLog.md b/ChangeLog.md index 7d80a91057b..cd74b030830 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -473,6 +473,7 @@ These artifacts include extensions for the types available in the latter JDKs, s - Pull Up: Fix pull-up from object to superclass - [`KT-15602`](https://youtrack.jetbrains.com/issue/KT-15602) Extract Interface/Superclass: Disable "Make abstract" for inline/external/lateinit members - Extract Interface: Disable inline/external/lateinit members +- [`KT-12704`](https://youtrack.jetbrains.com/issue/KT-12704), [`KT-15583`](https://youtrack.jetbrains.com/issue/KT-15583) Override/Implement Members: Support all nullability annotations respected by the Kotlin compiler #### Intention actions, inspections and quickfixes diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt index 36c51137220..f24fe59ebba 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt @@ -31,10 +31,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.typeUtil.builtIns -import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes -import org.jetbrains.kotlin.types.typeUtil.substitute -import org.jetbrains.kotlin.types.typeUtil.supertypes +import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.kotlin.utils.addToStdlib.singletonList @@ -68,7 +65,7 @@ private fun KotlinType.approximateNonDynamicFlexibleTypes( approximation = approximation.approximateNonDynamicFlexibleTypes() - approximation = if (isAnnotatedNotNull()) approximation.makeNullableAsSpecified(false) else approximation + approximation = if (nullability() == TypeNullability.NOT_NULL) approximation.makeNullableAsSpecified(false) else approximation if (approximation.isMarkedNullable && !flexible.lowerBound.isMarkedNullable && TypeUtils.isTypeParameter(approximation) && TypeUtils.hasNullableSuperType(approximation)) { approximation = approximation.makeNullableAsSpecified(false) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractableCodeDescriptor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractableCodeDescriptor.kt index dc3e33e1a78..599aa6f4bcb 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractableCodeDescriptor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractableCodeDescriptor.kt @@ -47,8 +47,10 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.typeUtil.TypeNullability import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.isUnit +import org.jetbrains.kotlin.types.typeUtil.nullability import java.util.* interface Parameter { @@ -331,7 +333,7 @@ val ControlFlow.possibleReturnTypes: List return when { !returnType.isNullabilityFlexible() -> listOf(returnType) - returnType.isAnnotatedNotNull() || returnType.isAnnotatedNullable() -> + returnType.nullability() != TypeNullability.FLEXIBLE -> listOf(returnType.approximateFlexibleTypes()) else -> (returnType.unwrap() as FlexibleType).let { listOf(it.upperBound, it.lowerBound) } diff --git a/idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/foo/A.java b/idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/foo/A.java new file mode 100644 index 00000000000..7a79e0de991 --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/foo/A.java @@ -0,0 +1,9 @@ +package foo; + +import javax.annotation.Nonnull; + +public class A { + public @Nonnull String foo(@Nonnull String s) { + return null; + } +} diff --git a/idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/foo/Impl.kt b/idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/foo/Impl.kt new file mode 100644 index 00000000000..4cfd67ae82c --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/foo/Impl.kt @@ -0,0 +1,5 @@ +import foo.A + +class B : A() { + +} diff --git a/idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/foo/Impl.kt.after b/idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/foo/Impl.kt.after new file mode 100644 index 00000000000..d96507a4100 --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/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/javaxNonnullJavaType/javax/annotation/Nonnull.java b/idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/javax/annotation/Nonnull.java new file mode 100644 index 00000000000..4b7aad97c70 --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/javaxNonnullJavaType/javax/annotation/Nonnull.java @@ -0,0 +1,26 @@ +package javax.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.annotation.meta.TypeQualifier; +import javax.annotation.meta.TypeQualifierValidator; +import javax.annotation.meta.When; + +@Documented +@TypeQualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface Nonnull { + When when() default When.ALWAYS; + + static class Checker implements TypeQualifierValidator { + + public When forConstantValue(Nonnull qualifierqualifierArgument, + Object value) { + if (value == null) + return When.NEVER; + return When.ALWAYS; + } + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt index ef6e046b6f3..f99c995f5b4 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/OverrideImplementTest.kt @@ -256,6 +256,10 @@ class OverrideImplementTest : AbstractOverrideImplementTest() { doOverrideDirectoryTest("foo") } + fun testJavaxNonnullJavaType() { + doOverrideDirectoryTest("foo") + } + fun testNullableKotlinType() { doOverrideDirectoryTest("foo") }