Recognize Checker Framework declaration annotations.

We are migrating Guava to use these annotations rather than jsr305's
@Nullable. We can't use the Checker Framework's _@Nullable_ yet because
we promise compatibility with Java 7, which doesn't support type
annotations. This is related to but distinct from
https://youtrack.jetbrains.com/issue/KT-21408, which is about a
different jsr305 annotation we use, @ParametersAreNonnullByDefault.

I've also updated some docs to mention Kotlin's existing support for the
Checker Framework _@NonNull_.
This commit is contained in:
Chris Povirk
2017-12-04 17:22:54 -05:00
committed by Alexander Udalov
parent 79359b7bc2
commit ac87ad422d
10 changed files with 107 additions and 1 deletions
@@ -0,0 +1,33 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// FILE: A.java
import org.checkerframework.checker.nullness.compatqual.*;
public class A {
@NullableDecl public String field = null;
@NullableDecl
public String foo(@NonNullDecl String x, @NullableDecl CharSequence y) {
return "";
}
@NonNullDecl
public String bar() {
return "";
}
}
// FILE: main.kt
fun main(a: A) {
a.foo("", null)?.length
a.foo("", null)<!UNSAFE_CALL!>.<!>length
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")<!UNSAFE_CALL!>.<!>length
a.bar().length
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
a.field?.length
a.field<!UNSAFE_CALL!>.<!>length
}
@@ -0,0 +1,13 @@
package
public fun main(/*0*/ a: A): kotlin.Unit
public open class A {
public constructor A()
@org.checkerframework.checker.nullness.compatqual.NullableDecl public final var field: kotlin.String?
@org.checkerframework.checker.nullness.compatqual.NonNullDecl public open fun bar(): kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@org.checkerframework.checker.nullness.compatqual.NullableDecl public open fun foo(/*0*/ @org.checkerframework.checker.nullness.compatqual.NonNullDecl x: kotlin.String, /*1*/ @org.checkerframework.checker.nullness.compatqual.NullableDecl y: kotlin.CharSequence?): kotlin.String?
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -48,6 +48,12 @@ public class ForeignAnnotationsNoAnnotationInClasspathTestGenerated extends Abst
doTest(fileName);
}
@TestMetadata("checkerFramework.kt")
public void testCheckerFramework() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/checkerFramework.kt");
doTest(fileName);
}
@TestMetadata("eclipse.kt")
public void testEclipse() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/eclipse.kt");
@@ -48,6 +48,12 @@ public class ForeignAnnotationsNoAnnotationInClasspathWithFastClassReadingTestGe
doTest(fileName);
}
@TestMetadata("checkerFramework.kt")
public void testCheckerFramework() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/checkerFramework.kt");
doTest(fileName);
}
@TestMetadata("eclipse.kt")
public void testEclipse() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/eclipse.kt");
@@ -48,6 +48,12 @@ public class ForeignAnnotationsTestGenerated extends AbstractForeignAnnotationsT
doTest(fileName);
}
@TestMetadata("checkerFramework.kt")
public void testCheckerFramework() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/checkerFramework.kt");
doTest(fileName);
}
@TestMetadata("eclipse.kt")
public void testEclipse() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/eclipse.kt");
@@ -48,6 +48,12 @@ public class JavacForeignAnnotationsTestGenerated extends AbstractJavacForeignAn
doTest(fileName);
}
@TestMetadata("checkerFramework.kt")
public void testCheckerFramework() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/checkerFramework.kt");
doTest(fileName);
}
@TestMetadata("eclipse.kt")
public void testEclipse() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/eclipse.kt");
@@ -24,6 +24,7 @@ val NULLABLE_ANNOTATIONS = listOf(
FqName("com.android.annotations.Nullable"),
FqName("org.eclipse.jdt.annotation.Nullable"),
FqName("org.checkerframework.checker.nullness.qual.Nullable"),
FqName("org.checkerframework.checker.nullness.compatqual.NullableDecl"),
FqName("javax.annotation.Nullable"),
FqName("javax.annotation.CheckForNull"),
FqName("edu.umd.cs.findbugs.annotations.CheckForNull"),
@@ -42,6 +43,7 @@ val NOT_NULL_ANNOTATIONS = listOf(
FqName("com.android.annotations.NonNull"),
FqName("org.eclipse.jdt.annotation.NonNull"),
FqName("org.checkerframework.checker.nullness.qual.NonNull"),
FqName("org.checkerframework.checker.nullness.compatqual.NonNullDecl"),
FqName("lombok.NonNull"),
FqName("io.reactivex.annotations.NonNull")
)
+5 -1
View File
@@ -498,4 +498,8 @@ We can also support the following annotations out-of-the-box:
* `NotNull` and `NotNull.List`
* [Project Lombok](http://projectlombok.org/features/NonNull.html)
* [`org.eclipse.jdt.annotation`](https://wiki.eclipse.org/JDT_Core/Null_Analysis)
* [`org.checkerframework.checker.nullness.qual`](http://types.cs.washington.edu/checker-framework/current/checker-framework-manual.html#nullness-checker)
* [`org.checkerframework.checker.nullness`](https://checkerframework.org/manual/#nullness-checker)
* [`*.qual.Nullable`](https://checkerframework.org/api/org/checkerframework/checker/nullness/qual/Nullable.html)
* [`*.qual.NonNull`](https://checkerframework.org/api/org/checkerframework/checker/nullness/qual/NonNull.html)
* [`*.compatqual.NullableDecl`](https://checkerframework.org/api/org/checkerframework/checker/nullness/compatqual/NullableDecl.html)
* [`*.compatqual.NonNullDecl`](https://checkerframework.org/api/org/checkerframework/checker/nullness/compatqual/NonNullDecl.html)
@@ -0,0 +1,15 @@
package org.checkerframework.checker.nullness.compatqual;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Java 7 compatibility annotation without dependency on Java 8 classes.
*
* @see org.checkerframework.checker.nullness.qual.NonNull
* @checker_framework.manual #nullness-checker Nullness Checker
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface NonNullDecl {}
@@ -0,0 +1,15 @@
package org.checkerframework.checker.nullness.compatqual;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Java 7 compatibility annotation without dependency on Java 8 classes.
*
* @see org.checkerframework.checker.nullness.qual.Nullable
* @checker_framework.manual #nullness-checker Nullness Checker
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface NullableDecl {}