diff --git a/compiler/testData/foreignAnnotations/tests/irrelevantQualifierNicknames.kt b/compiler/testData/foreignAnnotations/tests/irrelevantQualifierNicknames.kt new file mode 100644 index 00000000000..dd7406c28c8 --- /dev/null +++ b/compiler/testData/foreignAnnotations/tests/irrelevantQualifierNicknames.kt @@ -0,0 +1,85 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER + +// FILE: UnknownQualifier.java +import 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.When; + +@Documented +@TypeQualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface UnknownQualifier { +} + +// FILE: UnknownQualifierNickname.java +import javax.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.annotation.meta.TypeQualifierNickname; +import javax.annotation.meta.When; + +@Documented +@TypeQualifierNickname +@UnknownQualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface UnknownQualifierNickname { +} + +// FILE: UnknownQualifierDefault.java +import javax.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.ElementType; +import java.lang.annotation.RetentionPolicy; + +import javax.annotation.meta.TypeQualifierDefault; +import javax.annotation.meta.When; + +@Documented +@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER}) +@UnknownQualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface UnknownQualifierDefault { +} + +// FILE: UnknownQualifierNicknameDefault.java +import javax.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.ElementType; +import java.lang.annotation.RetentionPolicy; + +import javax.annotation.meta.TypeQualifierDefault; +import javax.annotation.meta.When; + +@Documented +@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER}) +@UnknownQualifierNickname +@Retention(RetentionPolicy.RUNTIME) +public @interface UnknownQualifierNicknameDefault { +} + +// FILE: A.java + +import javax.annotation.*; + +@UnknownQualifierDefault +public class A { + @UnknownQualifierNicknameDefault + public static class B { + @UnknownQualifier + public static String foo(@UnknownQualifierNickname String x) { return null; } + } +} + +// FILE: main.kt + +fun main() { + A.B.foo(null).hashCode() +} diff --git a/compiler/testData/foreignAnnotations/tests/irrelevantQualifierNicknames.txt b/compiler/testData/foreignAnnotations/tests/irrelevantQualifierNicknames.txt new file mode 100644 index 00000000000..586eefba1c4 --- /dev/null +++ b/compiler/testData/foreignAnnotations/tests/irrelevantQualifierNicknames.txt @@ -0,0 +1,48 @@ +package + +public fun main(): kotlin.Unit + +@UnknownQualifierDefault public open class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + @UnknownQualifierNicknameDefault public open class B { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + @UnknownQualifier public open fun foo(/*0*/ @UnknownQualifierNickname x: kotlin.String!): kotlin.String! + } +} + +@kotlin.annotation.MustBeDocumented @javax.annotation.meta.TypeQualifier @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class UnknownQualifier : kotlin.Annotation { + public constructor UnknownQualifier() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.MustBeDocumented @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.METHOD, ElementType.PARAMETER}) @UnknownQualifier @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class UnknownQualifierDefault : kotlin.Annotation { + public constructor UnknownQualifierDefault() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.MustBeDocumented @javax.annotation.meta.TypeQualifierNickname @UnknownQualifier @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class UnknownQualifierNickname : kotlin.Annotation { + public constructor UnknownQualifierNickname() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.MustBeDocumented @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.METHOD, ElementType.PARAMETER}) @UnknownQualifierNickname @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class UnknownQualifierNicknameDefault : kotlin.Annotation { + public constructor UnknownQualifierNicknameDefault() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsNoAnnotationInClasspathTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsNoAnnotationInClasspathTestGenerated.java index 3c305f8be1e..d746497c794 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsNoAnnotationInClasspathTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsNoAnnotationInClasspathTestGenerated.java @@ -60,6 +60,12 @@ public class ForeignAnnotationsNoAnnotationInClasspathTestGenerated extends Abst doTest(fileName); } + @TestMetadata("irrelevantQualifierNicknames.kt") + public void testIrrelevantQualifierNicknames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/irrelevantQualifierNicknames.kt"); + doTest(fileName); + } + @TestMetadata("jsr305NullabilityNicknames.kt") public void testJsr305NullabilityNicknames() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305NullabilityNicknames.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsNoAnnotationInClasspathWithFastClassReadingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsNoAnnotationInClasspathWithFastClassReadingTestGenerated.java index 7d431287543..56776cfb8f1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsNoAnnotationInClasspathWithFastClassReadingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsNoAnnotationInClasspathWithFastClassReadingTestGenerated.java @@ -60,6 +60,12 @@ public class ForeignAnnotationsNoAnnotationInClasspathWithFastClassReadingTestGe doTest(fileName); } + @TestMetadata("irrelevantQualifierNicknames.kt") + public void testIrrelevantQualifierNicknames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/irrelevantQualifierNicknames.kt"); + doTest(fileName); + } + @TestMetadata("jsr305NullabilityNicknames.kt") public void testJsr305NullabilityNicknames() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305NullabilityNicknames.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsTestGenerated.java index 3314f7217a4..d49b548359c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsTestGenerated.java @@ -60,6 +60,12 @@ public class ForeignAnnotationsTestGenerated extends AbstractForeignAnnotationsT doTest(fileName); } + @TestMetadata("irrelevantQualifierNicknames.kt") + public void testIrrelevantQualifierNicknames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/irrelevantQualifierNicknames.kt"); + doTest(fileName); + } + @TestMetadata("jsr305NullabilityNicknames.kt") public void testJsr305NullabilityNicknames() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305NullabilityNicknames.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/JavacForeignAnnotationsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/JavacForeignAnnotationsTestGenerated.java index 286b208e856..07e739c1e56 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/JavacForeignAnnotationsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/JavacForeignAnnotationsTestGenerated.java @@ -60,6 +60,12 @@ public class JavacForeignAnnotationsTestGenerated extends AbstractJavacForeignAn doTest(fileName); } + @TestMetadata("irrelevantQualifierNicknames.kt") + public void testIrrelevantQualifierNicknames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/irrelevantQualifierNicknames.kt"); + doTest(fileName); + } + @TestMetadata("jsr305NullabilityNicknames.kt") public void testJsr305NullabilityNicknames() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/jsr305NullabilityNicknames.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 ca0f5328cc0..4a56af91530 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 @@ -68,27 +68,30 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati } fun extractNullability(annotationDescriptor: AnnotationDescriptor): NullabilityQualifierWithMigrationStatus? { + extractNullabilityFromKnownAnnotations(annotationDescriptor)?.let { return it } + + val typeQualifierAnnotation = + annotationTypeQualifierResolver.resolveTypeQualifierAnnotation(annotationDescriptor) + ?: return null + + val forWarning = annotationTypeQualifierResolver.jsr305State.isWarning() + + return extractNullabilityFromKnownAnnotations(typeQualifierAnnotation)?.copy(isForWarningOnly = forWarning) + } + + private fun extractNullabilityFromKnownAnnotations( + annotationDescriptor: AnnotationDescriptor + ): NullabilityQualifierWithMigrationStatus? { val annotationFqName = annotationDescriptor.fqName ?: return null return when (annotationFqName) { in NULLABLE_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE) in NOT_NULL_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL) JAVAX_NONNULL_ANNOTATION -> annotationDescriptor.extractNullabilityTypeFromArgument() - else -> { - val forWarning = annotationTypeQualifierResolver.jsr305State.isWarning() - - val typeQualifierAnnotation = - annotationTypeQualifierResolver.resolveTypeQualifierAnnotation(annotationDescriptor) - ?: return null - - // resolveTypeQualifierAnnotation guarantees that `typeQualifierAnnotation` is javax.annotation.NonNull with argument - // or javax.annotation.CheckForNull without arguments - extractNullability(typeQualifierAnnotation)?.copy(isForWarningOnly = forWarning) - } + else -> null } } - fun enhanceSignatures(c: LazyJavaResolverContext, platformSignatures: Collection): Collection { return platformSignatures.map { it.enhanceSignature(c)