Support enhancement for unbounded wildcards from codeanalysis annotations
This commit is contained in:
committed by
Victor Petukhov
parent
392ef9aa2b
commit
2f04a1505d
+75
@@ -0,0 +1,75 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||||
|
// FILE: A.java
|
||||||
|
|
||||||
|
import jspecify.annotations.*;
|
||||||
|
|
||||||
|
public class A<T extends @NotNull Object, E extends @Nullable Object, F extends @UnknownNullness Object> {
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: B.java
|
||||||
|
|
||||||
|
import jspecify.annotations.*;
|
||||||
|
|
||||||
|
public class B {
|
||||||
|
public void superAsIs(A<? super CharSequence, ? super CharSequence, ? super CharSequence> a) {}
|
||||||
|
public void superNotNull(A<? super @NotNull CharSequence, ? super @NotNull CharSequence, ? super @NotNull CharSequence> a) {}
|
||||||
|
public void superNullable(A<? super @Nullable CharSequence, ? super @Nullable CharSequence, ? super @Nullable CharSequence> a) {}
|
||||||
|
|
||||||
|
public void extendsAsIs(A<? extends CharSequence, ? extends CharSequence, ? extends CharSequence> a) {}
|
||||||
|
public void extendsNotNull(A<? extends @NotNull CharSequence, ? extends @NotNull CharSequence, ? extends @NotNull CharSequence> a) {}
|
||||||
|
public void extendsNullable(A<? extends @Nullable CharSequence, ? extends @Nullable CharSequence, ? extends @Nullable CharSequence> a) {}
|
||||||
|
|
||||||
|
public void noBounds(A<?, ?, ?> a) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun main(
|
||||||
|
aNotNullNotNullNotNull: A<String, String, String>,
|
||||||
|
aNotNullNotNullNull: A<String, String, String?>,
|
||||||
|
aNotNullNullNotNull: A<String, String?, String>,
|
||||||
|
aNotNullNullNull: A<String, String?, String?>,
|
||||||
|
|
||||||
|
aAnyNotNullNotNullNotNull: A<Any, Any, Any>,
|
||||||
|
aAnyNotNullNotNullNull: A<Any, Any, Any?>,
|
||||||
|
aAnyNotNullNullNotNull: A<Any, Any?, Any>,
|
||||||
|
aAnyNotNullNullNull: A<Any, Any?, Any?>,
|
||||||
|
b: B
|
||||||
|
) {
|
||||||
|
b.superAsIs(<!TYPE_MISMATCH!>aAnyNotNullNotNullNotNull<!>)
|
||||||
|
b.superAsIs(<!TYPE_MISMATCH!>aAnyNotNullNotNullNull<!>)
|
||||||
|
b.superAsIs(aAnyNotNullNullNotNull)
|
||||||
|
b.superAsIs(aAnyNotNullNullNull)
|
||||||
|
|
||||||
|
b.superNotNull(aAnyNotNullNotNullNotNull)
|
||||||
|
b.superNotNull(aAnyNotNullNotNullNull)
|
||||||
|
b.superNotNull(aAnyNotNullNullNotNull)
|
||||||
|
b.superNotNull(aAnyNotNullNullNull)
|
||||||
|
|
||||||
|
// TODO: Bound for the first argument in "superNullable" contradicts to declared nullability of the parameter
|
||||||
|
// Do we need to ignore such arguments' nullability?
|
||||||
|
b.superNullable(<!TYPE_MISMATCH!>aAnyNotNullNotNullNotNull<!>)
|
||||||
|
b.superNullable(<!TYPE_MISMATCH!>aAnyNotNullNotNullNull<!>)
|
||||||
|
b.superNullable(<!TYPE_MISMATCH!>aAnyNotNullNullNotNull<!>)
|
||||||
|
b.superNullable(<!TYPE_MISMATCH!>aAnyNotNullNullNull<!>)
|
||||||
|
|
||||||
|
b.extendsAsIs(aNotNullNotNullNotNull)
|
||||||
|
b.extendsAsIs(aNotNullNotNullNull)
|
||||||
|
b.extendsAsIs(aNotNullNullNotNull)
|
||||||
|
b.extendsAsIs(aNotNullNullNull)
|
||||||
|
|
||||||
|
b.extendsNotNull(aNotNullNotNullNotNull)
|
||||||
|
b.extendsNotNull(<!TYPE_MISMATCH!>aNotNullNotNullNull<!>)
|
||||||
|
b.extendsNotNull(<!TYPE_MISMATCH!>aNotNullNullNotNull<!>)
|
||||||
|
b.extendsNotNull(<!TYPE_MISMATCH!>aNotNullNullNull<!>)
|
||||||
|
|
||||||
|
b.extendsNullable(aNotNullNotNullNotNull)
|
||||||
|
b.extendsNullable(aNotNullNotNullNull)
|
||||||
|
b.extendsNullable(aNotNullNullNotNull)
|
||||||
|
b.extendsNullable(aNotNullNullNull)
|
||||||
|
|
||||||
|
b.noBounds(aNotNullNotNullNotNull)
|
||||||
|
b.noBounds(aNotNullNotNullNull)
|
||||||
|
b.noBounds(aNotNullNullNotNull)
|
||||||
|
b.noBounds(aNotNullNullNull)
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun main(/*0*/ aNotNullNotNullNotNull: A<kotlin.String, kotlin.String, kotlin.String>, /*1*/ aNotNullNotNullNull: A<kotlin.String, kotlin.String, kotlin.String?>, /*2*/ aNotNullNullNotNull: A<kotlin.String, kotlin.String?, kotlin.String>, /*3*/ aNotNullNullNull: A<kotlin.String, kotlin.String?, kotlin.String?>, /*4*/ aAnyNotNullNotNullNotNull: A<kotlin.Any, kotlin.Any, kotlin.Any>, /*5*/ aAnyNotNullNotNullNull: A<kotlin.Any, kotlin.Any, kotlin.Any?>, /*6*/ aAnyNotNullNullNotNull: A<kotlin.Any, kotlin.Any?, kotlin.Any>, /*7*/ aAnyNotNullNullNull: A<kotlin.Any, kotlin.Any?, kotlin.Any?>, /*8*/ b: B): kotlin.Unit
|
||||||
|
|
||||||
|
public open class A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any, /*1*/ E, /*2*/ F : @jspecify.annotations.UnknownNullness kotlin.Any!> {
|
||||||
|
public constructor A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any, /*1*/ E, /*2*/ F : @jspecify.annotations.UnknownNullness kotlin.Any!>()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class B {
|
||||||
|
public constructor B()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open fun extendsAsIs(/*0*/ a: A<out kotlin.CharSequence, out kotlin.CharSequence?, out kotlin.CharSequence!>!): kotlin.Unit
|
||||||
|
public open fun extendsNotNull(/*0*/ a: A<out @jspecify.annotations.NotNull kotlin.CharSequence, out @jspecify.annotations.NotNull kotlin.CharSequence, out @jspecify.annotations.NotNull kotlin.CharSequence>!): kotlin.Unit
|
||||||
|
public open fun extendsNullable(/*0*/ a: A<out @jspecify.annotations.Nullable kotlin.CharSequence?, out @jspecify.annotations.Nullable kotlin.CharSequence?, out @jspecify.annotations.Nullable kotlin.CharSequence?>!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open fun noBounds(/*0*/ a: A<*, *, *>!): kotlin.Unit
|
||||||
|
public open fun superAsIs(/*0*/ a: A<in kotlin.CharSequence, in kotlin.CharSequence?, in kotlin.CharSequence!>!): kotlin.Unit
|
||||||
|
public open fun superNotNull(/*0*/ a: A<in @jspecify.annotations.NotNull kotlin.CharSequence, in @jspecify.annotations.NotNull kotlin.CharSequence, in @jspecify.annotations.NotNull kotlin.CharSequence>!): kotlin.Unit
|
||||||
|
public open fun superNullable(/*0*/ a: A<in @jspecify.annotations.Nullable kotlin.CharSequence?, in @jspecify.annotations.Nullable kotlin.CharSequence?, in @jspecify.annotations.Nullable kotlin.CharSequence?>!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||||
|
// FILE: A.java
|
||||||
|
|
||||||
|
import jspecify.annotations.*;
|
||||||
|
|
||||||
|
public class A<T extends @NotNull Object, E extends @Nullable Object, F extends @UnknownNullness Object> {
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: B.java
|
||||||
|
|
||||||
|
import jspecify.annotations.*;
|
||||||
|
|
||||||
|
public class B {
|
||||||
|
@DefaultNotNull
|
||||||
|
public void noBoundsNotNull(A<?, ?, ?> a) {}
|
||||||
|
@DefaultNullable
|
||||||
|
public void noBoundsNullable(A<?, ?, ?> a) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun main(
|
||||||
|
aNotNullNotNullNotNull: A<String, String, String>,
|
||||||
|
aNotNullNotNullNull: A<String, String, String?>,
|
||||||
|
aNotNullNullNotNull: A<String, String?, String>,
|
||||||
|
aNotNullNullNull: A<String, String?, String?>,
|
||||||
|
b: B
|
||||||
|
) {
|
||||||
|
b.noBoundsNotNull(aNotNullNotNullNotNull)
|
||||||
|
b.noBoundsNotNull(<!TYPE_MISMATCH!>aNotNullNotNullNull<!>)
|
||||||
|
b.noBoundsNotNull(<!TYPE_MISMATCH!>aNotNullNullNotNull<!>)
|
||||||
|
b.noBoundsNotNull(<!TYPE_MISMATCH!>aNotNullNullNull<!>)
|
||||||
|
|
||||||
|
b.noBoundsNullable(aNotNullNotNullNotNull)
|
||||||
|
b.noBoundsNullable(aNotNullNotNullNull)
|
||||||
|
b.noBoundsNullable(aNotNullNullNotNull)
|
||||||
|
b.noBoundsNullable(aNotNullNullNull)
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun main(/*0*/ aNotNullNotNullNotNull: A<kotlin.String, kotlin.String, kotlin.String>, /*1*/ aNotNullNotNullNull: A<kotlin.String, kotlin.String, kotlin.String?>, /*2*/ aNotNullNullNotNull: A<kotlin.String, kotlin.String?, kotlin.String>, /*3*/ aNotNullNullNull: A<kotlin.String, kotlin.String?, kotlin.String?>, /*4*/ b: B): kotlin.Unit
|
||||||
|
|
||||||
|
public open class A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any, /*1*/ E, /*2*/ F : @jspecify.annotations.UnknownNullness kotlin.Any!> {
|
||||||
|
public constructor A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any, /*1*/ E, /*2*/ F : @jspecify.annotations.UnknownNullness kotlin.Any!>()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
@jspecify.annotations.DefaultNotNull public open fun noBoundsNotNull(/*0*/ a: A<out @jspecify.annotations.NotNull kotlin.Any, out @codeanalysis.annotations.Nullable kotlin.Any, out @codeanalysis.annotations.UnknownNullness kotlin.Any>): kotlin.Unit
|
||||||
|
@jspecify.annotations.DefaultNullable public open fun noBoundsNullable(/*0*/ a: A<out @jspecify.annotations.NotNull kotlin.Any, *, *>?): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+23
@@ -43,6 +43,29 @@ public class ForeignJava8AnnotationsNoAnnotationInClasspathTestGenerated extends
|
|||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/typeUseOnObject.kt");
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/typeUseOnObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Codeanalysis extends AbstractForeignJava8AnnotationsNoAnnotationInClasspathTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInCodeanalysis() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotatedWildcards.kt")
|
||||||
|
public void testAnnotatedWildcards() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("wildcardsWithDefault.kt")
|
||||||
|
public void testWildcardsWithDefault() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+23
@@ -43,6 +43,29 @@ public class ForeignJava8AnnotationsNoAnnotationInClasspathWithPsiClassReadingTe
|
|||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/typeUseOnObject.kt");
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/typeUseOnObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Codeanalysis extends AbstractForeignJava8AnnotationsNoAnnotationInClasspathWithPsiClassReadingTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInCodeanalysis() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotatedWildcards.kt")
|
||||||
|
public void testAnnotatedWildcards() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("wildcardsWithDefault.kt")
|
||||||
|
public void testWildcardsWithDefault() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Generated
+23
@@ -43,6 +43,29 @@ public class ForeignJava8AnnotationsTestGenerated extends AbstractForeignJava8An
|
|||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/typeUseOnObject.kt");
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/typeUseOnObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Codeanalysis extends AbstractForeignJava8AnnotationsTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInCodeanalysis() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotatedWildcards.kt")
|
||||||
|
public void testAnnotatedWildcards() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("wildcardsWithDefault.kt")
|
||||||
|
public void testWildcardsWithDefault() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+23
@@ -43,6 +43,29 @@ public class JavacForeignJava8AnnotationsTestGenerated extends AbstractJavacFore
|
|||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/typeUseOnObject.kt");
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/typeUseOnObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Codeanalysis extends AbstractJavacForeignJava8AnnotationsTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInCodeanalysis() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotatedWildcards.kt")
|
||||||
|
public void testAnnotatedWildcards() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/annotatedWildcards.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("wildcardsWithDefault.kt")
|
||||||
|
public void testWildcardsWithDefault() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/wildcardsWithDefault.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jspecify")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+26
-16
@@ -313,7 +313,8 @@ class SignatureEnhancement(
|
|||||||
private fun KotlinType.extractQualifiersFromAnnotations(
|
private fun KotlinType.extractQualifiersFromAnnotations(
|
||||||
isHeadTypeConstructor: Boolean,
|
isHeadTypeConstructor: Boolean,
|
||||||
defaultQualifiersForType: JavaDefaultQualifiers?,
|
defaultQualifiersForType: JavaDefaultQualifiers?,
|
||||||
typeParameterForArgument: TypeParameterDescriptor?
|
typeParameterForArgument: TypeParameterDescriptor?,
|
||||||
|
isFromStarProjection: Boolean
|
||||||
): JavaTypeQualifiers {
|
): JavaTypeQualifiers {
|
||||||
val composedAnnotation =
|
val composedAnnotation =
|
||||||
if (isHeadTypeConstructor && typeContainer != null)
|
if (isHeadTypeConstructor && typeContainer != null)
|
||||||
@@ -337,7 +338,7 @@ class SignatureEnhancement(
|
|||||||
val (nullabilityFromBoundsForTypeBasedOnTypeParameter, isTypeParameterWithNotNullableBounds) =
|
val (nullabilityFromBoundsForTypeBasedOnTypeParameter, isTypeParameterWithNotNullableBounds) =
|
||||||
nullabilityInfoBoundsForTypeParameterUsage()
|
nullabilityInfoBoundsForTypeParameterUsage()
|
||||||
|
|
||||||
val annotationsNullability = composedAnnotation.extractNullability()
|
val annotationsNullability = composedAnnotation.extractNullability()?.takeUnless { isFromStarProjection }
|
||||||
val nullabilityInfo =
|
val nullabilityInfo =
|
||||||
annotationsNullability
|
annotationsNullability
|
||||||
?: computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
?: computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
||||||
@@ -447,11 +448,13 @@ class SignatureEnhancement(
|
|||||||
val isHeadTypeConstructor = index == 0
|
val isHeadTypeConstructor = index == 0
|
||||||
assert(isHeadTypeConstructor || !onlyHeadTypeConstructor) { "Only head type constructors should be computed" }
|
assert(isHeadTypeConstructor || !onlyHeadTypeConstructor) { "Only head type constructors should be computed" }
|
||||||
|
|
||||||
val (qualifiers, defaultQualifiers, typeParameterForArgument) = indexedThisType[index]
|
val (qualifiers, defaultQualifiers, typeParameterForArgument, isFromStarProjection) = indexedThisType[index]
|
||||||
val verticalSlice = indexedFromSupertypes.mapNotNull { it.getOrNull(index)?.type }
|
val verticalSlice = indexedFromSupertypes.mapNotNull { it.getOrNull(index)?.type }
|
||||||
|
|
||||||
// Only the head type constructor is safely co-variant
|
// Only the head type constructor is safely co-variant
|
||||||
qualifiers.computeQualifiersForOverride(verticalSlice, defaultQualifiers, isHeadTypeConstructor, typeParameterForArgument)
|
qualifiers.computeQualifiersForOverride(
|
||||||
|
verticalSlice, defaultQualifiers, isHeadTypeConstructor, typeParameterForArgument, isFromStarProjection
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return { index -> computedResult.getOrElse(index) { JavaTypeQualifiers.NONE } }
|
return { index -> computedResult.getOrElse(index) { JavaTypeQualifiers.NONE } }
|
||||||
@@ -464,24 +467,26 @@ class SignatureEnhancement(
|
|||||||
fun add(type: KotlinType, ownerContext: LazyJavaResolverContext, typeParameterForArgument: TypeParameterDescriptor?) {
|
fun add(type: KotlinType, ownerContext: LazyJavaResolverContext, typeParameterForArgument: TypeParameterDescriptor?) {
|
||||||
val c = ownerContext.copyWithNewDefaultTypeQualifiers(type.annotations)
|
val c = ownerContext.copyWithNewDefaultTypeQualifiers(type.annotations)
|
||||||
|
|
||||||
|
val defaultQualifiers = c.defaultTypeQualifiers
|
||||||
|
?.get(
|
||||||
|
if (typeParameterBounds)
|
||||||
|
AnnotationQualifierApplicabilityType.TYPE_PARAMETER_BOUNDS
|
||||||
|
else
|
||||||
|
AnnotationQualifierApplicabilityType.TYPE_USE
|
||||||
|
)
|
||||||
list.add(
|
list.add(
|
||||||
TypeAndDefaultQualifiers(
|
TypeAndDefaultQualifiers(
|
||||||
type,
|
type,
|
||||||
c.defaultTypeQualifiers
|
defaultQualifiers,
|
||||||
?.get(
|
typeParameterForArgument,
|
||||||
if (typeParameterBounds)
|
isFromStarProjection = false
|
||||||
AnnotationQualifierApplicabilityType.TYPE_PARAMETER_BOUNDS
|
|
||||||
else
|
|
||||||
AnnotationQualifierApplicabilityType.TYPE_USE
|
|
||||||
),
|
|
||||||
typeParameterForArgument
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
for ((arg, parameter) in type.arguments.zip(type.constructor.parameters)) {
|
for ((arg, parameter) in type.arguments.zip(type.constructor.parameters)) {
|
||||||
if (arg.isStarProjection) {
|
if (arg.isStarProjection) {
|
||||||
// TODO: sort out how to handle wildcards
|
// TODO: sort out how to handle wildcards
|
||||||
list.add(TypeAndDefaultQualifiers(arg.type, null, parameter))
|
list.add(TypeAndDefaultQualifiers(arg.type, defaultQualifiers, parameter, isFromStarProjection = true))
|
||||||
} else {
|
} else {
|
||||||
add(arg.type, c, parameter)
|
add(arg.type, c, parameter)
|
||||||
}
|
}
|
||||||
@@ -496,7 +501,8 @@ class SignatureEnhancement(
|
|||||||
fromSupertypes: Collection<KotlinType>,
|
fromSupertypes: Collection<KotlinType>,
|
||||||
defaultQualifiersForType: JavaDefaultQualifiers?,
|
defaultQualifiersForType: JavaDefaultQualifiers?,
|
||||||
isHeadTypeConstructor: Boolean,
|
isHeadTypeConstructor: Boolean,
|
||||||
typeParameterForArgument: TypeParameterDescriptor?
|
typeParameterForArgument: TypeParameterDescriptor?,
|
||||||
|
isFromStarProjection: Boolean
|
||||||
): JavaTypeQualifiers {
|
): JavaTypeQualifiers {
|
||||||
val superQualifiers = fromSupertypes.map { it.extractQualifiers() }
|
val superQualifiers = fromSupertypes.map { it.extractQualifiers() }
|
||||||
val mutabilityFromSupertypes = superQualifiers.mapNotNull { it.mutability }.toSet()
|
val mutabilityFromSupertypes = superQualifiers.mapNotNull { it.mutability }.toSet()
|
||||||
@@ -505,7 +511,10 @@ class SignatureEnhancement(
|
|||||||
.mapNotNull { it.unwrapEnhancement().extractQualifiers().nullability }
|
.mapNotNull { it.unwrapEnhancement().extractQualifiers().nullability }
|
||||||
.toSet()
|
.toSet()
|
||||||
|
|
||||||
val own = extractQualifiersFromAnnotations(isHeadTypeConstructor, defaultQualifiersForType, typeParameterForArgument)
|
val own =
|
||||||
|
extractQualifiersFromAnnotations(
|
||||||
|
isHeadTypeConstructor, defaultQualifiersForType, typeParameterForArgument, isFromStarProjection
|
||||||
|
)
|
||||||
val ownNullability = own.takeIf { !it.isNullabilityQualifierForWarning }?.nullability
|
val ownNullability = own.takeIf { !it.isNullabilityQualifierForWarning }?.nullability
|
||||||
val ownNullabilityForWarning = own.nullability
|
val ownNullabilityForWarning = own.nullability
|
||||||
|
|
||||||
@@ -589,7 +598,8 @@ class SignatureEnhancement(
|
|||||||
private data class TypeAndDefaultQualifiers(
|
private data class TypeAndDefaultQualifiers(
|
||||||
val type: KotlinType,
|
val type: KotlinType,
|
||||||
val defaultQualifiers: JavaDefaultQualifiers?,
|
val defaultQualifiers: JavaDefaultQualifiers?,
|
||||||
val typeParameterForArgument: TypeParameterDescriptor?
|
val typeParameterForArgument: TypeParameterDescriptor?,
|
||||||
|
val isFromStarProjection: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun KotlinType.isNullabilityFlexible(): Boolean {
|
private fun KotlinType.isNullabilityFlexible(): Boolean {
|
||||||
|
|||||||
+1
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext
|
|||||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||||
import org.jetbrains.kotlin.types.typeUtil.createProjection
|
import org.jetbrains.kotlin.types.typeUtil.createProjection
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
|
|
||||||
fun KotlinType.hasEnhancedNullability(): Boolean =
|
fun KotlinType.hasEnhancedNullability(): Boolean =
|
||||||
SimpleClassicTypeSystemContext.hasEnhancedNullability(this)
|
SimpleClassicTypeSystemContext.hasEnhancedNullability(this)
|
||||||
|
|||||||
Reference in New Issue
Block a user