Support TypeQualifierDefault from JSR 305 for nullability qualifiers
#KT-10942 Fixed
This commit is contained in:
compiler/testData/foreignAnnotations/annotations/javax/annotation/ParametersAreNonnullByDefault.java
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
package javax.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.annotation.meta.TypeQualifierDefault;
|
||||
|
||||
/**
|
||||
* This annotation can be applied to a package, class or method to indicate that
|
||||
* the method parameters in that element are nonnull by default unless there is:
|
||||
* <ul>
|
||||
* <li>An explicit nullness annotation
|
||||
* <li>The method overrides a method in a superclass (in which case the
|
||||
* annotation of the corresponding parameter in the superclass applies)
|
||||
* <li>There is a default parameter annotation (like {@link ParametersAreNullableByDefault})
|
||||
* applied to a more tightly nested element.
|
||||
* </ul>
|
||||
*
|
||||
* @see Nonnull
|
||||
*/
|
||||
@Documented
|
||||
@Nonnull
|
||||
@TypeQualifierDefault(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ParametersAreNonnullByDefault {
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
// 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 "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main(a: A) {
|
||||
// foo is platform
|
||||
a.foo("", "", null)?.length
|
||||
a.foo("", "", null).length
|
||||
a.foo(null, <!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
a.bar().length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field?.length
|
||||
a.field<!UNSAFE_CALL!>.<!>length
|
||||
a.field = null
|
||||
|
||||
a.nonNullField<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.nonNullField.length
|
||||
a.nonNullField = <!NULL_FOR_NONNULL_TYPE!>null<!>
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package
|
||||
|
||||
public fun main(/*0*/ a: A): kotlin.Unit
|
||||
|
||||
@FieldsAreNullable public open class A {
|
||||
public constructor A()
|
||||
public final var field: kotlin.String?
|
||||
@javax.annotation.Nonnull public final var nonNullField: kotlin.String
|
||||
@javax.annotation.Nonnull public open fun bar(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ q: kotlin.String!, /*1*/ @javax.annotation.Nonnull x: kotlin.String, /*2*/ @javax.annotation.CheckForNull 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
|
||||
}
|
||||
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented @javax.annotation.CheckForNull @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.FIELD}) public final annotation class FieldsAreNullable : kotlin.Annotation {
|
||||
public constructor FieldsAreNullable()
|
||||
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
|
||||
}
|
||||
Vendored
+158
@@ -0,0 +1,158 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
// 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.CLASS)
|
||||
@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.CLASS)
|
||||
@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 ""; }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main(a: A, b: B, c: C) {
|
||||
a.foo1(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
a.foo2(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
a.foo3(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
a.bar1(null)<!UNSAFE_CALL!>.<!>length
|
||||
a.bar2(null)<!UNSAFE_CALL!>.<!>length
|
||||
a.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
|
||||
b.foo1(null).length
|
||||
b.foo1(null)?.length
|
||||
b.foo2(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
b.foo3(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
b.bar1(null)<!UNSAFE_CALL!>.<!>length
|
||||
b.bar2(null)<!UNSAFE_CALL!>.<!>length
|
||||
b.baz(null).length
|
||||
b.baz(null)?.length
|
||||
|
||||
c.foo1(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
c.foo2(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
c.foo3(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
c.bar1(null).length
|
||||
c.bar1(null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
c.bar2(null)<!UNSAFE_CALL!>.<!>length
|
||||
c.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
}
|
||||
Vendored
+68
@@ -0,0 +1,68 @@
|
||||
package
|
||||
|
||||
public fun main(/*0*/ a: A, /*1*/ b: B, /*2*/ c: C): kotlin.Unit
|
||||
|
||||
@NonNullApi public open class A {
|
||||
public constructor A()
|
||||
@javax.annotation.Nullable public open fun bar1(/*0*/ @javax.annotation.Nullable x: kotlin.String?): kotlin.String?
|
||||
@javax.annotation.Nullable public open fun bar2(/*0*/ @javax.annotation.Nullable x: kotlin.String?): kotlin.String?
|
||||
public open fun baz(/*0*/ @javax.annotation.Nonnull x: kotlin.String): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo1(/*0*/ x: kotlin.String): kotlin.String
|
||||
public open fun foo2(/*0*/ x: kotlin.String): kotlin.String
|
||||
public open fun foo3(/*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
|
||||
}
|
||||
|
||||
@NonNullApi public interface AInt {
|
||||
@javax.annotation.Nullable public abstract fun bar1(/*0*/ @javax.annotation.Nullable x: kotlin.String?): kotlin.CharSequence?
|
||||
@javax.annotation.Nullable public abstract fun bar2(/*0*/ @javax.annotation.Nullable x: kotlin.String?): kotlin.CharSequence?
|
||||
public abstract fun baz(/*0*/ @javax.annotation.Nonnull x: kotlin.String): kotlin.CharSequence
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo1(/*0*/ x: kotlin.String): kotlin.CharSequence
|
||||
public abstract fun foo2(/*0*/ x: kotlin.String): kotlin.CharSequence
|
||||
public abstract fun foo3(/*0*/ x: kotlin.String): kotlin.CharSequence
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@NullableApi public open class B : A, AInt {
|
||||
public constructor B()
|
||||
public open override /*2*/ fun bar1(/*0*/ x: kotlin.String?): kotlin.String?
|
||||
@javax.annotation.Nullable public open override /*2*/ /*fake_override*/ fun bar2(/*0*/ @javax.annotation.Nullable x: kotlin.String?): kotlin.String?
|
||||
public open override /*2*/ fun baz(/*0*/ x: kotlin.String!): kotlin.String!
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*2*/ fun foo1(/*0*/ x: kotlin.String!): kotlin.String!
|
||||
@javax.annotation.Nonnull public open override /*2*/ fun foo2(/*0*/ @javax.annotation.Nonnull x: kotlin.String): kotlin.String
|
||||
public open override /*2*/ /*fake_override*/ fun foo3(/*0*/ x: kotlin.String): kotlin.String
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@NonNullApi public open class C : A, AInt {
|
||||
public constructor C()
|
||||
public open override /*2*/ fun bar1(/*0*/ x: kotlin.String!): kotlin.String
|
||||
@javax.annotation.Nullable public open override /*2*/ fun bar2(/*0*/ @javax.annotation.Nullable x: kotlin.String?): kotlin.String?
|
||||
public open override /*2*/ fun baz(/*0*/ x: kotlin.String): kotlin.String
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*2*/ fun foo1(/*0*/ x: kotlin.String): kotlin.String
|
||||
public open override /*2*/ fun foo2(/*0*/ @javax.annotation.Nonnull x: kotlin.String): kotlin.String
|
||||
public open override /*2*/ /*fake_override*/ fun foo3(/*0*/ x: kotlin.String): kotlin.String
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.annotation.Target(allowedTargets = {}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented @javax.annotation.Nonnull @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
|
||||
}
|
||||
|
||||
@kotlin.annotation.Target(allowedTargets = {}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented @javax.annotation.CheckForNull @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) public final annotation class NullableApi : kotlin.Annotation {
|
||||
public constructor NullableApi()
|
||||
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
|
||||
}
|
||||
Vendored
+186
@@ -0,0 +1,186 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
// 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.PACKAGE)
|
||||
@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.PACKAGE)
|
||||
@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, @Nonnull 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, @Nullable 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main(a: A, b: A.B, c: A.C) {
|
||||
a.foo("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.foo("", null).length
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
a.foobar(null, "")<!UNSAFE_CALL!>.<!>length
|
||||
a.foobar("", <!NULL_FOR_NONNULL_TYPE!>null<!>)?.length
|
||||
|
||||
a.bar().length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.field.length
|
||||
|
||||
a.baz()<!UNSAFE_CALL!>.<!>get(0)
|
||||
a.baz()!!.get(0).get(0)
|
||||
a.baz()!!.get(0)?.get(0)
|
||||
|
||||
// b
|
||||
b.foo("", <!NULL_FOR_NONNULL_TYPE!>null<!>)?.length
|
||||
b.foo("", <!NULL_FOR_NONNULL_TYPE!>null<!>)<!UNSAFE_CALL!>.<!>length
|
||||
b.foo(null, "")<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
b.foobar(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
b.foobar("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
|
||||
b.bar()<!UNSAFE_CALL!>.<!>length
|
||||
b.bar()!!.length
|
||||
|
||||
b.field?.length
|
||||
b.field<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
b.baz()<!UNSAFE_CALL!>.<!>get(0)
|
||||
b.baz()!!.get(0).get(0)
|
||||
b.baz()!!.get(0)?.get(0)
|
||||
|
||||
// c
|
||||
c.foo("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
c.foo("", null).length
|
||||
c.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
c.foobar(null, "")<!UNSAFE_CALL!>.<!>length
|
||||
c.foobar("", null)?.length
|
||||
|
||||
c.bar().length
|
||||
c.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
c.field?.length
|
||||
c.field<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
c.baz()<!UNSAFE_CALL!>.<!>get(0)
|
||||
c.baz()!!.get(0).get(0)
|
||||
c.baz()!!.get(0)?.get(0)
|
||||
}
|
||||
Vendored
+60
@@ -0,0 +1,60 @@
|
||||
package
|
||||
|
||||
public fun main(/*0*/ a: A, /*1*/ b: A.B, /*2*/ c: A.C): kotlin.Unit
|
||||
|
||||
@NonNullApi public open class A {
|
||||
public constructor A()
|
||||
public final var field: kotlin.String
|
||||
public open fun bar(): kotlin.String
|
||||
@javax.annotation.Nullable public open fun baz(): kotlin.collections.(Mutable)List<kotlin.String!>?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ x: kotlin.String, /*1*/ @javax.annotation.CheckForNull y: kotlin.CharSequence?): kotlin.String
|
||||
@NullableApi public open fun foobar(/*0*/ x: kotlin.String?, /*1*/ @javax.annotation.Nonnull 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
|
||||
|
||||
@NullableApi public open inner class B {
|
||||
public constructor B()
|
||||
public final var field: kotlin.String?
|
||||
public open fun bar(): kotlin.String?
|
||||
@javax.annotation.Nullable public open fun baz(): kotlin.collections.(Mutable)List<kotlin.String!>?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ x: kotlin.String?, /*1*/ @javax.annotation.Nonnull y: kotlin.CharSequence): kotlin.String?
|
||||
@NonNullApi public open fun foobar(/*0*/ x: kotlin.String, /*1*/ @javax.annotation.Nullable 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
|
||||
}
|
||||
|
||||
@FieldsAreNullable public open inner class C {
|
||||
public constructor C()
|
||||
public final var field: kotlin.String?
|
||||
public open fun bar(): kotlin.String
|
||||
@javax.annotation.Nullable public open fun baz(): kotlin.collections.(Mutable)List<kotlin.String!>?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ x: kotlin.String, /*1*/ @javax.annotation.Nullable y: kotlin.CharSequence?): kotlin.String
|
||||
@NullableApi public open fun foobar(/*0*/ x: kotlin.String?, /*1*/ @javax.annotation.Nullable 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
|
||||
}
|
||||
}
|
||||
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented @javax.annotation.CheckForNull @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.FIELD}) public final annotation class FieldsAreNullable : kotlin.Annotation {
|
||||
public constructor FieldsAreNullable()
|
||||
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.Target(allowedTargets = {}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented @javax.annotation.Nonnull @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
|
||||
}
|
||||
|
||||
@kotlin.annotation.Target(allowedTargets = {}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.MustBeDocumented @javax.annotation.CheckForNull @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) public final annotation class NullableApi : kotlin.Annotation {
|
||||
public constructor NullableApi()
|
||||
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
|
||||
}
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// 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 "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main(a: A) {
|
||||
// foo is platform
|
||||
a.foo("", "", null)?.length
|
||||
a.foo("", "", null).length
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
a.bar().length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field?.length
|
||||
a.field<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
package
|
||||
|
||||
public fun main(/*0*/ a: A): kotlin.Unit
|
||||
|
||||
@javax.annotation.ParametersAreNonnullByDefault public open class A {
|
||||
public constructor A()
|
||||
@javax.annotation.Nullable public final var field: kotlin.String?
|
||||
@javax.annotation.Nonnull public open fun bar(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ q: kotlin.String, /*1*/ @javax.annotation.Nonnull x: kotlin.String, /*2*/ @javax.annotation.CheckForNull 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
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// RENDER_PACKAGE: test
|
||||
// RENDER_PACKAGE: test2
|
||||
|
||||
// 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 "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
import test.A
|
||||
import test2.A2
|
||||
|
||||
fun main(a: A, a2: A2) {
|
||||
a.foo("", "", null)?.length
|
||||
a.foo("", "", null).length
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
a.bar().length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field?.length
|
||||
a.field<!UNSAFE_CALL!>.<!>length
|
||||
|
||||
a2.foo("", "", null)?.length
|
||||
a2.foo("", "", null).length
|
||||
a2.foo(null, <!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
a2.bar().length
|
||||
a2.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a2.field?.length
|
||||
a2.field<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package test
|
||||
|
||||
public open class A {
|
||||
public constructor A()
|
||||
@javax.annotation.Nullable public final var field: kotlin.String?
|
||||
@javax.annotation.Nonnull public open fun bar(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ q: kotlin.String, /*1*/ @javax.annotation.Nonnull x: kotlin.String, /*2*/ @javax.annotation.CheckForNull 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
|
||||
}
|
||||
|
||||
package test2
|
||||
|
||||
public open class A2 {
|
||||
public constructor A2()
|
||||
@javax.annotation.Nullable public final var field: kotlin.String?
|
||||
@javax.annotation.Nonnull public open fun bar(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ q: kotlin.String!, /*1*/ @javax.annotation.Nonnull x: kotlin.String, /*2*/ @javax.annotation.CheckForNull 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
|
||||
}
|
||||
|
||||
package
|
||||
|
||||
public fun main(/*0*/ a: test.A, /*1*/ a2: test2.A2): kotlin.Unit
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
// 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.CLASS)
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main(a: A) {
|
||||
a.foo("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.foo("", null).length
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
a.bar().length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field?.length
|
||||
a.field.length
|
||||
|
||||
a.baz()<!UNSAFE_CALL!>.<!>get(0)
|
||||
a.baz()!!.get(0).get(0)
|
||||
a.baz()!!.get(0)?.get(0)
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun main(/*0*/ a: A): kotlin.Unit
|
||||
|
||||
@spr.NonNullApi public open class A {
|
||||
public constructor A()
|
||||
public final var field: kotlin.String!
|
||||
public open fun bar(): kotlin.String
|
||||
@spr.Nullable public open fun baz(): kotlin.collections.(Mutable)List<kotlin.String!>?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ x: kotlin.String, /*1*/ @spr.Nullable 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
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// RENDER_PACKAGE: test
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main(a: test.A) {
|
||||
a.foo("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.foo("", null).length
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
a.bar().length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field?.length
|
||||
a.field.length
|
||||
|
||||
a.baz()<!UNSAFE_CALL!>.<!>get(0)
|
||||
a.baz()!!.get(0).get(0)
|
||||
a.baz()!!.get(0)?.get(0)
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package test
|
||||
|
||||
public open class A {
|
||||
public constructor A()
|
||||
public final var field: kotlin.String!
|
||||
public open fun bar(): kotlin.String
|
||||
@spr.Nullable public open fun baz(): kotlin.collections.(Mutable)List<kotlin.String!>?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ x: kotlin.String, /*1*/ @spr.Nullable 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
|
||||
}
|
||||
|
||||
package
|
||||
|
||||
public fun main(/*0*/ a: test.A): kotlin.Unit
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package 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.MAYBE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CheckForNull {
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package javax.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.annotation.meta.TypeQualifier;
|
||||
import javax.annotation.meta.TypeQualifierValidator;
|
||||
import javax.annotation.meta.When;
|
||||
|
||||
@Documented
|
||||
@TypeQualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Nonnull {
|
||||
When when() default When.ALWAYS;
|
||||
|
||||
static class Checker implements TypeQualifierValidator<Nonnull> {
|
||||
|
||||
public When forConstantValue(Nonnull qualifierqualifierArgument,
|
||||
Object value) {
|
||||
if (value == null)
|
||||
return When.NEVER;
|
||||
return When.ALWAYS;
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package 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 Nullable {
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package javax.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.annotation.meta.TypeQualifierDefault;
|
||||
|
||||
/**
|
||||
* This annotation can be applied to a package, class or method to indicate that
|
||||
* the method parameters in that element are nonnull by default unless there is:
|
||||
* <ul>
|
||||
* <li>An explicit nullness annotation
|
||||
* <li>The method overrides a method in a superclass (in which case the
|
||||
* annotation of the corresponding parameter in the superclass applies)
|
||||
* <li>There is a default parameter annotation (like {@link ParametersAreNullableByDefault})
|
||||
* applied to a more tightly nested element.
|
||||
* </ul>
|
||||
*
|
||||
* @see Nonnull
|
||||
*/
|
||||
@Documented
|
||||
@Nonnull
|
||||
@TypeQualifierDefault(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ParametersAreNonnullByDefault {
|
||||
}
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
package javax.annotation.meta;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* This qualifier is applied to an annotation to denote that the annotation
|
||||
* should be treated as a type qualifier.
|
||||
*/
|
||||
|
||||
@Documented
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TypeQualifier {
|
||||
|
||||
/**
|
||||
* Describes the kinds of values the qualifier can be applied to. If a
|
||||
* numeric class is provided (e.g., Number.class or Integer.class) then the
|
||||
* annotation can also be applied to the corresponding primitive numeric
|
||||
* types.
|
||||
*/
|
||||
Class<?> applicableTo() default Object.class;
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package javax.annotation.meta;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* This qualifier is applied to an annotation to denote that the annotation
|
||||
* defines a default type qualifier that is visible within the scope of the
|
||||
* element it is applied to.
|
||||
*/
|
||||
|
||||
@Documented
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TypeQualifierDefault {
|
||||
ElementType[] value() default {};
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package javax.annotation.meta;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* This annotation is applied to a annotation, and marks the annotation as being
|
||||
* a qualifier nickname. Applying a nickname annotation X to a element Y should
|
||||
* be interpreted as having the same meaning as applying all of annotations of X
|
||||
* (other than QualifierNickname) to Y.
|
||||
*
|
||||
* <p>
|
||||
* Thus, you might define a qualifier SocialSecurityNumber as follows:
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <code>
|
||||
@Documented
|
||||
@TypeQualifierNickname @Pattern("[0-9]{3}-[0-9]{2}-[0-9]{4}")
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SocialSecurityNumber {
|
||||
}
|
||||
</code>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
public @interface TypeQualifierNickname {
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package javax.annotation.meta;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface TypeQualifierValidator<A extends Annotation> {
|
||||
/**
|
||||
* Given a type qualifier, check to see if a known specific constant value
|
||||
* is an instance of the set of values denoted by the qualifier.
|
||||
*
|
||||
* @param annotation
|
||||
* the type qualifier
|
||||
* @param value
|
||||
* the value to check
|
||||
* @return a value indicating whether or not the value is an member of the
|
||||
* values denoted by the type qualifier
|
||||
*/
|
||||
public @Nonnull
|
||||
When forConstantValue(@Nonnull A annotation, Object value);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package javax.annotation.meta;
|
||||
|
||||
/**
|
||||
* Used to describe the relationship between a qualifier T and the set of values
|
||||
* S possible on an annotated element.
|
||||
*
|
||||
* In particular, an issues should be reported if an ALWAYS or MAYBE value is
|
||||
* used where a NEVER value is required, or if a NEVER or MAYBE value is used
|
||||
* where an ALWAYS value is required.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public enum When {
|
||||
/** S is a subset of T */
|
||||
ALWAYS,
|
||||
/** nothing definitive is known about the relation between S and T */
|
||||
UNKNOWN,
|
||||
/** S intersection T is non empty and S - T is nonempty */
|
||||
MAYBE,
|
||||
/** S intersection T is empty */
|
||||
NEVER;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
// 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.CLASS)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Nonnull
|
||||
@TypeQualifierDefault({ElementType.TYPE_USE})
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main(a: A) {
|
||||
a.foo("", null)<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.foo("", null).length
|
||||
a.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>, "").length
|
||||
|
||||
a.bar().length
|
||||
a.bar()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length
|
||||
|
||||
a.field<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||
a.field.length
|
||||
|
||||
a.baz()<!UNSAFE_CALL!>.<!>get(0)
|
||||
a.baz()!!.get(0).get(0)
|
||||
a.baz()!!.get(0)?.get(0)
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public fun main(/*0*/ a: A): kotlin.Unit
|
||||
|
||||
@spr.NonNullApi public open class A {
|
||||
public constructor A()
|
||||
public final var field: kotlin.String
|
||||
public open fun bar(): kotlin.String
|
||||
@spr.Nullable public open fun baz(): kotlin.collections.(Mutable)List<kotlin.String!>?
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ x: kotlin.String, /*1*/ @spr.Nullable 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
|
||||
}
|
||||
@@ -66,6 +66,7 @@ import org.jetbrains.kotlin.test.util.DescriptorValidator
|
||||
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator
|
||||
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.RECURSIVE
|
||||
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.RECURSIVE_ALL
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import org.junit.Assert
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
@@ -363,7 +364,15 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
||||
val comparator = RecursiveDescriptorComparator(createdAffectedPackagesConfiguration(testFiles, modules.values))
|
||||
|
||||
val isMultiModuleTest = modules.size != 1
|
||||
val rootPackageText = StringBuilder()
|
||||
|
||||
val packages =
|
||||
(testFiles.flatMap {
|
||||
InTextDirectivesUtils.findListWithPrefixes(it.expectedText, "// RENDER_PACKAGE:").map {
|
||||
FqName(it.trim())
|
||||
}
|
||||
} + FqName.ROOT).toSet()
|
||||
|
||||
val textByPackage = packages.keysToMap { StringBuilder() }
|
||||
|
||||
val sortedModules = modules.keys.sortedWith(Comparator { x, y ->
|
||||
when {
|
||||
@@ -375,32 +384,37 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
||||
}
|
||||
})
|
||||
|
||||
val module = sortedModules.iterator()
|
||||
while (module.hasNext()) {
|
||||
val moduleDescriptor = modules[module.next()]!!
|
||||
val aPackage = moduleDescriptor.getPackage(FqName.ROOT)
|
||||
assertFalse(aPackage.isEmpty())
|
||||
for ((packageName, packageText) in textByPackage.entries) {
|
||||
val module = sortedModules.iterator()
|
||||
while (module.hasNext()) {
|
||||
val moduleDescriptor = modules[module.next()]!!
|
||||
|
||||
if (isMultiModuleTest) {
|
||||
rootPackageText.append(String.format("// -- Module: %s --\n", moduleDescriptor.name))
|
||||
}
|
||||
val aPackage = moduleDescriptor.getPackage(packageName)
|
||||
assertFalse(aPackage.isEmpty())
|
||||
|
||||
val actualSerialized = comparator.serializeRecursively(aPackage)
|
||||
rootPackageText.append(actualSerialized)
|
||||
if (isMultiModuleTest) {
|
||||
packageText.append(String.format("// -- Module: %s --\n", moduleDescriptor.name))
|
||||
}
|
||||
|
||||
if (isMultiModuleTest && module.hasNext()) {
|
||||
rootPackageText.append("\n\n")
|
||||
val actualSerialized = comparator.serializeRecursively(aPackage)
|
||||
packageText.append(actualSerialized)
|
||||
|
||||
if (isMultiModuleTest && module.hasNext()) {
|
||||
packageText.append("\n\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val lineCount = StringUtil.getLineBreakCount(rootPackageText)
|
||||
val allPackagesText = textByPackage.values.joinToString("\n")
|
||||
|
||||
val lineCount = StringUtil.getLineBreakCount(allPackagesText)
|
||||
assert(lineCount < 1000) {
|
||||
"Rendered descriptors of this test take up $lineCount lines. " +
|
||||
"Please ensure you don't render JRE contents to the .txt file. " +
|
||||
"Such tests are hard to maintain, take long time to execute and are subject to sudden unreviewed changes anyway."
|
||||
}
|
||||
|
||||
KotlinTestUtils.assertEqualsToFile(expectedFile, rootPackageText.toString())
|
||||
KotlinTestUtils.assertEqualsToFile(expectedFile, allPackagesText)
|
||||
}
|
||||
|
||||
private fun createdAffectedPackagesConfiguration(
|
||||
|
||||
+6
@@ -48,6 +48,12 @@ public class ForeignJava8AnnotationsTestGenerated extends AbstractForeignJava8An
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("springNullableWithTypeUse.kt")
|
||||
public void testSpringNullableWithTypeUse() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotationsJava8/tests/springNullableWithTypeUse.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/foreignAnnotationsJava8/tests/typeEnhancement")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -89,4 +89,55 @@ public class ForeignAnnotationsTestGenerated extends AbstractForeignAnnotationsT
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/rxjava.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@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("fieldsAreNullable.kt")
|
||||
public void testFieldsAreNullable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault/fieldsAreNullable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nullabilityFromOverridden.kt")
|
||||
public void testNullabilityFromOverridden() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault/nullabilityFromOverridden.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("overridingDefaultQualifier.kt")
|
||||
public void testOverridingDefaultQualifier() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault/overridingDefaultQualifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("parametersAreNonnullByDefault.kt")
|
||||
public void testParametersAreNonnullByDefault() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault/parametersAreNonnullByDefault.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("parametersAreNonnullByDefaultPackage.kt")
|
||||
public void testParametersAreNonnullByDefaultPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault/parametersAreNonnullByDefaultPackage.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("springNullable.kt")
|
||||
public void testSpringNullable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault/springNullable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("springNullablePackage.kt")
|
||||
public void testSpringNullablePackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/foreignAnnotations/tests/typeQualifierDefault/springNullablePackage.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,10 +68,10 @@ class LoadJavaPackageAnnotationsTest : KtUsefulTestCase() {
|
||||
it.getMemberScope().getContributedClassifier(Name.identifier("A"), NoLookupLocation.FROM_TEST) != null
|
||||
}.let { assertInstanceOf(it, LazyJavaPackageFragment::class.java) }
|
||||
|
||||
val annotation = packageFragmentDescriptor.getPackageAnnotations().findAnnotation(FqName("test.Ann"))
|
||||
val annotation = packageFragmentDescriptor.annotations.findAnnotation(FqName("test.Ann"))
|
||||
assertNotNull(annotation)
|
||||
|
||||
val singleAnnotation = packageFragmentDescriptor.getPackageAnnotations().singleOrNull()
|
||||
val singleAnnotation = packageFragmentDescriptor.annotations.singleOrNull()
|
||||
assertNotNull(singleAnnotation)
|
||||
|
||||
val annotationFqName = singleAnnotation!!.type.constructor.declarationDescriptor?.fqNameSafe
|
||||
|
||||
+56
@@ -20,12 +20,16 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
private val TYPE_QUALIFIER_NICKNAME_FQNAME = FqName("javax.annotation.meta.TypeQualifierNickname")
|
||||
private val TYPE_QUALIFIER_FQNAME = FqName("javax.annotation.meta.TypeQualifier")
|
||||
private val TYPE_QUALIFIER_DEFAULT_FQNAME = FqName("javax.annotation.meta.TypeQualifierDefault")
|
||||
|
||||
class AnnotationTypeQualifierResolver(storageManager: StorageManager) {
|
||||
private val resolvedNicknames =
|
||||
@@ -49,6 +53,58 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager) {
|
||||
|
||||
return resolveTypeQualifierNickname(annotationClass)
|
||||
}
|
||||
|
||||
enum class QualifierApplicabilityType {
|
||||
METHOD_RETURN_TYPE, VALUE_PARAMETER, FIELD, TYPE_USE
|
||||
}
|
||||
|
||||
class TypeQualifierWithApplicability(
|
||||
private val typeQualifier: AnnotationDescriptor,
|
||||
private val applicability: Int
|
||||
) {
|
||||
private fun isApplicableTo(elementType: QualifierApplicabilityType) = (applicability and (1 shl elementType.ordinal)) != 0
|
||||
|
||||
operator fun component1() = typeQualifier
|
||||
operator fun component2() = QualifierApplicabilityType.values().filter(this::isApplicableTo)
|
||||
}
|
||||
|
||||
fun resolveTypeQualifierDefaultAnnotation(annotationDescriptor: AnnotationDescriptor): TypeQualifierWithApplicability? {
|
||||
val typeQualifierDefaultAnnotatedClass =
|
||||
annotationDescriptor.annotationClass?.takeIf { it.annotations.hasAnnotation(TYPE_QUALIFIER_DEFAULT_FQNAME) }
|
||||
?: return null
|
||||
|
||||
val elementTypesMask =
|
||||
annotationDescriptor.annotationClass!!
|
||||
.annotations.findAnnotation(TYPE_QUALIFIER_DEFAULT_FQNAME)!!
|
||||
.allValueArguments
|
||||
.flatMap { (parameter, argument) ->
|
||||
if (parameter.name == JvmAnnotationNames.DEFAULT_ANNOTATION_MEMBER_NAME)
|
||||
argument.mapConstantToQualifierApplicabilityTypes()
|
||||
else
|
||||
emptyList()
|
||||
}
|
||||
.fold(0) { acc: Int, applicabilityType -> acc or (1 shl applicabilityType.ordinal) }
|
||||
|
||||
val typeQualifier =
|
||||
typeQualifierDefaultAnnotatedClass.annotations.firstNotNullResult(this::resolveTypeQualifierAnnotation)
|
||||
?: return null
|
||||
return TypeQualifierWithApplicability(typeQualifier, elementTypesMask)
|
||||
}
|
||||
|
||||
private fun ConstantValue<*>.mapConstantToQualifierApplicabilityTypes(): List<QualifierApplicabilityType> =
|
||||
when (this) {
|
||||
is ArrayValue -> value.flatMap { it.mapConstantToQualifierApplicabilityTypes() }
|
||||
is EnumValue -> listOfNotNull(
|
||||
when (value.name.identifier) {
|
||||
"METHOD" -> QualifierApplicabilityType.METHOD_RETURN_TYPE
|
||||
"FIELD" -> QualifierApplicabilityType.FIELD
|
||||
"PARAMETER" -> QualifierApplicabilityType.VALUE_PARAMETER
|
||||
"TYPE_USE" -> QualifierApplicabilityType.TYPE_USE
|
||||
else -> null
|
||||
}
|
||||
)
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private val ClassDescriptor.isAnnotatedWithTypeQualifier: Boolean
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ class LazyJavaPackageFragmentProvider(
|
||||
components: JavaResolverComponents
|
||||
) : PackageFragmentProvider {
|
||||
|
||||
private val c = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY)
|
||||
private val c = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY) { null }
|
||||
|
||||
private val packageFragments: MemoizedFunctionToNullable<FqName, LazyJavaPackageFragment> =
|
||||
c.storageManager.createMemoizedFunctionWithNullableValues {
|
||||
|
||||
@@ -17,10 +17,8 @@
|
||||
package org.jetbrains.kotlin.load.java.lazy
|
||||
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackagePartProvider
|
||||
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.load.java.AnnotationTypeQualifierResolver
|
||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||
@@ -28,11 +26,14 @@ import org.jetbrains.kotlin.load.java.components.*
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeResolver
|
||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElementFactory
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.JavaTypeQualifiers
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifier
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.SignatureEnhancement
|
||||
import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import java.util.*
|
||||
|
||||
class JavaResolverComponents(
|
||||
val storageManager: StorageManager,
|
||||
@@ -66,10 +67,33 @@ class JavaResolverComponents(
|
||||
)
|
||||
}
|
||||
|
||||
class LazyJavaResolverContext(
|
||||
val components: JavaResolverComponents,
|
||||
val typeParameterResolver: TypeParameterResolver
|
||||
private typealias QualifierByApplicabilityType = EnumMap<AnnotationTypeQualifierResolver.QualifierApplicabilityType, NullabilityQualifier?>
|
||||
|
||||
class JavaTypeQualifiersByElementType(
|
||||
internal val nullabilityQualifiers: QualifierByApplicabilityType
|
||||
) {
|
||||
operator fun get(
|
||||
applicabilityType: AnnotationTypeQualifierResolver.QualifierApplicabilityType
|
||||
): JavaTypeQualifiers? =
|
||||
(
|
||||
nullabilityQualifiers[applicabilityType]
|
||||
?: nullabilityQualifiers[AnnotationTypeQualifierResolver.QualifierApplicabilityType.TYPE_USE]
|
||||
)?.let { JavaTypeQualifiers(it, null, isNotNullTypeParameter = false) }
|
||||
}
|
||||
|
||||
class LazyJavaResolverContext internal constructor(
|
||||
val components: JavaResolverComponents,
|
||||
val typeParameterResolver: TypeParameterResolver,
|
||||
internal val delegateForDefaultTypeQualifiers: Lazy<JavaTypeQualifiersByElementType?>
|
||||
) {
|
||||
constructor(
|
||||
components: JavaResolverComponents,
|
||||
typeParameterResolver: TypeParameterResolver,
|
||||
typeQualifiersComputation: () -> JavaTypeQualifiersByElementType?
|
||||
) : this(components, typeParameterResolver, lazy(LazyThreadSafetyMode.NONE, typeQualifiersComputation))
|
||||
|
||||
val defaultTypeQualifiers: JavaTypeQualifiersByElementType? by delegateForDefaultTypeQualifiers
|
||||
|
||||
val typeResolver = JavaTypeResolver(this, typeParameterResolver)
|
||||
|
||||
val storageManager: StorageManager
|
||||
@@ -80,14 +104,59 @@ class LazyJavaResolverContext(
|
||||
|
||||
fun LazyJavaResolverContext.child(
|
||||
typeParameterResolver: TypeParameterResolver
|
||||
) = LazyJavaResolverContext(components, typeParameterResolver)
|
||||
) = LazyJavaResolverContext(components, typeParameterResolver, delegateForDefaultTypeQualifiers)
|
||||
|
||||
fun LazyJavaResolverContext.computeNewDefaultTypeQualifiers(
|
||||
additionalAnnotations: Annotations
|
||||
): JavaTypeQualifiersByElementType? {
|
||||
val typeQualifierDefaults =
|
||||
additionalAnnotations.mapNotNull(components.annotationTypeQualifierResolver::resolveTypeQualifierDefaultAnnotation)
|
||||
|
||||
if (typeQualifierDefaults.isEmpty()) return defaultTypeQualifiers
|
||||
|
||||
val nullabilityQualifiers =
|
||||
defaultTypeQualifiers?.nullabilityQualifiers?.let(::QualifierByApplicabilityType)
|
||||
?: QualifierByApplicabilityType(AnnotationTypeQualifierResolver.QualifierApplicabilityType::class.java)
|
||||
|
||||
var wasUpdate = false
|
||||
for ((typeQualifier, applicableTo) in typeQualifierDefaults) {
|
||||
val nullability = components.signatureEnhancement.extractNullability(typeQualifier) ?: continue
|
||||
for (applicabilityType in applicableTo) {
|
||||
nullabilityQualifiers[applicabilityType] = nullability
|
||||
wasUpdate = true
|
||||
}
|
||||
}
|
||||
|
||||
return if (!wasUpdate) defaultTypeQualifiers else JavaTypeQualifiersByElementType(nullabilityQualifiers)
|
||||
}
|
||||
|
||||
fun LazyJavaResolverContext.replaceComponents(
|
||||
components: JavaResolverComponents
|
||||
) = LazyJavaResolverContext(components, typeParameterResolver)
|
||||
) = LazyJavaResolverContext(components, typeParameterResolver, delegateForDefaultTypeQualifiers)
|
||||
|
||||
fun LazyJavaResolverContext.child(
|
||||
private fun LazyJavaResolverContext.child(
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
typeParameterOwner: JavaTypeParameterListOwner?,
|
||||
typeParametersIndexOffset: Int = 0,
|
||||
delegateForTypeQualifiers: Lazy<JavaTypeQualifiersByElementType?>
|
||||
) = LazyJavaResolverContext(
|
||||
components,
|
||||
typeParameterOwner?.let { LazyJavaTypeParameterResolver(this, containingDeclaration, it, typeParametersIndexOffset) }
|
||||
?: typeParameterResolver,
|
||||
delegateForTypeQualifiers
|
||||
)
|
||||
|
||||
fun LazyJavaResolverContext.childForMethod(
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
typeParameterOwner: JavaTypeParameterListOwner,
|
||||
typeParametersIndexOffset: Int = 0
|
||||
) = this.child(LazyJavaTypeParameterResolver(this, containingDeclaration, typeParameterOwner, typeParametersIndexOffset))
|
||||
) = child(containingDeclaration, typeParameterOwner, typeParametersIndexOffset, delegateForDefaultTypeQualifiers)
|
||||
|
||||
fun LazyJavaResolverContext.childForClassOrPackage(
|
||||
containingDeclaration: ClassOrPackageFragmentDescriptor,
|
||||
typeParameterOwner: JavaTypeParameterListOwner? = null,
|
||||
typeParametersIndexOffset: Int = 0
|
||||
) = child(
|
||||
containingDeclaration, typeParameterOwner, typeParametersIndexOffset,
|
||||
lazy(LazyThreadSafetyMode.NONE) { computeNewDefaultTypeQualifiers(containingDeclaration.annotations) }
|
||||
)
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.load.java.components.JavaResolverCache
|
||||
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.lazy.child
|
||||
import org.jetbrains.kotlin.load.java.lazy.childForClassOrPackage
|
||||
import org.jetbrains.kotlin.load.java.lazy.replaceComponents
|
||||
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
|
||||
@@ -64,7 +64,7 @@ class LazyJavaClassDescriptor(
|
||||
private val PUBLIC_METHOD_NAMES_IN_OBJECT = setOf("equals", "hashCode", "getClass", "wait", "notify", "notifyAll", "toString")
|
||||
}
|
||||
|
||||
private val c: LazyJavaResolverContext = outerContext.child(this, jClass)
|
||||
private val c: LazyJavaResolverContext = outerContext.childForClassOrPackage(this, jClass)
|
||||
|
||||
init {
|
||||
c.components.javaResolverCache.recordClass(jClass, this)
|
||||
|
||||
+4
-3
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.copyValueParameters
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.lazy.child
|
||||
import org.jetbrains.kotlin.load.java.lazy.childForMethod
|
||||
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaArrayType
|
||||
@@ -86,6 +86,7 @@ class LazyJavaClassMemberScope(
|
||||
}
|
||||
|
||||
c.components.signatureEnhancement.enhanceSignatures(
|
||||
c,
|
||||
result.ifEmpty { listOfNotNull(createDefaultConstructor()) }
|
||||
).toList()
|
||||
}
|
||||
@@ -424,7 +425,7 @@ class LazyJavaClassMemberScope(
|
||||
val getter = DescriptorFactory.createDefaultGetter(propertyDescriptor, Annotations.EMPTY)
|
||||
propertyDescriptor.initialize(getter, null)
|
||||
|
||||
val returnType = givenType ?: computeMethodReturnType(method, annotations, c.child(propertyDescriptor, method))
|
||||
val returnType = givenType ?: computeMethodReturnType(method, annotations, c.childForMethod(propertyDescriptor, method))
|
||||
propertyDescriptor.setType(returnType, listOf(), getDispatchReceiverParameter(), null as KotlinType?)
|
||||
getter.initialize(returnType)
|
||||
|
||||
@@ -511,7 +512,7 @@ class LazyJavaClassMemberScope(
|
||||
)
|
||||
|
||||
|
||||
val c = c.child(constructorDescriptor, constructor, typeParametersIndexOffset = classDescriptor.declaredTypeParameters.size)
|
||||
val c = c.childForMethod(constructorDescriptor, constructor, typeParametersIndexOffset = classDescriptor.declaredTypeParameters.size)
|
||||
val valueParameters = resolveValueParameters(c, constructorDescriptor, constructor.valueParameters)
|
||||
val constructorTypeParameters =
|
||||
classDescriptor.declaredTypeParameters +
|
||||
|
||||
+6
-6
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.lazy.childForClassOrPackage
|
||||
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaPackage
|
||||
@@ -31,9 +32,11 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
|
||||
class LazyJavaPackageFragment(
|
||||
private val c: LazyJavaResolverContext,
|
||||
outerContext: LazyJavaResolverContext,
|
||||
private val jPackage: JavaPackage
|
||||
) : PackageFragmentDescriptorImpl(c.module, jPackage.fqName) {
|
||||
) : PackageFragmentDescriptorImpl(outerContext.module, jPackage.fqName) {
|
||||
private val c = outerContext.childForClassOrPackage(this)
|
||||
|
||||
internal val binaryClasses by c.storageManager.createLazyValue {
|
||||
c.components.packageMapper.findPackageParts(fqName.asString()).mapNotNull { partName ->
|
||||
val classId = ClassId(fqName, Name.identifier(partName))
|
||||
@@ -49,10 +52,7 @@ class LazyJavaPackageFragment(
|
||||
onRecursiveCall = listOf()
|
||||
)
|
||||
|
||||
private val packageAnnotations = c.resolveAnnotations(jPackage)
|
||||
|
||||
// Test only method
|
||||
fun getPackageAnnotations() = packageAnnotations
|
||||
override val annotations = c.resolveAnnotations(jPackage)
|
||||
|
||||
internal fun getSubPackageFqNames(): List<FqName> = subPackages()
|
||||
|
||||
|
||||
+4
-4
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.load.java.components.TypeUsage
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.lazy.child
|
||||
import org.jetbrains.kotlin.load.java.lazy.childForMethod
|
||||
import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations
|
||||
import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeAttributes
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaArrayType
|
||||
@@ -87,7 +87,7 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
|
||||
|
||||
computeNonDeclaredFunctions(result, name)
|
||||
|
||||
c.components.signatureEnhancement.enhanceSignatures(result).toList()
|
||||
c.components.signatureEnhancement.enhanceSignatures(c, result).toList()
|
||||
}
|
||||
|
||||
open protected fun JavaMethodDescriptor.isVisibleAsFunction() = true
|
||||
@@ -114,7 +114,7 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
|
||||
ownerDescriptor, annotations, method.name, c.components.sourceElementFactory.source(method)
|
||||
)
|
||||
|
||||
val c = c.child(functionDescriptorImpl, method)
|
||||
val c = c.childForMethod(functionDescriptorImpl, method)
|
||||
|
||||
val methodTypeParameters = method.typeParameters.map { p -> c.typeParameterResolver.resolveTypeParameter(p)!! }
|
||||
val valueParameters = resolveValueParameters(c, functionDescriptorImpl, method.valueParameters)
|
||||
@@ -246,7 +246,7 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
|
||||
if (DescriptorUtils.isAnnotationClass(ownerDescriptor))
|
||||
properties.toList()
|
||||
else
|
||||
c.components.signatureEnhancement.enhanceSignatures(properties).toList()
|
||||
c.components.signatureEnhancement.enhanceSignatures(c, properties).toList()
|
||||
}
|
||||
|
||||
private fun resolveProperty(field: JavaField): PropertyDescriptor {
|
||||
|
||||
+64
-31
@@ -19,12 +19,17 @@ package org.jetbrains.kotlin.load.java.typeEnhancement
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.annotations.composeAnnotations
|
||||
import org.jetbrains.kotlin.load.java.*
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||
import org.jetbrains.kotlin.load.java.lazy.computeNewDefaultTypeQualifiers
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField
|
||||
import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
|
||||
import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -36,17 +41,40 @@ import org.jetbrains.kotlin.types.asFlexibleType
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.isFlexible
|
||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.util.*
|
||||
|
||||
class SignatureEnhancement(private val annotationTypeQualifierResolver: AnnotationTypeQualifierResolver) {
|
||||
fun <D : CallableMemberDescriptor> enhanceSignatures(platformSignatures: Collection<D>): Collection<D> {
|
||||
|
||||
fun extractNullability(annotationDescriptor: AnnotationDescriptor): NullabilityQualifier? {
|
||||
when (annotationDescriptor.annotationClass?.fqNameSafe) {
|
||||
in NULLABLE_ANNOTATIONS -> return NullabilityQualifier.NULLABLE
|
||||
in NOT_NULL_ANNOTATIONS -> return NullabilityQualifier.NOT_NULL
|
||||
}
|
||||
|
||||
val typeQualifier =
|
||||
annotationTypeQualifierResolver
|
||||
.resolveTypeQualifierAnnotation(annotationDescriptor)
|
||||
?.takeIf { it.annotationClass?.fqNameSafe == JAVAX_NONNULL_ANNOTATION }
|
||||
?: return null
|
||||
|
||||
return typeQualifier.allValueArguments.values.singleOrNull()?.value?.let {
|
||||
enumEntryDescriptor ->
|
||||
if (enumEntryDescriptor !is ClassDescriptor) return@let null
|
||||
if (enumEntryDescriptor.name.asString() == "ALWAYS") NullabilityQualifier.NOT_NULL else NullabilityQualifier.NULLABLE
|
||||
} ?: NullabilityQualifier.NOT_NULL
|
||||
}
|
||||
|
||||
|
||||
fun <D : CallableMemberDescriptor> enhanceSignatures(c: LazyJavaResolverContext, platformSignatures: Collection<D>): Collection<D> {
|
||||
return platformSignatures.map {
|
||||
it.enhanceSignature()
|
||||
it.enhanceSignature(c)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <D : CallableMemberDescriptor> D.enhanceSignature(): D {
|
||||
private fun <D : CallableMemberDescriptor> D.enhanceSignature(c: LazyJavaResolverContext): D {
|
||||
val outerScopeQualifiers = c.computeNewDefaultTypeQualifiers(annotations)
|
||||
// TODO type parameters
|
||||
// TODO use new type parameters while enhancing other types
|
||||
// TODO Propagation into generic type arguments
|
||||
@@ -62,7 +90,10 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
typeContainer =
|
||||
this.safeAs<FunctionDescriptor>()
|
||||
?.getUserData(JavaMethodDescriptor.ORIGINAL_VALUE_PARAMETER_FOR_EXTENSION_RECEIVER),
|
||||
isCovariant = false
|
||||
isCovariant = false,
|
||||
defaultTopLevelQualifiers =
|
||||
outerScopeQualifiers
|
||||
?.get(AnnotationTypeQualifierResolver.QualifierApplicabilityType.VALUE_PARAMETER)
|
||||
) { it.extensionReceiverParameter!!.type }.enhance()
|
||||
else null
|
||||
|
||||
@@ -81,12 +112,28 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
|
||||
val valueParameterEnhancements = valueParameters.map {
|
||||
p ->
|
||||
parts(typeContainer = p, isCovariant = false) { it.valueParameters[p.index].type }
|
||||
parts(
|
||||
typeContainer = p, isCovariant = false,
|
||||
defaultTopLevelQualifiers =
|
||||
outerScopeQualifiers
|
||||
?.get(AnnotationTypeQualifierResolver.QualifierApplicabilityType.VALUE_PARAMETER)
|
||||
) { it.valueParameters[p.index].type }
|
||||
.enhance(predefinedEnhancementInfo?.parametersInfo?.getOrNull(p.index))
|
||||
}
|
||||
|
||||
val returnTypeEnhancement =
|
||||
parts(typeContainer = this, isCovariant = true) { it.returnType!! }.enhance(predefinedEnhancementInfo?.returnTypeInfo)
|
||||
parts(
|
||||
typeContainer = this, isCovariant = true,
|
||||
defaultTopLevelQualifiers =
|
||||
outerScopeQualifiers?.get(
|
||||
if (this.safeAs<PropertyDescriptor>()?.isJavaField == true)
|
||||
AnnotationTypeQualifierResolver.QualifierApplicabilityType.FIELD
|
||||
else
|
||||
AnnotationTypeQualifierResolver.QualifierApplicabilityType.METHOD_RETURN_TYPE
|
||||
)
|
||||
|
||||
|
||||
) { it.returnType!! }.enhance(predefinedEnhancementInfo?.returnTypeInfo)
|
||||
|
||||
if ((receiverTypeEnhancement?.wereChanges ?: false)
|
||||
|| returnTypeEnhancement.wereChanges || valueParameterEnhancements.any { it.wereChanges }) {
|
||||
@@ -101,7 +148,8 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
private val typeContainer: Annotated?,
|
||||
private val fromOverride: KotlinType,
|
||||
private val fromOverridden: Collection<KotlinType>,
|
||||
private val isCovariant: Boolean
|
||||
private val isCovariant: Boolean,
|
||||
private val defaultTopLevelQualifiers: JavaTypeQualifiers?
|
||||
) {
|
||||
fun enhance(predefined: TypeEnhancementInfo? = null): PartEnhancementResult {
|
||||
val qualifiers = computeIndexedQualifiersForOverride()
|
||||
@@ -152,7 +200,10 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
|
||||
fun <T: Any> uniqueNotNull(x: T?, y: T?) = if (x == null || y == null || x == y) x ?: y else null
|
||||
|
||||
val nullability = composedAnnotation.extractNullability()
|
||||
val defaultTypeQualifier = defaultTopLevelQualifiers?.takeIf { isHeadTypeConstructor }
|
||||
val nullability =
|
||||
composedAnnotation.extractNullability()
|
||||
?: defaultTypeQualifier?.nullability
|
||||
|
||||
return JavaTypeQualifiers(
|
||||
nullability,
|
||||
@@ -168,28 +219,8 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
)
|
||||
}
|
||||
|
||||
private fun Annotations.extractNullability(): NullabilityQualifier? {
|
||||
for (annotationDescriptor in this) {
|
||||
when (annotationDescriptor.annotationClass?.fqNameSafe) {
|
||||
in NULLABLE_ANNOTATIONS -> return NullabilityQualifier.NULLABLE
|
||||
in NOT_NULL_ANNOTATIONS -> return NullabilityQualifier.NOT_NULL
|
||||
}
|
||||
|
||||
val typeQualifier =
|
||||
annotationTypeQualifierResolver
|
||||
.resolveTypeQualifierAnnotation(annotationDescriptor)
|
||||
?.takeIf { it.annotationClass?.fqNameSafe == JAVAX_NONNULL_ANNOTATION }
|
||||
?: continue
|
||||
|
||||
return typeQualifier.allValueArguments.values.singleOrNull()?.value?.let {
|
||||
enumEntryDescriptor ->
|
||||
if (enumEntryDescriptor !is ClassDescriptor) return@let null
|
||||
if (enumEntryDescriptor.name.asString() == "ALWAYS") NullabilityQualifier.NOT_NULL else NullabilityQualifier.NULLABLE
|
||||
} ?: NullabilityQualifier.NOT_NULL
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
private fun Annotations.extractNullability(): NullabilityQualifier? =
|
||||
this.firstNotNullResult(this@SignatureEnhancement::extractNullability)
|
||||
|
||||
private fun computeIndexedQualifiersForOverride(): (Int) -> JavaTypeQualifiers {
|
||||
fun KotlinType.toIndexed(): List<KotlinType> {
|
||||
@@ -292,6 +323,7 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
private fun <D : CallableMemberDescriptor> D.parts(
|
||||
typeContainer: Annotated?,
|
||||
isCovariant: Boolean,
|
||||
defaultTopLevelQualifiers: JavaTypeQualifiers?,
|
||||
collector: (D) -> KotlinType
|
||||
): SignatureParts {
|
||||
return SignatureParts(
|
||||
@@ -301,7 +333,8 @@ class SignatureEnhancement(private val annotationTypeQualifierResolver: Annotati
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
collector(it as D)
|
||||
},
|
||||
isCovariant
|
||||
isCovariant,
|
||||
defaultTopLevelQualifiers
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ public class JdkAndMockLibraryProjectDescriptor extends KotlinLightProjectDescri
|
||||
File libraryJar =
|
||||
isJsLibrary
|
||||
? MockLibraryUtil.compileJsLibraryToJar(sourcesPath, LIBRARY_NAME, withSources)
|
||||
: MockLibraryUtil.compileJvmLibraryToJar(sourcesPath, LIBRARY_NAME, withSources, extraOptions, classpath);
|
||||
: MockLibraryUtil.compileJvmLibraryToJar(sourcesPath, LIBRARY_NAME, withSources, true, extraOptions, classpath);
|
||||
String jarUrl = getJarUrl(libraryJar);
|
||||
|
||||
Library.ModifiableModel libraryModel = model.getModuleLibraryTable().getModifiableModel().createLibrary(LIBRARY_NAME).getModifiableModel();
|
||||
|
||||
Reference in New Issue
Block a user