Skip to content

Commit 8df40ea

Browse files
chris-hornerdzharkov
authored andcommitted
Add support for RxJava's nullability annotations.
1 parent aee5326 commit 8df40ea

File tree

7 files changed

+130
-3
lines changed

7 files changed

+130
-3
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright (c) 2016-present, RxJava Contributors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
5+
* compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is
10+
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
11+
* the License for the specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package io.reactivex.annotations;
15+
16+
import java.lang.annotation.Documented;
17+
import java.lang.annotation.Retention;
18+
import java.lang.annotation.Target;
19+
20+
import static java.lang.annotation.ElementType.*;
21+
import static java.lang.annotation.RetentionPolicy.CLASS;
22+
23+
/**
24+
* Indicates that a field/parameter/variable/return type is never null.
25+
*/
26+
@Documented
27+
@Target(value = {FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
28+
@Retention(value = CLASS)
29+
public @interface NonNull { }
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Copyright (c) 2016-present, RxJava Contributors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
5+
* compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is
10+
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
11+
* the License for the specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package io.reactivex.annotations;
15+
16+
import java.lang.annotation.Documented;
17+
import java.lang.annotation.Retention;
18+
import java.lang.annotation.Target;
19+
20+
import static java.lang.annotation.ElementType.FIELD;
21+
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
22+
import static java.lang.annotation.ElementType.METHOD;
23+
import static java.lang.annotation.ElementType.PARAMETER;
24+
import static java.lang.annotation.RetentionPolicy.CLASS;
25+
26+
/**
27+
* Indicates that a field/parameter/variable/return type may be null.
28+
*/
29+
@Documented
30+
@Target(value = {FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
31+
@Retention(value = CLASS)
32+
public @interface Nullable { }
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
2+
// FILE: A.java
3+
4+
import io.reactivex.annotations.*;
5+
6+
public class A<T> {
7+
@Nullable public String field = null;
8+
9+
@Nullable
10+
public String foo(@NonNull String x, @Nullable CharSequence y) {
11+
return "";
12+
}
13+
14+
@NonNull
15+
public String bar() {
16+
return "";
17+
}
18+
19+
@Nullable
20+
public T baz(@NonNull T x) { return x; }
21+
}
22+
23+
// FILE: main.kt
24+
25+
fun main(a: A<String>, a1: A<String?>) {
26+
a.foo("", null)?.length
27+
a.foo("", null)<!UNSAFE_CALL!>.<!>length
28+
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "")<!UNSAFE_CALL!>.<!>length
29+
30+
a.bar().length
31+
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
32+
33+
a.field?.length
34+
a.field<!UNSAFE_CALL!>.<!>length
35+
36+
a.baz("")<!UNSAFE_CALL!>.<!>length
37+
a.baz("")?.length
38+
a.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>)<!UNSAFE_CALL!>.<!>length
39+
40+
a1.baz("")!!.length
41+
a1.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>)!!.length
42+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package
2+
3+
public fun main(/*0*/ a: A<kotlin.String>, /*1*/ a1: A<kotlin.String?>): kotlin.Unit
4+
5+
public open class A</*0*/ T : kotlin.Any!> {
6+
public constructor A</*0*/ T : kotlin.Any!>()
7+
@io.reactivex.annotations.Nullable public final var field: kotlin.String?
8+
@io.reactivex.annotations.NonNull public open fun bar(): kotlin.String
9+
@io.reactivex.annotations.Nullable public open fun baz(/*0*/ @io.reactivex.annotations.NonNull x: T): T?
10+
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
11+
@io.reactivex.annotations.Nullable public open fun foo(/*0*/ @io.reactivex.annotations.NonNull x: kotlin.String, /*1*/ @io.reactivex.annotations.Nullable y: kotlin.CharSequence?): kotlin.String?
12+
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
13+
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
14+
}

compiler/tests/org/jetbrains/kotlin/checkers/ForeignAnnotationsTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,10 @@ public void testLombokSimple() throws Exception {
7777
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/lombokSimple.kt");
7878
doTest(fileName);
7979
}
80+
81+
@TestMetadata("rxjava.kt")
82+
public void testRxjava() throws Exception {
83+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/rxjava.kt");
84+
doTest(fileName);
85+
}
8086
}

core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ val NULLABLE_ANNOTATIONS = listOf(
2828
FqName("javax.annotation.CheckForNull"),
2929
FqName("edu.umd.cs.findbugs.annotations.CheckForNull"),
3030
FqName("edu.umd.cs.findbugs.annotations.Nullable"),
31-
FqName("edu.umd.cs.findbugs.annotations.PossiblyNull")
31+
FqName("edu.umd.cs.findbugs.annotations.PossiblyNull"),
32+
FqName("io.reactivex.annotations.Nullable")
3233
)
3334

3435
val JAVAX_NONNULL_ANNOTATION = FqName("javax.annotation.Nonnull")
@@ -40,7 +41,8 @@ val NOT_NULL_ANNOTATIONS = listOf(
4041
FqName("com.android.annotations.NonNull"),
4142
FqName("org.eclipse.jdt.annotation.NonNull"),
4243
FqName("org.checkerframework.checker.nullness.qual.NonNull"),
43-
FqName("lombok.NonNull")
44+
FqName("lombok.NonNull"),
45+
FqName("io.reactivex.annotations.NonNull")
4446
)
4547

4648
val READ_ONLY_ANNOTATIONS = listOf(

core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,9 @@ object ExcludedTypeAnnotations {
238238
FqName("edu.umd.cs.findbugs.annotations.CheckForNull"),
239239
FqName("edu.umd.cs.findbugs.annotations.Nullable"),
240240
FqName("edu.umd.cs.findbugs.annotations.PossiblyNull"),
241-
FqName("lombok.NonNull")
241+
FqName("lombok.NonNull"),
242+
FqName("io.reactivex.annotations.Nullable"),
243+
FqName("io.reactivex.annotations.NonNull")
242244
)
243245

244246
val internalAnnotationsForResolve = setOf(

0 commit comments

Comments
 (0)