Support codeanalysis annotations on type parameters bounds
This commit is contained in:
committed by
Victor Petukhov
parent
82d39dd86a
commit
e27501497b
+39
@@ -0,0 +1,39 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||||
|
// FILE: A.java
|
||||||
|
|
||||||
|
import jspecify.annotations.*;
|
||||||
|
|
||||||
|
public class A<T extends @NotNull Object> {
|
||||||
|
public void foo(T t) {}
|
||||||
|
public <E extends @NotNull Object> void bar(E e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: B.java
|
||||||
|
|
||||||
|
import jspecify.annotations.*;
|
||||||
|
|
||||||
|
@DefaultNotNull
|
||||||
|
public class B<T> {
|
||||||
|
public void foo(T t) {}
|
||||||
|
public <E> void bar(E e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun main(a1: A<<!UPPER_BOUND_VIOLATED!>Any?<!>>, a2: A<String>, b1: B<<!UPPER_BOUND_VIOLATED!>Any?<!>>, b2: B<String>) {
|
||||||
|
a1.foo(null)
|
||||||
|
a1.bar<<!UPPER_BOUND_VIOLATED!>String?<!>>(null)
|
||||||
|
a1.bar<String>("")
|
||||||
|
|
||||||
|
a2.foo(null)
|
||||||
|
a2.bar<<!UPPER_BOUND_VIOLATED!>String?<!>>(null)
|
||||||
|
a2.bar<String>("")
|
||||||
|
|
||||||
|
b1.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||||
|
b1.bar<<!UPPER_BOUND_VIOLATED!>String?<!>>(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||||
|
b1.bar<String>("")
|
||||||
|
|
||||||
|
b2.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||||
|
b2.bar<<!UPPER_BOUND_VIOLATED!>String?<!>>(<!NULL_FOR_NONNULL_TYPE!>null<!>)
|
||||||
|
b2.bar<String>("")
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun main(/*0*/ a1: A<kotlin.Any?>, /*1*/ a2: A<kotlin.String>, /*2*/ b1: B<kotlin.Any?>, /*3*/ b2: B<kotlin.String>): kotlin.Unit
|
||||||
|
|
||||||
|
public open class A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any> {
|
||||||
|
public constructor A</*0*/ T : @jspecify.annotations.NotNull kotlin.Any>()
|
||||||
|
public open fun </*0*/ E : @jspecify.annotations.NotNull kotlin.Any> bar(/*0*/ e: E!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open fun foo(/*0*/ t: T!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@jspecify.annotations.DefaultNotNull public open class B</*0*/ T : kotlin.Any> {
|
||||||
|
public constructor B</*0*/ T : kotlin.Any>()
|
||||||
|
public open fun </*0*/ E : kotlin.Any> bar(/*0*/ e: E): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open fun foo(/*0*/ t: T): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+10
-18
@@ -43,24 +43,6 @@ 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("defaults.kt")
|
|
||||||
public void testDefaults() throws Exception {
|
|
||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/defaults.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)
|
||||||
@@ -73,10 +55,20 @@ public class ForeignJava8AnnotationsNoAnnotationInClasspathTestGenerated extends
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/jspecify"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/jspecify"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("defaults.kt")
|
||||||
|
public void testDefaults() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/defaults.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simple.kt")
|
@TestMetadata("simple.kt")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/simple.kt");
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/simple.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParameterBounds.kt")
|
||||||
|
public void testTypeParameterBounds() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/typeParameterBounds.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305")
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305")
|
||||||
|
|||||||
+10
-18
@@ -43,24 +43,6 @@ 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("defaults.kt")
|
|
||||||
public void testDefaults() throws Exception {
|
|
||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/defaults.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)
|
||||||
@@ -73,10 +55,20 @@ public class ForeignJava8AnnotationsNoAnnotationInClasspathWithPsiClassReadingTe
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/jspecify"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/jspecify"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("defaults.kt")
|
||||||
|
public void testDefaults() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/defaults.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simple.kt")
|
@TestMetadata("simple.kt")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/simple.kt");
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/simple.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParameterBounds.kt")
|
||||||
|
public void testTypeParameterBounds() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/typeParameterBounds.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305")
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305")
|
||||||
|
|||||||
Generated
+10
-18
@@ -43,24 +43,6 @@ 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("defaults.kt")
|
|
||||||
public void testDefaults() throws Exception {
|
|
||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/defaults.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)
|
||||||
@@ -73,10 +55,20 @@ public class ForeignJava8AnnotationsTestGenerated extends AbstractForeignJava8An
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/jspecify"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/jspecify"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("defaults.kt")
|
||||||
|
public void testDefaults() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/defaults.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simple.kt")
|
@TestMetadata("simple.kt")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/simple.kt");
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/simple.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParameterBounds.kt")
|
||||||
|
public void testTypeParameterBounds() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/typeParameterBounds.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305")
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305")
|
||||||
|
|||||||
+10
-18
@@ -43,24 +43,6 @@ 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("defaults.kt")
|
|
||||||
public void testDefaults() throws Exception {
|
|
||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/codeanalysis/defaults.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)
|
||||||
@@ -73,10 +55,20 @@ public class JavacForeignJava8AnnotationsTestGenerated extends AbstractJavacFore
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/jspecify"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/foreignAnnotationsJava8/tests/jspecify"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("defaults.kt")
|
||||||
|
public void testDefaults() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/defaults.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simple.kt")
|
@TestMetadata("simple.kt")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/simple.kt");
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/simple.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParameterBounds.kt")
|
||||||
|
public void testTypeParameterBounds() throws Exception {
|
||||||
|
runTest("compiler/testData/foreignAnnotationsJava8/tests/jspecify/typeParameterBounds.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305")
|
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/jsr305")
|
||||||
|
|||||||
+1
-1
@@ -6,5 +6,5 @@
|
|||||||
package org.jetbrains.kotlin.load.java
|
package org.jetbrains.kotlin.load.java
|
||||||
|
|
||||||
enum class AnnotationQualifierApplicabilityType {
|
enum class AnnotationQualifierApplicabilityType {
|
||||||
METHOD_RETURN_TYPE, VALUE_PARAMETER, FIELD, TYPE_USE
|
METHOD_RETURN_TYPE, VALUE_PARAMETER, FIELD, TYPE_USE, TYPE_PARAMETER_BOUNDS
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -18,7 +18,8 @@ val MIGRATION_ANNOTATION_FQNAME = FqName("kotlin.annotations.jvm.UnderMigration"
|
|||||||
val DEFAULT_JSPECIFY_APPLICABILITY = listOf(
|
val DEFAULT_JSPECIFY_APPLICABILITY = listOf(
|
||||||
AnnotationQualifierApplicabilityType.FIELD,
|
AnnotationQualifierApplicabilityType.FIELD,
|
||||||
AnnotationQualifierApplicabilityType.METHOD_RETURN_TYPE,
|
AnnotationQualifierApplicabilityType.METHOD_RETURN_TYPE,
|
||||||
AnnotationQualifierApplicabilityType.VALUE_PARAMETER
|
AnnotationQualifierApplicabilityType.VALUE_PARAMETER,
|
||||||
|
AnnotationQualifierApplicabilityType.TYPE_PARAMETER_BOUNDS
|
||||||
)
|
)
|
||||||
|
|
||||||
val BUILT_IN_TYPE_QUALIFIER_DEFAULT_ANNOTATIONS = mapOf(
|
val BUILT_IN_TYPE_QUALIFIER_DEFAULT_ANNOTATIONS = mapOf(
|
||||||
|
|||||||
@@ -39,8 +39,7 @@ val NULLABLE_ANNOTATIONS = listOf(
|
|||||||
FqName("edu.umd.cs.findbugs.annotations.CheckForNull"),
|
FqName("edu.umd.cs.findbugs.annotations.CheckForNull"),
|
||||||
FqName("edu.umd.cs.findbugs.annotations.Nullable"),
|
FqName("edu.umd.cs.findbugs.annotations.Nullable"),
|
||||||
FqName("edu.umd.cs.findbugs.annotations.PossiblyNull"),
|
FqName("edu.umd.cs.findbugs.annotations.PossiblyNull"),
|
||||||
FqName("io.reactivex.annotations.Nullable"),
|
FqName("io.reactivex.annotations.Nullable")
|
||||||
JSPECIFY_NULLABLE
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val JAVAX_NONNULL_ANNOTATION = FqName("javax.annotation.Nonnull")
|
val JAVAX_NONNULL_ANNOTATION = FqName("javax.annotation.Nonnull")
|
||||||
@@ -56,8 +55,7 @@ val NOT_NULL_ANNOTATIONS = listOf(
|
|||||||
FqName("org.eclipse.jdt.annotation.NonNull"),
|
FqName("org.eclipse.jdt.annotation.NonNull"),
|
||||||
FqName("org.checkerframework.checker.nullness.qual.NonNull"),
|
FqName("org.checkerframework.checker.nullness.qual.NonNull"),
|
||||||
FqName("lombok.NonNull"),
|
FqName("lombok.NonNull"),
|
||||||
FqName("io.reactivex.annotations.NonNull"),
|
FqName("io.reactivex.annotations.NonNull")
|
||||||
JSPECIFY_NOT_NULL
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val COMPATQUAL_NULLABLE_ANNOTATION = FqName("org.checkerframework.checker.nullness.compatqual.NullableDecl")
|
val COMPATQUAL_NULLABLE_ANNOTATION = FqName("org.checkerframework.checker.nullness.compatqual.NullableDecl")
|
||||||
|
|||||||
+9
-2
@@ -38,8 +38,15 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager, private va
|
|||||||
operator fun component1() = typeQualifier
|
operator fun component1() = typeQualifier
|
||||||
operator fun component2() = AnnotationQualifierApplicabilityType.values().filter(this::isApplicableTo)
|
operator fun component2() = AnnotationQualifierApplicabilityType.values().filter(this::isApplicableTo)
|
||||||
|
|
||||||
private fun isApplicableTo(elementType: AnnotationQualifierApplicabilityType) =
|
private fun isApplicableTo(elementType: AnnotationQualifierApplicabilityType): Boolean {
|
||||||
isApplicableConsideringMask(AnnotationQualifierApplicabilityType.TYPE_USE) || isApplicableConsideringMask(elementType)
|
if (isApplicableConsideringMask(elementType)) return true
|
||||||
|
|
||||||
|
// We explicitly state that while JSR-305 TYPE_USE annotations effectively should be applied to every type
|
||||||
|
// they are not applicable for type parameter bounds because it would be a breaking change otherwise.
|
||||||
|
// Only defaulting annotations from jspecify are applicable
|
||||||
|
return isApplicableConsideringMask(AnnotationQualifierApplicabilityType.TYPE_USE) &&
|
||||||
|
elementType != AnnotationQualifierApplicabilityType.TYPE_PARAMETER_BOUNDS
|
||||||
|
}
|
||||||
|
|
||||||
private fun isApplicableConsideringMask(elementType: AnnotationQualifierApplicabilityType) =
|
private fun isApplicableConsideringMask(elementType: AnnotationQualifierApplicabilityType) =
|
||||||
(applicability and (1 shl elementType.ordinal)) != 0
|
(applicability and (1 shl elementType.ordinal)) != 0
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ private fun LazyJavaResolverContext.extractDefaultNullabilityQualifier(
|
|||||||
val nullabilityQualifier =
|
val nullabilityQualifier =
|
||||||
components
|
components
|
||||||
.signatureEnhancement
|
.signatureEnhancement
|
||||||
.extractNullability(typeQualifier)
|
.extractNullability(typeQualifier, onlyForJspecify = false)
|
||||||
?.copy(isForWarningOnly = jsr305State.isWarning)
|
?.copy(isForWarningOnly = jsr305State.isWarning)
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
@@ -187,7 +187,8 @@ private fun LazyJavaResolverContext.child(
|
|||||||
delegateForTypeQualifiers: Lazy<JavaTypeQualifiersByElementType?>
|
delegateForTypeQualifiers: Lazy<JavaTypeQualifiersByElementType?>
|
||||||
) = LazyJavaResolverContext(
|
) = LazyJavaResolverContext(
|
||||||
components,
|
components,
|
||||||
typeParameterOwner?.let { LazyJavaTypeParameterResolver(this, containingDeclaration, it, typeParametersIndexOffset) }
|
typeParameterOwner?.let {
|
||||||
|
LazyJavaTypeParameterResolver(this, containingDeclaration, it, typeParametersIndexOffset) }
|
||||||
?: typeParameterResolver,
|
?: typeParameterResolver,
|
||||||
delegateForTypeQualifiers
|
delegateForTypeQualifiers
|
||||||
)
|
)
|
||||||
|
|||||||
+4
@@ -45,6 +45,10 @@ class LazyJavaTypeParameterDescriptor(
|
|||||||
override val annotations = LazyJavaAnnotations(c, javaTypeParameter)
|
override val annotations = LazyJavaAnnotations(c, javaTypeParameter)
|
||||||
|
|
||||||
override fun resolveUpperBounds(): List<KotlinType> {
|
override fun resolveUpperBounds(): List<KotlinType> {
|
||||||
|
return computeNotEnhancedBounds().let { c.components.signatureEnhancement.enhanceTypeParameterBounds(this, it, c) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeNotEnhancedBounds(): List<KotlinType> {
|
||||||
val bounds = javaTypeParameter.upperBounds
|
val bounds = javaTypeParameter.upperBounds
|
||||||
if (bounds.isEmpty()) {
|
if (bounds.isEmpty()) {
|
||||||
return listOf(
|
return listOf(
|
||||||
|
|||||||
@@ -41,7 +41,10 @@ class LazyJavaTypeParameterResolver(
|
|||||||
|
|
||||||
private val resolve = c.storageManager.createMemoizedFunctionWithNullableValues { typeParameter: JavaTypeParameter ->
|
private val resolve = c.storageManager.createMemoizedFunctionWithNullableValues { typeParameter: JavaTypeParameter ->
|
||||||
typeParameters[typeParameter]?.let { index ->
|
typeParameters[typeParameter]?.let { index ->
|
||||||
LazyJavaTypeParameterDescriptor(c.child(this), typeParameter, typeParametersIndexOffset + index, containingDeclaration)
|
LazyJavaTypeParameterDescriptor(
|
||||||
|
c.child(this).copyWithNewDefaultTypeQualifiers(containingDeclaration.annotations),
|
||||||
|
typeParameter, typeParametersIndexOffset + index, containingDeclaration
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+75
-31
@@ -62,8 +62,11 @@ class SignatureEnhancement(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun extractNullability(annotationDescriptor: AnnotationDescriptor): NullabilityQualifierWithMigrationStatus? {
|
fun extractNullability(
|
||||||
extractNullabilityFromKnownAnnotations(annotationDescriptor)?.let { return it }
|
annotationDescriptor: AnnotationDescriptor,
|
||||||
|
onlyForJspecify: Boolean
|
||||||
|
): NullabilityQualifierWithMigrationStatus? {
|
||||||
|
extractNullabilityFromKnownAnnotations(annotationDescriptor, onlyForJspecify)?.let { return it }
|
||||||
|
|
||||||
val typeQualifierAnnotation =
|
val typeQualifierAnnotation =
|
||||||
annotationTypeQualifierResolver.resolveTypeQualifierAnnotation(annotationDescriptor)
|
annotationTypeQualifierResolver.resolveTypeQualifierAnnotation(annotationDescriptor)
|
||||||
@@ -72,42 +75,63 @@ class SignatureEnhancement(
|
|||||||
val jsr305State = annotationTypeQualifierResolver.resolveJsr305AnnotationState(annotationDescriptor)
|
val jsr305State = annotationTypeQualifierResolver.resolveJsr305AnnotationState(annotationDescriptor)
|
||||||
if (jsr305State.isIgnore) return null
|
if (jsr305State.isIgnore) return null
|
||||||
|
|
||||||
return extractNullabilityFromKnownAnnotations(typeQualifierAnnotation)?.copy(isForWarningOnly = jsr305State.isWarning)
|
return extractNullabilityFromKnownAnnotations(
|
||||||
|
typeQualifierAnnotation, onlyForJspecify
|
||||||
|
)?.copy(isForWarningOnly = jsr305State.isWarning)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractNullabilityFromKnownAnnotations(
|
private fun extractNullabilityFromKnownAnnotations(
|
||||||
annotationDescriptor: AnnotationDescriptor
|
annotationDescriptor: AnnotationDescriptor,
|
||||||
|
onlyForJspecify: Boolean
|
||||||
): NullabilityQualifierWithMigrationStatus? {
|
): NullabilityQualifierWithMigrationStatus? {
|
||||||
val annotationFqName = annotationDescriptor.fqName ?: return null
|
val annotationFqName = annotationDescriptor.fqName ?: return null
|
||||||
|
|
||||||
return when {
|
val migrationStatus =
|
||||||
annotationFqName in NULLABLE_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE)
|
jspecifyMigrationStatus(annotationFqName)
|
||||||
annotationFqName in NOT_NULL_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
|
?: (if (!onlyForJspecify) commonMigrationStatus(annotationFqName, annotationDescriptor) else null)
|
||||||
annotationFqName == JAVAX_NONNULL_ANNOTATION -> annotationDescriptor.extractNullabilityTypeFromArgument()
|
?: return null
|
||||||
|
|
||||||
annotationFqName == COMPATQUAL_NULLABLE_ANNOTATION && jsr305State.enableCompatqualCheckerFrameworkAnnotations ->
|
return if (!migrationStatus.isForWarningOnly
|
||||||
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE)
|
&& annotationDescriptor is PossiblyExternalAnnotationDescriptor
|
||||||
|
&& annotationDescriptor.isIdeExternalAnnotation
|
||||||
|
)
|
||||||
|
migrationStatus.copy(isForWarningOnly = true)
|
||||||
|
else migrationStatus
|
||||||
|
}
|
||||||
|
|
||||||
annotationFqName == COMPATQUAL_NONNULL_ANNOTATION && jsr305State.enableCompatqualCheckerFrameworkAnnotations ->
|
private fun jspecifyMigrationStatus(
|
||||||
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
|
annotationFqName: FqName
|
||||||
|
): NullabilityQualifierWithMigrationStatus? = when (annotationFqName) {
|
||||||
|
JSPECIFY_NOT_NULL -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
|
||||||
|
JSPECIFY_NULLABLE -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE)
|
||||||
|
JSPECIFY_NULLNESS_UNKNOWN -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.FORCE_FLEXIBILITY)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
annotationFqName == ANDROIDX_RECENTLY_NON_NULL_ANNOTATION -> NullabilityQualifierWithMigrationStatus(
|
private fun commonMigrationStatus(
|
||||||
NullabilityQualifier.NOT_NULL,
|
annotationFqName: FqName,
|
||||||
isForWarningOnly = true
|
annotationDescriptor: AnnotationDescriptor
|
||||||
)
|
): NullabilityQualifierWithMigrationStatus? = when {
|
||||||
|
annotationFqName in NULLABLE_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE)
|
||||||
|
annotationFqName in NOT_NULL_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
|
||||||
|
annotationFqName == JAVAX_NONNULL_ANNOTATION -> annotationDescriptor.extractNullabilityTypeFromArgument()
|
||||||
|
|
||||||
annotationFqName == ANDROIDX_RECENTLY_NULLABLE_ANNOTATION -> NullabilityQualifierWithMigrationStatus(
|
annotationFqName == COMPATQUAL_NULLABLE_ANNOTATION && jsr305State.enableCompatqualCheckerFrameworkAnnotations ->
|
||||||
NullabilityQualifier.NULLABLE,
|
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE)
|
||||||
isForWarningOnly = true
|
|
||||||
)
|
annotationFqName == COMPATQUAL_NONNULL_ANNOTATION && jsr305State.enableCompatqualCheckerFrameworkAnnotations ->
|
||||||
else -> null
|
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
|
||||||
}?.let { migrationStatus ->
|
|
||||||
if (!migrationStatus.isForWarningOnly
|
annotationFqName == ANDROIDX_RECENTLY_NON_NULL_ANNOTATION -> NullabilityQualifierWithMigrationStatus(
|
||||||
&& annotationDescriptor is PossiblyExternalAnnotationDescriptor
|
NullabilityQualifier.NOT_NULL,
|
||||||
&& annotationDescriptor.isIdeExternalAnnotation)
|
isForWarningOnly = true
|
||||||
migrationStatus.copy(isForWarningOnly = true)
|
)
|
||||||
else migrationStatus
|
|
||||||
}
|
annotationFqName == ANDROIDX_RECENTLY_NULLABLE_ANNOTATION -> NullabilityQualifierWithMigrationStatus(
|
||||||
|
NullabilityQualifier.NULLABLE,
|
||||||
|
isForWarningOnly = true
|
||||||
|
)
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <D : CallableMemberDescriptor> enhanceSignatures(c: LazyJavaResolverContext, platformSignatures: Collection<D>): Collection<D> {
|
fun <D : CallableMemberDescriptor> enhanceSignatures(c: LazyJavaResolverContext, platformSignatures: Collection<D>): Collection<D> {
|
||||||
@@ -204,6 +228,20 @@ class SignatureEnhancement(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun enhanceTypeParameterBounds(
|
||||||
|
typeParameter: TypeParameterDescriptor,
|
||||||
|
bounds: List<KotlinType>,
|
||||||
|
context: LazyJavaResolverContext
|
||||||
|
): List<KotlinType> {
|
||||||
|
return bounds.map { bound ->
|
||||||
|
SignatureParts(
|
||||||
|
typeParameter, bound, emptyList(), false, context,
|
||||||
|
AnnotationTypeQualifierResolver.QualifierApplicabilityType.TYPE_PARAMETER_BOUNDS,
|
||||||
|
typeParameterBounds = true
|
||||||
|
).enhance().type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun ValueParameterDescriptor.hasDefaultValueInAnnotation(type: KotlinType): Boolean {
|
private fun ValueParameterDescriptor.hasDefaultValueInAnnotation(type: KotlinType): Boolean {
|
||||||
val defaultValue = getDefaultValueFromAnnotation()
|
val defaultValue = getDefaultValueFromAnnotation()
|
||||||
|
|
||||||
@@ -220,7 +258,8 @@ class SignatureEnhancement(
|
|||||||
private val fromOverridden: Collection<KotlinType>,
|
private val fromOverridden: Collection<KotlinType>,
|
||||||
private val isCovariant: Boolean,
|
private val isCovariant: Boolean,
|
||||||
private val containerContext: LazyJavaResolverContext,
|
private val containerContext: LazyJavaResolverContext,
|
||||||
private val containerApplicabilityType: AnnotationQualifierApplicabilityType
|
private val containerApplicabilityType: AnnotationTypeQualifierResolver.QualifierApplicabilityType,
|
||||||
|
private val typeParameterBounds: Boolean = false
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val isForVarargParameter get() = typeContainer.safeAs<ValueParameterDescriptor>()?.varargElementType != null
|
private val isForVarargParameter get() = typeContainer.safeAs<ValueParameterDescriptor>()?.varargElementType != null
|
||||||
@@ -316,7 +355,7 @@ class SignatureEnhancement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Annotations.extractNullability(): NullabilityQualifierWithMigrationStatus? =
|
private fun Annotations.extractNullability(): NullabilityQualifierWithMigrationStatus? =
|
||||||
this.firstNotNullResult(this@SignatureEnhancement::extractNullability)
|
this.firstNotNullResult { extractNullability(it, onlyForJspecify = typeParameterBounds) }
|
||||||
|
|
||||||
private fun computeIndexedQualifiersForOverride(): (Int) -> JavaTypeQualifiers {
|
private fun computeIndexedQualifiersForOverride(): (Int) -> JavaTypeQualifiers {
|
||||||
|
|
||||||
@@ -356,7 +395,12 @@ class SignatureEnhancement(
|
|||||||
TypeAndDefaultQualifiers(
|
TypeAndDefaultQualifiers(
|
||||||
type,
|
type,
|
||||||
c.defaultTypeQualifiers
|
c.defaultTypeQualifiers
|
||||||
?.get(AnnotationQualifierApplicabilityType.TYPE_USE)
|
?.get(
|
||||||
|
if (typeParameterBounds)
|
||||||
|
AnnotationTypeQualifierResolver.QualifierApplicabilityType.TYPE_PARAMETER_BOUNDS
|
||||||
|
else
|
||||||
|
AnnotationTypeQualifierResolver.QualifierApplicabilityType.TYPE_USE
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user