Use report policy from TypeQualifierDefault annotation if possible

This commit is contained in:
e5l
2017-09-19 13:44:55 +06:00
committed by Leonid Stashevsky
parent c512db8e1c
commit 1e157d6480
8 changed files with 176 additions and 5 deletions
@@ -0,0 +1,69 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// JSR305_GLOBAL_REPORT warn
// FILE: NonNullApi.java
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.meta.TypeQualifierDefault;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@MyNonnull
@TypeQualifierDefault({ ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD })
public @interface NonNullApi {
}
// FILE: MigrationNonNullApi.java
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.meta.TypeQualifierDefault;
import kotlin.annotations.jvm.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@MyNonnull
@UnderMigration(status = MigrationStatus.STRICT)
@TypeQualifierDefault({ ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD })
public @interface MigrationNonNullApi {
}
// FILE: PolicyFromDefault.java
@NonNullApi
public class PolicyFromDefault {
public String foo(String x) {
return x;
}
public String bar = "bar";
}
// FILE: PolicyFromNickname.java
@MigrationNonNullApi
public class PolicyFromNickname {
public String foo(String x) {
return x;
}
public String bar = "bar";
}
// FILE: main.kt
fun main(default: PolicyFromDefault, nickname: PolicyFromNickname) {
default.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>).length
default.foo("hello").length
nickname.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
nickname.foo("hello").length
}
@@ -0,0 +1,35 @@
package
public fun main(/*0*/ default: PolicyFromDefault, /*1*/ nickname: PolicyFromNickname): kotlin.Unit
@kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented @MyNonnull @kotlin.annotations.jvm.UnderMigration(status = MigrationStatus.STRICT) @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) public final annotation class MigrationNonNullApi : kotlin.Annotation {
public constructor MigrationNonNullApi()
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.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented @MyNonnull @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) 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
}
@NonNullApi public open class PolicyFromDefault {
public constructor PolicyFromDefault()
public final var bar: 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
}
@MigrationNonNullApi public open class PolicyFromNickname {
public constructor PolicyFromNickname()
public final var bar: 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
}
@@ -473,4 +473,19 @@ public class ForeignAnnotationsNoAnnotationInClasspathTestGenerated extends Abst
}
}
}
@TestMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TypeQualifierDefault extends AbstractForeignAnnotationsNoAnnotationInClasspathTest {
public void testAllFilesPresentInTypeQualifierDefault() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("defaultAndNicknameMigrationPolicy.kt")
public void testDefaultAndNicknameMigrationPolicy() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault/defaultAndNicknameMigrationPolicy.kt");
doTest(fileName);
}
}
}
@@ -473,4 +473,19 @@ public class ForeignAnnotationsNoAnnotationInClasspathWithFastClassReadingTestGe
}
}
}
@TestMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TypeQualifierDefault extends AbstractForeignAnnotationsNoAnnotationInClasspathWithFastClassReadingTest {
public void testAllFilesPresentInTypeQualifierDefault() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("defaultAndNicknameMigrationPolicy.kt")
public void testDefaultAndNicknameMigrationPolicy() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault/defaultAndNicknameMigrationPolicy.kt");
doTest(fileName);
}
}
}
@@ -473,4 +473,19 @@ public class ForeignAnnotationsTestGenerated extends AbstractForeignAnnotationsT
}
}
}
@TestMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TypeQualifierDefault extends AbstractForeignAnnotationsTest {
public void testAllFilesPresentInTypeQualifierDefault() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("defaultAndNicknameMigrationPolicy.kt")
public void testDefaultAndNicknameMigrationPolicy() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault/defaultAndNicknameMigrationPolicy.kt");
doTest(fileName);
}
}
}
@@ -473,4 +473,19 @@ public class JavacForeignAnnotationsTestGenerated extends AbstractJavacForeignAn
}
}
}
@TestMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TypeQualifierDefault extends AbstractJavacForeignAnnotationsTest {
public void testAllFilesPresentInTypeQualifierDefault() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/foreignAnnotations/tests/typeQualifierDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("defaultAndNicknameMigrationPolicy.kt")
public void testDefaultAndNicknameMigrationPolicy() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault/defaultAndNicknameMigrationPolicy.kt");
doTest(fileName);
}
}
}
@@ -138,13 +138,15 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager, private va
}
fun resolveJsr305AnnotationState(annotationDescriptor: AnnotationDescriptor): ReportLevel {
jsr305State.user[annotationDescriptor.fqName?.asString()]?.let { return it }
annotationDescriptor.annotationClass?.migrationAnnotationStatus()?.let { return it }
resolveJsr305CustomState(annotationDescriptor)?.let { return it }
return jsr305State.global
}
fun resolveJsr305CustomState(annotationDescriptor: AnnotationDescriptor): ReportLevel? {
jsr305State.user[annotationDescriptor.fqName?.asString()]?.let { return it }
return annotationDescriptor.annotationClass?.migrationAnnotationStatus()
}
private fun ClassDescriptor.migrationAnnotationStatus(): ReportLevel? {
val stateDescriptor = annotations.findAnnotation(MIGRATION_ANNOTATION_FQNAME)?.firstArgumentValue()?.safeAs<ClassDescriptor>()
?: return null
@@ -147,7 +147,12 @@ private fun LazyJavaResolverContext.extractDefaultNullabilityQualifier(
typeQualifierResolver.resolveTypeQualifierDefaultAnnotation(annotationDescriptor)
?: return null
val jsr305State = typeQualifierResolver.resolveJsr305AnnotationState(typeQualifier).takeIf { it != ReportLevel.IGNORE } ?: return null
val jsr305State = typeQualifierResolver.resolveJsr305CustomState(annotationDescriptor)
?: typeQualifierResolver.resolveJsr305AnnotationState(typeQualifier)
if (jsr305State.isIgnore) {
return null
}
val nullabilityQualifier =
components