From ce37ab81ba14992c5858dbe72169eff4f0fdab19 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Thu, 10 Aug 2017 17:14:37 +0700 Subject: [PATCH] Fix types enhancement for properties' getters overrides in Java Prior to the 1.1.4, nullability related annotations were stored in types that became hard to maintain at some moment and we got rid of it (see 57b7b914444097824cfdcc50ebc425fefcaa12a2) But enhancement for properties overrides stopped working because there were effectively no annotations in the resulting descriptor #KT-19409 Fixed #KT-19409 Fixed --- .../diagnostics/tests/j+k/exceptionMessage.kt | 19 ++++++++++++++ .../tests/j+k/exceptionMessage.txt | 26 +++++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 +++++ .../typeEnhancement/signatureEnhancement.kt | 15 ++++++++--- 4 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/j+k/exceptionMessage.kt create mode 100644 compiler/testData/diagnostics/tests/j+k/exceptionMessage.txt diff --git a/compiler/testData/diagnostics/tests/j+k/exceptionMessage.kt b/compiler/testData/diagnostics/tests/j+k/exceptionMessage.kt new file mode 100644 index 00000000000..93f99cd4e0c --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/exceptionMessage.kt @@ -0,0 +1,19 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// FILE: VcsException.java +import org.jetbrains.annotations.NotNull; + +public class VcsException extends Exception { + @Override + @NotNull + public String getMessage() { + return ""; + } +} + +// FILE: main.kt +fun foo(e: VcsException) { + e.message.contains("") + "" in e.message +} + +public operator fun CharSequence.contains(other: CharSequence): Boolean = true diff --git a/compiler/testData/diagnostics/tests/j+k/exceptionMessage.txt b/compiler/testData/diagnostics/tests/j+k/exceptionMessage.txt new file mode 100644 index 00000000000..b211938f6fe --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/exceptionMessage.txt @@ -0,0 +1,26 @@ +package + +public fun foo(/*0*/ e: VcsException): kotlin.Unit +public operator fun kotlin.CharSequence.contains(/*0*/ other: kotlin.CharSequence): kotlin.Boolean + +public open class VcsException : java.lang.Exception { + public constructor VcsException() + public open override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public open override /*1*/ val message: kotlin.String + public final override /*1*/ /*fake_override*/ fun addSuppressed(/*0*/ exception: kotlin.Throwable!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun fillInStackTrace(): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun getLocalizedMessage(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun getStackTrace(): kotlin.Array<(out) java.lang.StackTraceElement!>! + public final override /*1*/ /*fake_override*/ fun getSuppressed(): kotlin.Array<(out) kotlin.Throwable!>! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun initCause(/*0*/ cause: kotlin.Throwable!): kotlin.Throwable! + public open override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintStream!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun printStackTrace(/*0*/ s: java.io.PrintWriter!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun setStackTrace(/*0*/ stackTrace: kotlin.Array<(out) java.lang.StackTraceElement!>!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + invisible_fake const final override /*1*/ /*fake_override*/ val serialVersionUID: kotlin.Long = -3387516993124229948.toLong() +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 21f4f576c0e..22d40f51c8f 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -12040,6 +12040,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("exceptionMessage.kt") + public void testExceptionMessage() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/exceptionMessage.kt"); + doTest(fileName); + } + @TestMetadata("fieldOverridesField.kt") public void testFieldOverridesField() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/fieldOverridesField.kt"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt index 043cf0dbc2a..a5b47634ed7 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.annotations.composeAnnotations import org.jetbrains.kotlin.load.java.* import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor +import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.lazy.computeNewDefaultTypeQualifiers import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField @@ -91,11 +92,19 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati if (kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE && original.overriddenDescriptors.size == 1) return this val outerScopeQualifiers = c.computeNewDefaultTypeQualifiers(annotations) + + // When loading method as an override for a property, all annotations are stick to its getter + val annotationOwnerForMember = + if (this is JavaPropertyDescriptor && getter?.isDefault == false) + getter!! + else + this + val receiverTypeEnhancement = if (extensionReceiverParameter != null) parts( typeContainer = - this.safeAs() + annotationOwnerForMember.safeAs() ?.getUserData(JavaMethodDescriptor.ORIGINAL_VALUE_PARAMETER_FOR_EXTENSION_RECEIVER), isCovariant = false, defaultTopLevelQualifiers = @@ -117,7 +126,7 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati } } - val valueParameterEnhancements = valueParameters.map { + val valueParameterEnhancements = annotationOwnerForMember.valueParameters.map { p -> parts( typeContainer = p, isCovariant = false, @@ -130,7 +139,7 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati val returnTypeEnhancement = parts( - typeContainer = this, isCovariant = true, + typeContainer = annotationOwnerForMember, isCovariant = true, defaultTopLevelQualifiers = outerScopeQualifiers?.get( if (this.safeAs()?.isJavaField == true)