FIR type enhancements: handle class qualifiers, add new JSR 305 tests

Related to KT-29937
This commit is contained in:
Mikhail Glukhikh
2019-03-04 17:24:40 +03:00
parent 6c8aba8039
commit 3d29b31177
20 changed files with 931 additions and 1 deletions
@@ -47,7 +47,7 @@ class JavaClassEnhancementScope(
private val typeQualifierResolver = FirAnnotationTypeQualifierResolver(jsr305State)
private val context: FirJavaEnhancementContext =
FirJavaEnhancementContext(session) { null }
FirJavaEnhancementContext(session) { null }.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, owner.annotations)
private val enhancements = mutableMapOf<ConeCallableSymbol, ConeCallableSymbol>()
@@ -0,0 +1,16 @@
@R|FieldsAreNullable|() public open class A : R|java/lang/Object| {
public open property field(var): R|ft<kotlin/String?, kotlin/String?>|?
public get(): R|ft<kotlin/String?, kotlin/String?>|?
public set(value: R|ft<kotlin/String?, kotlin/String?>|?): kotlin/Unit
@R|javax/annotation/Nonnull|() public open property nonNullField(var): R|ft<kotlin/String, kotlin/String>|
public get(): R|ft<kotlin/String, kotlin/String>|
public set(value: R|ft<kotlin/String, kotlin/String>|): kotlin/Unit
public open operator function foo(q: R|ft<kotlin/String, kotlin/String?>|!, @R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|, @R|javax/annotation/CheckForNull|() y: R|ft<kotlin/CharSequence?, kotlin/CharSequence?>|?): R|ft<kotlin/String, kotlin/String?>|!
@R|javax/annotation/Nonnull|() public open operator function bar(): R|ft<kotlin/String, kotlin/String>|
}
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class FieldsAreNullable : R|java/lang/annotation/Annotation| {
}
@@ -0,0 +1,39 @@
// FOREIGN_ANNOTATIONS
// FILE: FieldsAreNullable.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.Nonnull;
import javax.annotation.CheckForNull;
import javax.annotation.meta.TypeQualifierDefault;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@CheckForNull
@TypeQualifierDefault({ElementType.FIELD})
public @interface FieldsAreNullable {
}
// FILE: A.java
import javax.annotation.*;
@FieldsAreNullable
public class A {
public String field = null;
@Nonnull
public String nonNullField = "";
public String foo(String q, @Nonnull String x, @CheckForNull CharSequence y) {
return "";
}
@Nonnull
public String bar() {
return "";
}
}
@@ -0,0 +1,14 @@
@R|spr/NonNullApi|() public open class A : R|java/lang/Object| {
public open operator function foo(x: R|ft<kotlin/String, kotlin/String>|, @R|spr/Nullable|() y: R|ft<kotlin/CharSequence?, kotlin/CharSequence?>|?): R|ft<kotlin/String, kotlin/String>|
@R|spr/ForceFlexibility|() public open operator function bar(x: R|ft<kotlin/String, kotlin/String?>|!, @R|javax/annotation/Nonnull|() y: R|ft<kotlin/CharSequence, kotlin/CharSequence>|): R|ft<kotlin/String, kotlin/String?>|!
}
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class ForceFlexibility : R|java/lang/annotation/Annotation| {
}
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|java/lang/annotation/Annotation| {
}
@R|java/lang/annotation/Target|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|java/lang/annotation/Annotation| {
}
@R|java/lang/annotation/Documented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) public abstract annotation class UnknownNullability : R|java/lang/annotation/Annotation| {
}
@@ -0,0 +1,99 @@
// FOREIGN_ANNOTATIONS
// FILE: spr/Nullable.java
package spr;
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.Nonnull;
import javax.annotation.meta.TypeQualifierNickname;
import javax.annotation.meta.When;
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull(when = When.MAYBE)
@TypeQualifierNickname
public @interface Nullable {
}
// FILE: spr/NonNullApi.java
package spr;
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.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
public @interface NonNullApi {
}
// FILE: spr/UnknownNullability.java
package spr;
import javax.annotation.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.annotation.meta.TypeQualifierNickname;
import javax.annotation.meta.When;
@Documented
@TypeQualifierNickname
@Nonnull(when = When.UNKNOWN)
@Retention(RetentionPolicy.RUNTIME)
public @interface UnknownNullability {
}
// FILE: spr/ForceFlexibility.java
package spr;
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.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
import javax.annotation.meta.When;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@UnknownNullability
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
public @interface ForceFlexibility {
}
// FILE: A.java
import spr.*;
@NonNullApi
public class A {
public String foo(String x, @Nullable CharSequence y) {
return "";
}
@ForceFlexibility
public String bar(String x, @javax.annotation.Nonnull CharSequence y) {
return "";
}
}
@@ -0,0 +1,26 @@
@R|spr/NonNullApi|() public open class A : R|java/lang/Object|, R|B| {
@R|spr/ForceFlexibility|() public open operator function foo(x: R|ft<kotlin/String, kotlin/String>|): R|kotlin/Unit|
public open operator function bar(@R|spr/ForceFlexibility|() x: R|ft<kotlin/String, kotlin/String>|): R|kotlin/Unit|
public open operator function baz(@R|spr/UnknownNullability|() x: R|ft<kotlin/String, kotlin/String>|): R|kotlin/Unit|
public open operator function foobar(@R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) x: R|ft<kotlin/String, kotlin/String?>|!): R|kotlin/Unit|
}
public abstract interface B : R|java/lang/Object| {
public abstract operator function foo(@R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|): R|kotlin/Unit|
public abstract operator function bar(@R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|): R|kotlin/Unit|
public abstract operator function baz(@R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|): R|kotlin/Unit|
public abstract operator function foobar(@R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|): R|kotlin/Unit|
}
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class ForceFlexibility : R|java/lang/annotation/Annotation| {
}
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|java/lang/annotation/Annotation| {
}
@R|java/lang/annotation/Documented|() @R|javax/annotation/meta/TypeQualifierNickname|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) public abstract annotation class UnknownNullability : R|java/lang/annotation/Annotation| {
}
@@ -0,0 +1,82 @@
// FOREIGN_ANNOTATIONS
// FILE: spr/NonNullApi.java
package spr;
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.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
public @interface NonNullApi {
}
// FILE: spr/UnknownNullability.java
package spr;
import javax.annotation.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.annotation.meta.TypeQualifierNickname;
import javax.annotation.meta.When;
@Documented
@TypeQualifierNickname
@Nonnull(when = When.UNKNOWN)
@Retention(RetentionPolicy.RUNTIME)
public @interface UnknownNullability {
}
// FILE: spr/ForceFlexibility.java
package spr;
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.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
import javax.annotation.meta.When;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@UnknownNullability
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
public @interface ForceFlexibility {
}
// FILE: B.java
public interface B {
public void foo(@javax.annotation.Nonnull String x);
public void bar(@javax.annotation.Nonnull String x);
public void baz(@javax.annotation.Nonnull String x);
public void foobar(@javax.annotation.Nonnull String x);
}
// FILE: A.java
import spr.*;
@NonNullApi
public class A implements B {
@ForceFlexibility
public void foo(String x) {}
public void bar(@ForceFlexibility String x) {}
public void baz(@UnknownNullability String x) {}
public void foobar(@javax.annotation.Nonnull(when = javax.annotation.meta.When.UNKNOWN) String x) {}
}
@@ -0,0 +1,54 @@
@R|NonNullApi|() public open class A : R|java/lang/Object| {
public open operator function foo1(x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/String, kotlin/String>|
public open operator function foo2(x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/String, kotlin/String>|
public open operator function foo3(x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/String, kotlin/String>|
@R|javax/annotation/Nullable|() public open operator function bar1(@R|javax/annotation/Nullable|() x: R|ft<kotlin/String?, kotlin/String?>|?): R|ft<kotlin/String?, kotlin/String?>|?
@R|javax/annotation/Nullable|() public open operator function bar2(@R|javax/annotation/Nullable|() x: R|ft<kotlin/String?, kotlin/String?>|?): R|ft<kotlin/String?, kotlin/String?>|?
public open operator function baz(@R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/String, kotlin/String>|
}
@R|NonNullApi|() public abstract interface AInt : R|java/lang/Object| {
public abstract operator function foo1(x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/CharSequence, kotlin/CharSequence>|
public abstract operator function foo2(x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/CharSequence, kotlin/CharSequence>|
public abstract operator function foo3(x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/CharSequence, kotlin/CharSequence>|
@R|javax/annotation/Nullable|() public abstract operator function bar1(@R|javax/annotation/Nullable|() x: R|ft<kotlin/String?, kotlin/String?>|?): R|ft<kotlin/CharSequence?, kotlin/CharSequence?>|?
@R|javax/annotation/Nullable|() public abstract operator function bar2(@R|javax/annotation/Nullable|() x: R|ft<kotlin/String?, kotlin/String?>|?): R|ft<kotlin/CharSequence?, kotlin/CharSequence?>|?
public abstract operator function baz(@R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/CharSequence, kotlin/CharSequence>|
}
@R|NullableApi|() public open class B : R|A|, R|AInt| {
public open operator function foo1(x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/String, kotlin/String>|
@R|javax/annotation/Nonnull|() public open operator function foo2(@R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/String, kotlin/String>|
public open operator function bar1(x: R|ft<kotlin/String?, kotlin/String?>|?): R|ft<kotlin/String?, kotlin/String?>|?
public open operator function baz(x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/String, kotlin/String>|
}
@R|NonNullApi|() public open class C : R|A|, R|AInt| {
public open operator function foo1(x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/String, kotlin/String>|
public open operator function foo2(@R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/String, kotlin/String>|
public open operator function bar1(x: R|ft<kotlin/String?, kotlin/String?>|?): R|ft<kotlin/String?, kotlin/String?>|?
@R|javax/annotation/Nullable|() public open operator function bar2(@R|javax/annotation/Nullable|() x: R|ft<kotlin/String?, kotlin/String?>|?): R|ft<kotlin/String?, kotlin/String?>|?
public open operator function baz(x: R|ft<kotlin/String, kotlin/String>|): R|ft<kotlin/String, kotlin/String>|
}
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NonNullApi : R|java/lang/annotation/Annotation| {
}
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NullableApi : R|java/lang/annotation/Annotation| {
}
@@ -0,0 +1,131 @@
// FOREIGN_ANNOTATIONS
// 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.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
public @interface NonNullApi {
}
// FILE: NullableApi.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.CheckForNull;
import javax.annotation.meta.TypeQualifierDefault;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@CheckForNull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
public @interface NullableApi {
}
// FILE: A.java
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
@NonNullApi
public class A {
public String foo1(String x) { return ""; }
public String foo2(String x) { return ""; }
public String foo3(String x) { return ""; }
@Nullable
public String bar1(@Nullable String x) { return ""; }
@Nullable
public String bar2(@Nullable String x) { return ""; }
public String baz(@Nonnull String x) { return ""; }
}
// FILE: AInt.java
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
@NonNullApi
public interface AInt {
public CharSequence foo1(String x);
public CharSequence foo2(String x);
public CharSequence foo3(String x);
@Nullable
public CharSequence bar1(@Nullable String x);
@Nullable
public CharSequence bar2(@Nullable String x);
public CharSequence baz(@Nonnull String x);
}
// FILE: B.java
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
@NullableApi
public class B extends A implements AInt {
// conflicts
public String foo1(String x) { return ""; }
// no conflicts
@Nonnull
public String foo2(@Nonnull String x) { return ""; }
// fake override for foo3 shouldn't have any conflicts
// no conflicts
public String bar1(String x) { return ""; }
// conflicts
public String baz(String x) { return ""; }
}
// FILE: C.java
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
@NonNullApi
public class C extends A implements AInt {
// no conflicts
public String foo1(String x) { return ""; }
// no conflicts
public String foo2(@Nonnull String x) { return ""; }
// fake override for foo3 shouldn't have any conflicts
// no conflicts, covariant override
public String bar1(String x) { return ""; }
// no conflicts
@Nullable
public String bar2(@Nullable String x) { return ""; }
// no conflicts
public String baz(String x) { return ""; }
}
@@ -0,0 +1,20 @@
@R|NonNullApi|() public open class A : R|java/lang/Object| {
public open property field(var): R|ft<kotlin/String, kotlin/String>|
public get(): R|ft<kotlin/String, kotlin/String>|
public set(value: R|ft<kotlin/String, kotlin/String>|): kotlin/Unit
public open operator function foo(x: R|ft<kotlin/String, kotlin/String>|, @R|javax/annotation/CheckForNull|() y: R|ft<kotlin/CharSequence?, kotlin/CharSequence?>|?): R|ft<kotlin/String, kotlin/String>|
@R|NullableApi|() public open operator function foobar(x: R|ft<kotlin/String?, kotlin/String?>|?, @R|NonNullApi|() y: R|ft<kotlin/CharSequence, kotlin/CharSequence>|): R|ft<kotlin/String?, kotlin/String?>|?
public open operator function bar(): R|ft<kotlin/String, kotlin/String>|
@R|javax/annotation/Nullable|() public open operator function baz(): R|ft<kotlin/collections/MutableList<ft<kotlin/String, kotlin/String?>>?, kotlin/collections/List<ft<kotlin/String, kotlin/String?>>?>|?
}
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class FieldsAreNullable : R|java/lang/annotation/Annotation| {
}
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NonNullApi : R|java/lang/annotation/Annotation| {
}
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NullableApi : R|java/lang/annotation/Annotation| {
}
@@ -0,0 +1,128 @@
// FOREIGN_ANNOTATIONS
// 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.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
public @interface NonNullApi {
}
// FILE: NullableApi.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.CheckForNull;
import javax.annotation.meta.TypeQualifierDefault;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@CheckForNull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
public @interface NullableApi {
}
// FILE: FieldsAreNullable.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.Nonnull;
import javax.annotation.CheckForNull;
import javax.annotation.meta.TypeQualifierDefault;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@CheckForNull
@TypeQualifierDefault({ElementType.FIELD})
public @interface FieldsAreNullable {
}
// FILE: A.java
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
@NonNullApi
public class A {
public String field = null;
public String foo(String x, @CheckForNull CharSequence y) {
return "";
}
@NullableApi
public String foobar(String x, @NonNullApi CharSequence y) {
return "";
}
public String bar() {
return "";
}
@Nullable
public java.util.List<String> baz() {
return null;
}
@NullableApi
public class B {
public String field = null;
public String foo(String x, @Nonnull CharSequence y) {
return "";
}
@NonNullApi
public String foobar(String x, @NullableApi CharSequence y) {
return "";
}
public String bar() {
return "";
}
@Nullable
public java.util.List<String> baz() {
return null;
}
}
@FieldsAreNullable
public class C {
public String field = null;
public String foo(String x, @Nullable CharSequence y) {
return "";
}
@NullableApi
public String foobar(String x, @Nullable CharSequence y) {
return "";
}
public String bar() {
return "";
}
@Nullable
public java.util.List<String> baz() {
return null;
}
}
}
@@ -0,0 +1,10 @@
@R|javax/annotation/ParametersAreNonnullByDefault|() public open class A : R|java/lang/Object| {
@R|javax/annotation/Nullable|() public open property field(var): R|ft<kotlin/String?, kotlin/String?>|?
public get(): R|ft<kotlin/String?, kotlin/String?>|?
public set(value: R|ft<kotlin/String?, kotlin/String?>|?): kotlin/Unit
public open operator function foo(q: R|ft<kotlin/String, kotlin/String>|, @R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|, @R|javax/annotation/CheckForNull|() y: R|ft<kotlin/CharSequence?, kotlin/CharSequence?>|?): R|ft<kotlin/String, kotlin/String?>|!
@R|javax/annotation/Nonnull|() public open operator function bar(): R|ft<kotlin/String, kotlin/String>|
}
@@ -0,0 +1,20 @@
// FOREIGN_ANNOTATIONS
// FILE: A.java
import javax.annotation.*;
@ParametersAreNonnullByDefault
public class A {
@Nullable public String field = null;
public String foo(String q, @Nonnull String x, @CheckForNull CharSequence y) {
return "";
}
@Nonnull
public String bar() {
return "";
}
}
@@ -0,0 +1,20 @@
public open class A : R|java/lang/Object| {
@R|javax/annotation/Nullable|() public open property field(var): R|ft<kotlin/String?, kotlin/String?>|?
public get(): R|ft<kotlin/String?, kotlin/String?>|?
public set(value: R|ft<kotlin/String?, kotlin/String?>|?): kotlin/Unit
public open operator function foo(q: R|ft<kotlin/String, kotlin/String?>|!, @R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|, @R|javax/annotation/CheckForNull|() y: R|ft<kotlin/CharSequence?, kotlin/CharSequence?>|?): R|ft<kotlin/String, kotlin/String?>|!
@R|javax/annotation/Nonnull|() public open operator function bar(): R|ft<kotlin/String, kotlin/String>|
}
public open class A2 : R|java/lang/Object| {
@R|javax/annotation/Nullable|() public open property field(var): R|ft<kotlin/String?, kotlin/String?>|?
public get(): R|ft<kotlin/String?, kotlin/String?>|?
public set(value: R|ft<kotlin/String?, kotlin/String?>|?): kotlin/Unit
public open operator function foo(q: R|ft<kotlin/String, kotlin/String?>|!, @R|javax/annotation/Nonnull|() x: R|ft<kotlin/String, kotlin/String>|, @R|javax/annotation/CheckForNull|() y: R|ft<kotlin/CharSequence?, kotlin/CharSequence?>|?): R|ft<kotlin/String, kotlin/String?>|!
@R|javax/annotation/Nonnull|() public open operator function bar(): R|ft<kotlin/String, kotlin/String>|
}
@@ -0,0 +1,45 @@
// FOREIGN_ANNOTATIONS
// FILE: test/package-info.java
@javax.annotation.ParametersAreNonnullByDefault()
package test;
// FILE: test/A.java
package test;
import javax.annotation.*;
public class A {
@Nullable public String field = null;
public String foo(String q, @Nonnull String x, @CheckForNull CharSequence y) {
return "";
}
@Nonnull
public String bar() {
return "";
}
}
// FILE: test2/A2.java
package test2;
import javax.annotation.*;
public class A2 {
@Nullable public String field = null;
public String foo(String q, @Nonnull String x, @CheckForNull CharSequence y) {
return "";
}
@Nonnull
public String bar() {
return "";
}
}
@@ -0,0 +1,16 @@
@R|spr/NonNullApi|() public open class A : R|java/lang/Object| {
public open property field(var): R|ft<kotlin/String, kotlin/String?>|!
public get(): R|ft<kotlin/String, kotlin/String?>|!
public set(value: R|ft<kotlin/String, kotlin/String?>|!): kotlin/Unit
public open operator function foo(x: R|ft<kotlin/String, kotlin/String>|, @R|spr/Nullable|() y: R|ft<kotlin/CharSequence?, kotlin/CharSequence?>|?): R|ft<kotlin/String, kotlin/String>|
public open operator function bar(): R|ft<kotlin/String, kotlin/String>|
@R|spr/Nullable|() public open operator function baz(): R|ft<kotlin/collections/MutableList<ft<kotlin/String, kotlin/String?>>?, kotlin/collections/List<ft<kotlin/String, kotlin/String?>>?>|?
}
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|java/lang/annotation/Annotation| {
}
@R|java/lang/annotation/Target|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|java/lang/annotation/Annotation| {
}
@@ -0,0 +1,65 @@
// FOREIGN_ANNOTATIONS
// FILE: spr/Nullable.java
package spr;
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.Nonnull;
import javax.annotation.meta.TypeQualifierNickname;
import javax.annotation.meta.When;
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull(when = When.MAYBE)
@TypeQualifierNickname
public @interface Nullable {
}
// FILE: spr/NonNullApi.java
package spr;
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.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
public @interface NonNullApi {
}
// FILE: A.java
import spr.*;
@NonNullApi
public class A {
public String field = null;
public String foo(String x, @Nullable CharSequence y) {
return "";
}
public String bar() {
return "";
}
@Nullable
public java.util.List<String> baz() {
return null;
}
}
@@ -0,0 +1,16 @@
public open class A : R|java/lang/Object| {
public open property field(var): R|ft<kotlin/String, kotlin/String?>|!
public get(): R|ft<kotlin/String, kotlin/String?>|!
public set(value: R|ft<kotlin/String, kotlin/String?>|!): kotlin/Unit
public open operator function foo(x: R|ft<kotlin/String, kotlin/String?>|!, @R|spr/Nullable|() y: R|ft<kotlin/CharSequence?, kotlin/CharSequence?>|?): R|ft<kotlin/String, kotlin/String?>|!
public open operator function bar(): R|ft<kotlin/String, kotlin/String?>|!
@R|spr/Nullable|() public open operator function baz(): R|ft<kotlin/collections/MutableList<ft<kotlin/String, kotlin/String?>>?, kotlin/collections/List<ft<kotlin/String, kotlin/String?>>?>|?
}
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.PACKAGE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|java/lang/annotation/Annotation| {
}
@R|java/lang/annotation/Target|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.MAYBE|()) @R|javax/annotation/meta/TypeQualifierNickname|() public abstract annotation class Nullable : R|java/lang/annotation/Annotation| {
}
@@ -0,0 +1,71 @@
// FOREIGN_ANNOTATIONS
// FILE: spr/Nullable.java
package spr;
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.Nonnull;
import javax.annotation.meta.TypeQualifierNickname;
import javax.annotation.meta.When;
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull(when = When.MAYBE)
@TypeQualifierNickname
public @interface Nullable {
}
// FILE: spr/NonNullApi.java
package spr;
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.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
@Target(ElementType.PACKAGE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Nonnull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
public @interface NonNullApi {
}
// FILE: test/package-info.java
@spr.NonNullApi()
package test;
// FILE: test/A.java
package test;
import spr.*;
public class A {
public String field = null;
public String foo(String x, @Nullable CharSequence y) {
return "";
}
public String bar() {
return "";
}
@Nullable
public java.util.List<String> baz() {
return null;
}
}
@@ -55,5 +55,63 @@ public class OwnFirTypeEnhancementTestGenerated extends AbstractOwnFirTypeEnhanc
public void testStrange() throws Exception {
runTest("compiler/fir/resolve/testData/enhancement/jsr305/Strange.java");
}
@TestMetadata("compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TypeQualifierDefault extends AbstractOwnFirTypeEnhancementTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInTypeQualifierDefault() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true);
}
@TestMetadata("FieldsAreNullable.java")
public void testFieldsAreNullable() throws Exception {
runTest("compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/FieldsAreNullable.java");
}
@TestMetadata("ForceFlexibility.java")
public void testForceFlexibility() throws Exception {
runTest("compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibility.java");
}
@TestMetadata("ForceFlexibleOverOverrides.java")
public void testForceFlexibleOverOverrides() throws Exception {
runTest("compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibleOverOverrides.java");
}
@TestMetadata("NullabilityFromOverridden.java")
public void testNullabilityFromOverridden() throws Exception {
runTest("compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/NullabilityFromOverridden.java");
}
@TestMetadata("OverridingDefaultQualifier.java")
public void testOverridingDefaultQualifier() throws Exception {
runTest("compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/OverridingDefaultQualifier.java");
}
@TestMetadata("ParametersAreNonnullByDefault.java")
public void testParametersAreNonnullByDefault() throws Exception {
runTest("compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefault.java");
}
@TestMetadata("ParametersAreNonnullByDefaultPackage.java")
public void testParametersAreNonnullByDefaultPackage() throws Exception {
runTest("compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefaultPackage.java");
}
@TestMetadata("SpringNullable.java")
public void testSpringNullable() throws Exception {
runTest("compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullable.java");
}
@TestMetadata("SpringNullablePackage.java")
public void testSpringNullablePackage() throws Exception {
runTest("compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullablePackage.java");
}
}
}
}