diff --git a/compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeUseVsMethodConflict.kt b/compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeUseVsMethodConflict.kt new file mode 100644 index 00000000000..d9931c5c933 --- /dev/null +++ b/compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeUseVsMethodConflict.kt @@ -0,0 +1,80 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// SKIP_JAVAC +// SKIP_COMPILED_JAVA + +// FILE: spr/NonNullApi.java + +package spr; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import javax.annotation.Nonnull; +import javax.annotation.meta.TypeQualifierDefault; + +@Target({ElementType.TYPE, ElementType.TYPE_USE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Nonnull +@TypeQualifierDefault({ElementType.TYPE_USE, ElementType.METHOD}) +public @interface NonNullApi { +} + +// FILE: spr/NullableApi.java + +package spr; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import javax.annotation.Nonnull; +import javax.annotation.meta.TypeQualifierDefault; +import javax.annotation.meta.When; + +@Target({ElementType.TYPE_USE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Nonnull(when = When.MAYBE) +@TypeQualifierDefault({ElementType.TYPE_USE}) +public @interface NullableApi { +} + +// FILE: A.java + +import spr.*; +import java.util.*; + +@NonNullApi +public class A { + public String foo(String x) { return ""; } + public @NullableApi String bar(@NullableApi String y) { return ""; } + public @NullableApi List baz1() { return null; } + public List<@NullableApi String> baz2() { return null; } + public @NullableApi List<@NonNullApi String> baz3() { return null; } +} + +// FILE: main.kt + +fun main(a: A) { + a.foo("").length + a.foo(null)?.length + + a.bar("").length + a.bar(null)?.length + + a.baz1().get(0).length + a.baz1()!!.get(0).length + a.baz1()!!.get(0)?.length + + a.baz2().get(0).length + a.baz2()!!.get(0).length + a.baz2()!!.get(0)?.length + + a.baz3().get(0).length + a.baz3()!!.get(0).length + a.baz3()!!.get(0)?.length +} diff --git a/compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeUseVsMethodConflict.txt b/compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeUseVsMethodConflict.txt new file mode 100644 index 00000000000..2cf8d4c01fb --- /dev/null +++ b/compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeUseVsMethodConflict.txt @@ -0,0 +1,32 @@ +package + +public fun main(/*0*/ a: A): kotlin.Unit + +@spr.NonNullApi public open class A { + public constructor A() + @spr.NullableApi public open fun bar(/*0*/ @spr.NullableApi y: @spr.NullableApi kotlin.String?): @spr.NullableApi kotlin.String? + @spr.NullableApi public open fun baz1(): (@spr.NullableApi kotlin.collections.MutableList?..@spr.NullableApi kotlin.collections.List?) + public open fun baz2(): kotlin.collections.(Mutable)List<@spr.NullableApi kotlin.String?> + @spr.NullableApi public open fun baz3(): (@spr.NullableApi kotlin.collections.MutableList<@spr.NonNullApi kotlin.String>?..@spr.NullableApi kotlin.collections.List<@spr.NonNullApi kotlin.String>?) + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foo(/*0*/ x: kotlin.String): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +package spr { + + @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FILE, AnnotationTarget.TYPE}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented @javax.annotation.Nonnull @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.TYPE_USE, ElementType.METHOD}) public final annotation class NonNullApi : kotlin.Annotation { + public constructor NonNullApi() + 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.Target(allowedTargets = {AnnotationTarget.TYPE}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented @javax.annotation.Nonnull(when = When.MAYBE) @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.TYPE_USE}) public final annotation class NullableApi : kotlin.Annotation { + public constructor NullableApi() + 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-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsNoAnnotationInClasspathTestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsNoAnnotationInClasspathTestGenerated.java index 9e2d1b7cc9e..4e59e622e7b 100644 --- a/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsNoAnnotationInClasspathTestGenerated.java +++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsNoAnnotationInClasspathTestGenerated.java @@ -79,6 +79,12 @@ public class ForeignJava8AnnotationsNoAnnotationInClasspathTestGenerated extends String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeArguments.kt"); doTest(fileName); } + + @TestMetadata("typeUseVsMethodConflict.kt") + public void testTypeUseVsMethodConflict() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeUseVsMethodConflict.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/typeEnhancement") diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsNoAnnotationInClasspathWithFastClassReadingTestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsNoAnnotationInClasspathWithFastClassReadingTestGenerated.java index 55cfc358e17..33ac4d93fbf 100644 --- a/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsNoAnnotationInClasspathWithFastClassReadingTestGenerated.java +++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsNoAnnotationInClasspathWithFastClassReadingTestGenerated.java @@ -79,6 +79,12 @@ public class ForeignJava8AnnotationsNoAnnotationInClasspathWithFastClassReadingT String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeArguments.kt"); doTest(fileName); } + + @TestMetadata("typeUseVsMethodConflict.kt") + public void testTypeUseVsMethodConflict() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeUseVsMethodConflict.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/typeEnhancement") diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsTestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsTestGenerated.java index be60ddb5e36..5822c98f8e3 100644 --- a/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsTestGenerated.java +++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/ForeignJava8AnnotationsTestGenerated.java @@ -79,6 +79,12 @@ public class ForeignJava8AnnotationsTestGenerated extends AbstractForeignJava8An String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeArguments.kt"); doTest(fileName); } + + @TestMetadata("typeUseVsMethodConflict.kt") + public void testTypeUseVsMethodConflict() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeUseVsMethodConflict.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/typeEnhancement") diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/javac/JavacForeignJava8AnnotationsTestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/javac/JavacForeignJava8AnnotationsTestGenerated.java index b54e4241237..ab8fa8f1b6d 100644 --- a/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/javac/JavacForeignJava8AnnotationsTestGenerated.java +++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/javac/JavacForeignJava8AnnotationsTestGenerated.java @@ -79,6 +79,12 @@ public class JavacForeignJava8AnnotationsTestGenerated extends AbstractJavacFore String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeArguments.kt"); doTest(fileName); } + + @TestMetadata("typeUseVsMethodConflict.kt") + public void testTypeUseVsMethodConflict() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305/typeUseVsMethodConflict.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/typeEnhancement") diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/AnnotationTypeQualifierResolver.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/AnnotationTypeQualifierResolver.kt index 2bc0f256b7d..db0150fb6e9 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/AnnotationTypeQualifierResolver.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/AnnotationTypeQualifierResolver.kt @@ -42,10 +42,14 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager, val jsr305 private val typeQualifier: AnnotationDescriptor, private val applicability: Int ) { - private fun isApplicableTo(elementType: QualifierApplicabilityType) = (applicability and (1 shl elementType.ordinal)) != 0 - operator fun component1() = typeQualifier operator fun component2() = QualifierApplicabilityType.values().filter(this::isApplicableTo) + + private fun isApplicableTo(elementType: QualifierApplicabilityType) = + isApplicableConsideringMask(QualifierApplicabilityType.TYPE_USE) || isApplicableConsideringMask(elementType) + + private fun isApplicableConsideringMask(elementType: QualifierApplicabilityType) = + (applicability and (1 shl elementType.ordinal)) != 0 } private val resolvedNicknames = diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/context.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/context.kt index 6ee1f4778b5..4fa7f711b58 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/context.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/context.kt @@ -78,10 +78,7 @@ class JavaTypeQualifiersByElementType( operator fun get( applicabilityType: AnnotationTypeQualifierResolver.QualifierApplicabilityType? ): JavaTypeQualifiers? { - val nullabilityQualifierWithMigrationStatus = - nullabilityQualifiers[applicabilityType] - ?: nullabilityQualifiers[AnnotationTypeQualifierResolver.QualifierApplicabilityType.TYPE_USE] - ?: return null + val nullabilityQualifierWithMigrationStatus = nullabilityQualifiers[applicabilityType] ?: return null return JavaTypeQualifiers( nullabilityQualifierWithMigrationStatus.qualifier, null,