[FE 1.0] Support loading rxjava3 nullability annotations on bounded wildcards

^KT-53041 Fixed
This commit is contained in:
Victor Petukhov
2022-07-05 14:46:50 +02:00
committed by teamcity
parent 9f72193d57
commit cb2dbca0c3
12 changed files with 277 additions and 3 deletions
@@ -27847,6 +27847,32 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/javaInterop/unresolvedJavaClassInDifferentFile.kt");
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests")
@TestDataPath("$PROJECT_ROOT")
public class ForeignAnnotationsTests {
@Test
public void testAllFilesPresentInForeignAnnotationsTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests")
@TestDataPath("$PROJECT_ROOT")
public class Tests {
@Test
public void testAllFilesPresentInTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("kt53041.kt")
public void testKt53041() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt");
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/generics")
@TestDataPath("$PROJECT_ROOT")
@@ -0,0 +1,27 @@
// FIR_IDENTICAL
// JVM_TARGET: 1.8
// NULLABILITY_ANNOTATIONS: @io.reactivex.rxjava3.annotations:strict
// IGNORE_LIGHT_ANALYSIS
// FILE: MyBiConsumer.java
import io.reactivex.rxjava3.annotations.NonNull;
@FunctionalInterface
public interface MyBiConsumer<@NonNull T> {
void accept(T t);
}
// FILE: MyMaybe.java
import io.reactivex.rxjava3.annotations.Nullable;
public class MyMaybe {
public static void doOnEvent(MyBiConsumer<@Nullable ? super Throwable> onEvent) {
onEvent.accept(null);
}
}
// FILE: main.kt
fun box(): String {
MyMaybe.doOnEvent { _ -> }
return "OK"
}
@@ -27283,6 +27283,32 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/javaInterop/unresolvedJavaClassInDifferentFile.kt");
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests")
@TestDataPath("$PROJECT_ROOT")
public class ForeignAnnotationsTests {
@Test
public void testAllFilesPresentInForeignAnnotationsTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests")
@TestDataPath("$PROJECT_ROOT")
public class Tests {
@Test
public void testAllFilesPresentInTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@Test
@TestMetadata("kt53041.kt")
public void testKt53041() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt");
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/generics")
@TestDataPath("$PROJECT_ROOT")
@@ -27847,6 +27847,32 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/javaInterop/unresolvedJavaClassInDifferentFile.kt");
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests")
@TestDataPath("$PROJECT_ROOT")
public class ForeignAnnotationsTests {
@Test
public void testAllFilesPresentInForeignAnnotationsTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests")
@TestDataPath("$PROJECT_ROOT")
public class Tests {
@Test
public void testAllFilesPresentInTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("kt53041.kt")
public void testKt53041() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt");
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/generics")
@TestDataPath("$PROJECT_ROOT")
@@ -23032,6 +23032,37 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/javaInterop/unresolvedJavaClassInDifferentFile.kt");
}
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ForeignAnnotationsTests extends AbstractLightAnalysisModeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInForeignAnnotationsTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Tests extends AbstractLightAnalysisModeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("kt53041.kt")
public void testKt53041() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt");
}
}
}
@TestMetadata("compiler/testData/codegen/box/javaInterop/generics")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -10,8 +10,16 @@ import org.jetbrains.kotlin.name.findValueForMostSpecificFqname
import org.jetbrains.kotlin.storage.LockBasedStorageManager
val JSPECIFY_ANNOTATIONS_PACKAGE = FqName("org.jspecify.nullness")
val RXJAVA3_ANNOTATIONS_PACKAGE = FqName("io.reactivex.rxjava3.annotations")
val CHECKER_FRAMEWORK_COMPATQUAL_ANNOTATIONS_PACKAGE = FqName("org.checkerframework.checker.nullness.compatqual")
private val RXJAVA3_ANNOTATIONS_PACKAGE_NAME = RXJAVA3_ANNOTATIONS_PACKAGE.asString()
val RXJAVA3_ANNOTATIONS = arrayOf(
FqName("$RXJAVA3_ANNOTATIONS_PACKAGE_NAME.Nullable"),
FqName("$RXJAVA3_ANNOTATIONS_PACKAGE_NAME.NonNull")
)
val NULLABILITY_ANNOTATION_SETTINGS: NullabilityAnnotationStates<JavaNullabilityAnnotationsStatus> = NullabilityAnnotationStatesImpl(
mapOf(
FqName("org.jetbrains.annotations") to JavaNullabilityAnnotationsStatus.DEFAULT,
@@ -39,7 +47,7 @@ val NULLABILITY_ANNOTATION_SETTINGS: NullabilityAnnotationStates<JavaNullability
sinceVersion = KotlinVersion(1, 9),
reportLevelAfter = ReportLevel.STRICT
),
FqName("io.reactivex.rxjava3.annotations") to JavaNullabilityAnnotationsStatus(
RXJAVA3_ANNOTATIONS_PACKAGE to JavaNullabilityAnnotationsStatus(
reportLevelBefore = ReportLevel.WARN,
sinceVersion = KotlinVersion(1, 8),
reportLevelAfter = ReportLevel.STRICT
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMapper
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.types.TypeUsage
import org.jetbrains.kotlin.load.java.extractNullabilityAnnotationOnBoundedWildcard
import org.jetbrains.kotlin.types.TypeUsage.COMMON
import org.jetbrains.kotlin.types.TypeUsage.SUPERTYPE
import org.jetbrains.kotlin.load.java.lazy.LazyJavaAnnotations
@@ -287,8 +287,15 @@ class JavaTypeResolver(
if (bound == null || projectionKind.isConflictingArgumentFor(typeParameter))
makeStarProjection(typeParameter, attr)
else {
val nullabilityAnnotationOnWildcard = extractNullabilityAnnotationOnBoundedWildcard(c, javaType)
val transformedJavaType = transformJavaType(bound, COMMON.toAttributes()).let {
if (nullabilityAnnotationOnWildcard != null) {
it.replaceAnnotations(Annotations.create(it.annotations + nullabilityAnnotationOnWildcard))
} else it
}
createProjection(
type = transformJavaType(bound, COMMON.toAttributes()),
type = transformedJavaType,
projectionKind = projectionKind,
typeParameterDescriptor = typeParameter
)
@@ -18,7 +18,11 @@ package org.jetbrains.kotlin.load.java
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.load.java.lazy.LazyJavaAnnotations
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.structure.JavaWildcardType
import org.jetbrains.kotlin.resolve.deprecation.DescriptorBasedDeprecationInfo
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
@@ -36,3 +40,9 @@ fun isJspecifyEnabledInStrictMode(javaTypeEnhancementState: JavaTypeEnhancementS
fun hasErasedValueParameters(memberDescriptor: CallableMemberDescriptor) =
memberDescriptor is FunctionDescriptor && memberDescriptor.getUserData(JavaMethodDescriptor.HAS_ERASED_VALUE_PARAMETERS) == true
// For now it's supported only for RxJava3 annotations, see KT-53041
fun extractNullabilityAnnotationOnBoundedWildcard(c: LazyJavaResolverContext, wildcardType: JavaWildcardType): AnnotationDescriptor? {
require(wildcardType.bound != null) { "Nullability annotations on unbounded wildcards aren't supported" }
return LazyJavaAnnotations(c, wildcardType).find { annotation -> RXJAVA3_ANNOTATIONS.any { annotation.fqName == it } }
}
@@ -21123,6 +21123,32 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests")
@TestDataPath("$PROJECT_ROOT")
public class ForeignAnnotationsTests {
@Test
public void testAllFilesPresentInForeignAnnotationsTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests")
@TestDataPath("$PROJECT_ROOT")
public class Tests {
@Test
public void testAllFilesPresentInTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@Test
@TestMetadata("kt53041.kt")
public void testKt53041() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt");
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/generics")
@TestDataPath("$PROJECT_ROOT")
@@ -21087,6 +21087,32 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests")
@TestDataPath("$PROJECT_ROOT")
public class ForeignAnnotationsTests {
@Test
public void testAllFilesPresentInForeignAnnotationsTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests")
@TestDataPath("$PROJECT_ROOT")
public class Tests {
@Test
public void testAllFilesPresentInTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@Test
@TestMetadata("kt53041.kt")
public void testKt53041() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt");
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/generics")
@TestDataPath("$PROJECT_ROOT")
@@ -18710,6 +18710,37 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ForeignAnnotationsTests extends AbstractIrCodegenBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInForeignAnnotationsTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Tests extends AbstractIrCodegenBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@TestMetadata("kt53041.kt")
public void testKt53041() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt");
}
}
}
@TestMetadata("compiler/testData/codegen/box/javaInterop/generics")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -23768,6 +23768,36 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests")
@TestDataPath("$PROJECT_ROOT")
@Tag("codegen")
@UseExtTestCaseGroupProvider()
public class ForeignAnnotationsTests {
@Test
public void testAllFilesPresentInForeignAnnotationsTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests")
@TestDataPath("$PROJECT_ROOT")
@Tag("codegen")
@UseExtTestCaseGroupProvider()
public class Tests {
@Test
public void testAllFilesPresentInTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
@Test
@TestMetadata("kt53041.kt")
public void testKt53041() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt");
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/javaInterop/generics")
@TestDataPath("$PROJECT_ROOT")