From 3d29b311773163cdf805e4afb6a3469c0f5404d1 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 4 Mar 2019 17:24:40 +0300 Subject: [PATCH] FIR type enhancements: handle class qualifiers, add new JSR 305 tests Related to KT-29937 --- .../java/scopes/JavaClassEnhancementScope.kt | 2 +- .../FieldsAreNullable.fir.txt | 16 +++ .../FieldsAreNullable.java | 39 ++++++ .../ForceFlexibility.fir.txt | 14 ++ .../ForceFlexibility.java | 99 +++++++++++++ .../ForceFlexibleOverOverrides.fir.txt | 26 ++++ .../ForceFlexibleOverOverrides.java | 82 +++++++++++ .../NullabilityFromOverridden.fir.txt | 54 ++++++++ .../NullabilityFromOverridden.java | 131 ++++++++++++++++++ .../OverridingDefaultQualifier.fir.txt | 20 +++ .../OverridingDefaultQualifier.java | 128 +++++++++++++++++ .../ParametersAreNonnullByDefault.fir.txt | 10 ++ .../ParametersAreNonnullByDefault.java | 20 +++ ...rametersAreNonnullByDefaultPackage.fir.txt | 20 +++ .../ParametersAreNonnullByDefaultPackage.java | 45 ++++++ .../SpringNullable.fir.txt | 16 +++ .../typeQualifierDefault/SpringNullable.java | 65 +++++++++ .../SpringNullablePackage.fir.txt | 16 +++ .../SpringNullablePackage.java | 71 ++++++++++ .../OwnFirTypeEnhancementTestGenerated.java | 58 ++++++++ 20 files changed, 931 insertions(+), 1 deletion(-) create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/FieldsAreNullable.fir.txt create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/FieldsAreNullable.java create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibility.fir.txt create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibility.java create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibleOverOverrides.fir.txt create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibleOverOverrides.java create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/NullabilityFromOverridden.fir.txt create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/NullabilityFromOverridden.java create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/OverridingDefaultQualifier.fir.txt create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/OverridingDefaultQualifier.java create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefault.fir.txt create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefault.java create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefaultPackage.fir.txt create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefaultPackage.java create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullable.fir.txt create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullable.java create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullablePackage.fir.txt create mode 100644 compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullablePackage.java diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt index 3941edb0d05..d910bea52ad 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassEnhancementScope.kt @@ -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() diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/FieldsAreNullable.fir.txt b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/FieldsAreNullable.fir.txt new file mode 100644 index 00000000000..126f86d4607 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/FieldsAreNullable.fir.txt @@ -0,0 +1,16 @@ +@R|FieldsAreNullable|() public open class A : R|java/lang/Object| { + public open property field(var): R|ft|? + public get(): R|ft|? + public set(value: R|ft|?): kotlin/Unit + + @R|javax/annotation/Nonnull|() public open property nonNullField(var): R|ft| + public get(): R|ft| + public set(value: R|ft|): kotlin/Unit + + public open operator function foo(q: R|ft|!, @R|javax/annotation/Nonnull|() x: R|ft|, @R|javax/annotation/CheckForNull|() y: R|ft|?): R|ft|! + + @R|javax/annotation/Nonnull|() public open operator function bar(): R|ft| + +} +@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|((R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class FieldsAreNullable : R|java/lang/annotation/Annotation| { +} diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/FieldsAreNullable.java b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/FieldsAreNullable.java new file mode 100644 index 00000000000..963086370a4 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/FieldsAreNullable.java @@ -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 ""; + } +} + diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibility.fir.txt b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibility.fir.txt new file mode 100644 index 00000000000..0586d7cab86 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibility.fir.txt @@ -0,0 +1,14 @@ +@R|spr/NonNullApi|() public open class A : R|java/lang/Object| { + public open operator function foo(x: R|ft|, @R|spr/Nullable|() y: R|ft|?): R|ft| + + @R|spr/ForceFlexibility|() public open operator function bar(x: R|ft|!, @R|javax/annotation/Nonnull|() y: R|ft|): R|ft|! + +} +@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|((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|((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|((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| { +} diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibility.java b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibility.java new file mode 100644 index 00000000000..23e1fb2c10d --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibility.java @@ -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 ""; + } +} + diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibleOverOverrides.fir.txt b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibleOverOverrides.fir.txt new file mode 100644 index 00000000000..386398045a6 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibleOverOverrides.fir.txt @@ -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|): R|kotlin/Unit| + + public open operator function bar(@R|spr/ForceFlexibility|() x: R|ft|): R|kotlin/Unit| + + public open operator function baz(@R|spr/UnknownNullability|() x: R|ft|): R|kotlin/Unit| + + public open operator function foobar(@R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) x: R|ft|!): R|kotlin/Unit| + +} +public abstract interface B : R|java/lang/Object| { + public abstract operator function foo(@R|javax/annotation/Nonnull|() x: R|ft|): R|kotlin/Unit| + + public abstract operator function bar(@R|javax/annotation/Nonnull|() x: R|ft|): R|kotlin/Unit| + + public abstract operator function baz(@R|javax/annotation/Nonnull|() x: R|ft|): R|kotlin/Unit| + + public abstract operator function foobar(@R|javax/annotation/Nonnull|() x: R|ft|): 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|((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|((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| { +} diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibleOverOverrides.java b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibleOverOverrides.java new file mode 100644 index 00000000000..4c424e66a6f --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ForceFlexibleOverOverrides.java @@ -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) {} +} + diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/NullabilityFromOverridden.fir.txt b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/NullabilityFromOverridden.fir.txt new file mode 100644 index 00000000000..0208d8f98f8 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/NullabilityFromOverridden.fir.txt @@ -0,0 +1,54 @@ +@R|NonNullApi|() public open class A : R|java/lang/Object| { + public open operator function foo1(x: R|ft|): R|ft| + + public open operator function foo2(x: R|ft|): R|ft| + + public open operator function foo3(x: R|ft|): R|ft| + + @R|javax/annotation/Nullable|() public open operator function bar1(@R|javax/annotation/Nullable|() x: R|ft|?): R|ft|? + + @R|javax/annotation/Nullable|() public open operator function bar2(@R|javax/annotation/Nullable|() x: R|ft|?): R|ft|? + + public open operator function baz(@R|javax/annotation/Nonnull|() x: R|ft|): R|ft| + +} +@R|NonNullApi|() public abstract interface AInt : R|java/lang/Object| { + public abstract operator function foo1(x: R|ft|): R|ft| + + public abstract operator function foo2(x: R|ft|): R|ft| + + public abstract operator function foo3(x: R|ft|): R|ft| + + @R|javax/annotation/Nullable|() public abstract operator function bar1(@R|javax/annotation/Nullable|() x: R|ft|?): R|ft|? + + @R|javax/annotation/Nullable|() public abstract operator function bar2(@R|javax/annotation/Nullable|() x: R|ft|?): R|ft|? + + public abstract operator function baz(@R|javax/annotation/Nonnull|() x: R|ft|): R|ft| + +} +@R|NullableApi|() public open class B : R|A|, R|AInt| { + public open operator function foo1(x: R|ft|): R|ft| + + @R|javax/annotation/Nonnull|() public open operator function foo2(@R|javax/annotation/Nonnull|() x: R|ft|): R|ft| + + public open operator function bar1(x: R|ft|?): R|ft|? + + public open operator function baz(x: R|ft|): R|ft| + +} +@R|NonNullApi|() public open class C : R|A|, R|AInt| { + public open operator function foo1(x: R|ft|): R|ft| + + public open operator function foo2(@R|javax/annotation/Nonnull|() x: R|ft|): R|ft| + + public open operator function bar1(x: R|ft|?): R|ft|? + + @R|javax/annotation/Nullable|() public open operator function bar2(@R|javax/annotation/Nullable|() x: R|ft|?): R|ft|? + + public open operator function baz(x: R|ft|): R|ft| + +} +@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|((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|((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| { +} diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/NullabilityFromOverridden.java b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/NullabilityFromOverridden.java new file mode 100644 index 00000000000..5681ebbed19 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/NullabilityFromOverridden.java @@ -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 ""; } +} + diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/OverridingDefaultQualifier.fir.txt b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/OverridingDefaultQualifier.fir.txt new file mode 100644 index 00000000000..0d8c3d8745e --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/OverridingDefaultQualifier.fir.txt @@ -0,0 +1,20 @@ +@R|NonNullApi|() public open class A : R|java/lang/Object| { + public open property field(var): R|ft| + public get(): R|ft| + public set(value: R|ft|): kotlin/Unit + + public open operator function foo(x: R|ft|, @R|javax/annotation/CheckForNull|() y: R|ft|?): R|ft| + + @R|NullableApi|() public open operator function foobar(x: R|ft|?, @R|NonNullApi|() y: R|ft|): R|ft|? + + public open operator function bar(): R|ft| + + @R|javax/annotation/Nullable|() public open operator function baz(): R|ft>?, kotlin/collections/List>?>|? + +} +@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|((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|((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|((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| { +} diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/OverridingDefaultQualifier.java b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/OverridingDefaultQualifier.java new file mode 100644 index 00000000000..07019c8ab4a --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/OverridingDefaultQualifier.java @@ -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 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 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 baz() { + return null; + } + } +} + diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefault.fir.txt b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefault.fir.txt new file mode 100644 index 00000000000..bc0206bf785 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefault.fir.txt @@ -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|? + public get(): R|ft|? + public set(value: R|ft|?): kotlin/Unit + + public open operator function foo(q: R|ft|, @R|javax/annotation/Nonnull|() x: R|ft|, @R|javax/annotation/CheckForNull|() y: R|ft|?): R|ft|! + + @R|javax/annotation/Nonnull|() public open operator function bar(): R|ft| + +} diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefault.java b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefault.java new file mode 100644 index 00000000000..016e36a6483 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefault.java @@ -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 ""; + } +} + diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefaultPackage.fir.txt b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefaultPackage.fir.txt new file mode 100644 index 00000000000..009ddb12340 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefaultPackage.fir.txt @@ -0,0 +1,20 @@ +public open class A : R|java/lang/Object| { + @R|javax/annotation/Nullable|() public open property field(var): R|ft|? + public get(): R|ft|? + public set(value: R|ft|?): kotlin/Unit + + public open operator function foo(q: R|ft|!, @R|javax/annotation/Nonnull|() x: R|ft|, @R|javax/annotation/CheckForNull|() y: R|ft|?): R|ft|! + + @R|javax/annotation/Nonnull|() public open operator function bar(): R|ft| + +} +public open class A2 : R|java/lang/Object| { + @R|javax/annotation/Nullable|() public open property field(var): R|ft|? + public get(): R|ft|? + public set(value: R|ft|?): kotlin/Unit + + public open operator function foo(q: R|ft|!, @R|javax/annotation/Nonnull|() x: R|ft|, @R|javax/annotation/CheckForNull|() y: R|ft|?): R|ft|! + + @R|javax/annotation/Nonnull|() public open operator function bar(): R|ft| + +} diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefaultPackage.java b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefaultPackage.java new file mode 100644 index 00000000000..ec0c06487f4 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/ParametersAreNonnullByDefaultPackage.java @@ -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 ""; + } +} + diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullable.fir.txt b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullable.fir.txt new file mode 100644 index 00000000000..c656893aee9 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullable.fir.txt @@ -0,0 +1,16 @@ +@R|spr/NonNullApi|() public open class A : R|java/lang/Object| { + public open property field(var): R|ft|! + public get(): R|ft|! + public set(value: R|ft|!): kotlin/Unit + + public open operator function foo(x: R|ft|, @R|spr/Nullable|() y: R|ft|?): R|ft| + + public open operator function bar(): R|ft| + + @R|spr/Nullable|() public open operator function baz(): R|ft>?, kotlin/collections/List>?>|? + +} +@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|((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|((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| { +} diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullable.java b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullable.java new file mode 100644 index 00000000000..83139b4dcc4 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullable.java @@ -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 baz() { + return null; + } +} + diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullablePackage.fir.txt b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullablePackage.fir.txt new file mode 100644 index 00000000000..94a8568e979 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullablePackage.fir.txt @@ -0,0 +1,16 @@ +public open class A : R|java/lang/Object| { + public open property field(var): R|ft|! + public get(): R|ft|! + public set(value: R|ft|!): kotlin/Unit + + public open operator function foo(x: R|ft|!, @R|spr/Nullable|() y: R|ft|?): R|ft|! + + public open operator function bar(): R|ft|! + + @R|spr/Nullable|() public open operator function baz(): R|ft>?, kotlin/collections/List>?>|? + +} +@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|((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|((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| { +} diff --git a/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullablePackage.java b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullablePackage.java new file mode 100644 index 00000000000..3f0ce8c5826 --- /dev/null +++ b/compiler/fir/resolve/testData/enhancement/jsr305/typeQualifierDefault/SpringNullablePackage.java @@ -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 baz() { + return null; + } +} + diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/OwnFirTypeEnhancementTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/OwnFirTypeEnhancementTestGenerated.java index fa74832b781..c6a4a2e43da 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/OwnFirTypeEnhancementTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/OwnFirTypeEnhancementTestGenerated.java @@ -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"); + } + } } }