diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt index 46a548bd6dd..097ed4e5f1d 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/frontend/java/di/injection.kt @@ -137,6 +137,7 @@ fun StorageComponentContainer.configureJavaSpecificComponents( JavaResolverSettings.create( isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines), correctNullabilityForNotNullTypeParameter = languageVersionSettings.supportsFeature(LanguageFeature.ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated), + enhancementImprovements = languageVersionSettings.supportsFeature(LanguageFeature.ImprovementsAroundTypeEnhancement), ) ) diff --git a/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.java b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.java index c363b13d82c..d29ce251dc7 100644 --- a/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.java +++ b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.java @@ -1,4 +1,4 @@ -// JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic_DisabledImprovements.java b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic_DisabledImprovements.java new file mode 100644 index 00000000000..20ae7c5392d --- /dev/null +++ b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic_DisabledImprovements.java @@ -0,0 +1,19 @@ +// !LANGUAGE: -ImprovementsAroundTypeEnhancement + +package test; + +import org.jetbrains.annotations.*; + +public class Basic_DisabledImprovements { + public interface G<@NotNull T> { + <@NotNull R> void foo(R r); + } + + public interface G1 { + void foo(R r); + } + + void foo(R r) { + + } +} diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/BaseClassTypeArguments.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/BaseClassTypeArguments.java index 27c4dff6bba..728df19f7de 100644 --- a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/BaseClassTypeArguments.java +++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/BaseClassTypeArguments.java @@ -1,4 +1,4 @@ -// JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.java index 8759772b49e..d559293052e 100644 --- a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.java +++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.java @@ -1,4 +1,4 @@ -// JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic_DisabledImprovements.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic_DisabledImprovements.java new file mode 100644 index 00000000000..feafd88d327 --- /dev/null +++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic_DisabledImprovements.java @@ -0,0 +1,30 @@ +// !LANGUAGE: -ImprovementsAroundTypeEnhancement + +package test; + +import org.jetbrains.annotations.*; + +public class Basic_DisabledImprovements { + interface G extends G2<@NotNull T, @NotNull String> { } + + interface G2 { } + + static class A { + class B {} + } + + public interface MyClass { + void f1(G<@NotNull String> p); + G2<@Nullable String, @NotNull Integer> f2(); + void f3(@NotNull T x); + void f4(G<@NotNull String @Nullable []> p); + void f5(G<@NotNull ?> p); + void f6(G<@NotNull ? extends @Nullable Object> p); + void f7(G<@NotNull A.B> p); + G> f81(); + G> f9(); + > void f10(T p); + } + + Basic_DisabledImprovements(G<@NotNull String> p) { } +} \ No newline at end of file diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic_DisabledImprovements.txt b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic_DisabledImprovements.txt new file mode 100644 index 00000000000..f75974d7c03 --- /dev/null +++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic_DisabledImprovements.txt @@ -0,0 +1,32 @@ +package test + +public open class Basic_DisabledImprovements { + public/*package*/ constructor Basic_DisabledImprovements(/*0*/ p0: test.Basic_DisabledImprovements.G<@org.jetbrains.annotations.NotNull kotlin.String!>!) + + public/*package*/ open class A { + public/*package*/ constructor A() + + public/*package*/ open inner class B { + public/*package*/ constructor B() + } + } + + public/*package*/ interface G : test.Basic_DisabledImprovements.G2<@org.jetbrains.annotations.NotNull T!, @org.jetbrains.annotations.NotNull kotlin.String!> { + } + + public/*package*/ interface G2 { + } + + public interface MyClass { + public abstract fun f1(/*0*/ p0: test.Basic_DisabledImprovements.G<@org.jetbrains.annotations.NotNull kotlin.String!>!): kotlin.Unit + public abstract fun !>!> f10(/*0*/ p0: T!): kotlin.Unit + public abstract fun f2(): test.Basic_DisabledImprovements.G2<@org.jetbrains.annotations.Nullable kotlin.String!, @org.jetbrains.annotations.NotNull kotlin.Int!>! + public abstract fun f3(/*0*/ @org.jetbrains.annotations.NotNull p0: @org.jetbrains.annotations.NotNull T): kotlin.Unit + public abstract fun f4(/*0*/ p0: test.Basic_DisabledImprovements.G<(@org.jetbrains.annotations.Nullable kotlin.Array<@org.jetbrains.annotations.NotNull kotlin.String!>..@org.jetbrains.annotations.Nullable kotlin.Array?)>!): kotlin.Unit + public abstract fun f5(/*0*/ p0: test.Basic_DisabledImprovements.G<*>!): kotlin.Unit + public abstract fun f6(/*0*/ p0: test.Basic_DisabledImprovements.G!): kotlin.Unit + public abstract fun f7(/*0*/ p0: test.Basic_DisabledImprovements.G<@org.jetbrains.annotations.NotNull test.Basic_DisabledImprovements.A.B<*, *>!>!): kotlin.Unit + public abstract fun f81(): test.Basic_DisabledImprovements.G<@org.jetbrains.annotations.Nullable test.Basic_DisabledImprovements.A.B<*, *>!>! + public abstract fun f9(): test.Basic_DisabledImprovements.G<@org.jetbrains.annotations.Nullable test.Basic_DisabledImprovements.A.B<*, *>!>! + } +} diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterBounds.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterBounds.java index 1d6c9fadcec..6bfe9356db4 100644 --- a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterBounds.java +++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterBounds.java @@ -1,4 +1,4 @@ -// JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/MethodReceiver.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/MethodReceiver.java index 2a43d23c233..161d317072b 100644 --- a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/MethodReceiver.java +++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/MethodReceiver.java @@ -1,4 +1,4 @@ -// JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/MethodTypeParameterBounds.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/MethodTypeParameterBounds.java index 16b4632069b..64f434238dd 100644 --- a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/MethodTypeParameterBounds.java +++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/MethodTypeParameterBounds.java @@ -1,4 +1,4 @@ -// JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.java index bad8d817886..2e5e08f05d4 100644 --- a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.java +++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.java @@ -1,4 +1,4 @@ -// JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.java index 7f4944a269a..b45426a7e59 100644 --- a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.java +++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.java @@ -1,3 +1,5 @@ +// !LANGUAGE: +ImprovementsAroundTypeEnhancement + package test; import org.jetbrains.annotations.*; diff --git a/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.java b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.java index c363b13d82c..d29ce251dc7 100644 --- a/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.java +++ b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.java @@ -1,4 +1,4 @@ -// JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic_DisabledImprovements.java b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic_DisabledImprovements.java new file mode 100644 index 00000000000..3aa3ae514db --- /dev/null +++ b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic_DisabledImprovements.java @@ -0,0 +1,19 @@ +// !LANGUAGE: + +package test; + +import org.jetbrains.annotations.*; + +public class Basic_DisabledImprovements { + public interface G<@NotNull T> { + <@NotNull R> void foo(R r); + } + + public interface G1 { + void foo(R r); + } + + void foo(R r) { + + } +} diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/BaseClassTypeArguments.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/BaseClassTypeArguments.java index 27c4dff6bba..f4285d227e0 100644 --- a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/BaseClassTypeArguments.java +++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/BaseClassTypeArguments.java @@ -1,4 +1,5 @@ // JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.java index 8759772b49e..6d00a4e6999 100644 --- a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.java +++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.java @@ -1,4 +1,5 @@ // JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic_DisabledImprovements.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic_DisabledImprovements.java new file mode 100644 index 00000000000..feafd88d327 --- /dev/null +++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic_DisabledImprovements.java @@ -0,0 +1,30 @@ +// !LANGUAGE: -ImprovementsAroundTypeEnhancement + +package test; + +import org.jetbrains.annotations.*; + +public class Basic_DisabledImprovements { + interface G extends G2<@NotNull T, @NotNull String> { } + + interface G2 { } + + static class A { + class B {} + } + + public interface MyClass { + void f1(G<@NotNull String> p); + G2<@Nullable String, @NotNull Integer> f2(); + void f3(@NotNull T x); + void f4(G<@NotNull String @Nullable []> p); + void f5(G<@NotNull ?> p); + void f6(G<@NotNull ? extends @Nullable Object> p); + void f7(G<@NotNull A.B> p); + G> f81(); + G> f9(); + > void f10(T p); + } + + Basic_DisabledImprovements(G<@NotNull String> p) { } +} \ No newline at end of file diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic_DisabledImprovements.txt b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic_DisabledImprovements.txt new file mode 100644 index 00000000000..2ce1a78b2fb --- /dev/null +++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic_DisabledImprovements.txt @@ -0,0 +1,32 @@ +package test + +public open class Basic_DisabledImprovements { + public/*package*/ constructor Basic_DisabledImprovements(/*0*/ p: test.Basic_DisabledImprovements.G<@org.jetbrains.annotations.NotNull kotlin.String>!) + + public/*package*/ open class A { + public/*package*/ constructor A() + + public/*package*/ open inner class B { + public/*package*/ constructor B() + } + } + + public/*package*/ interface G : test.Basic_DisabledImprovements.G2<@org.jetbrains.annotations.NotNull T!, @org.jetbrains.annotations.NotNull kotlin.String!> { + } + + public/*package*/ interface G2 { + } + + public interface MyClass { + public abstract fun f1(/*0*/ p: test.Basic_DisabledImprovements.G<@org.jetbrains.annotations.NotNull kotlin.String>!): kotlin.Unit + public abstract fun !>!> f10(/*0*/ p: T!): kotlin.Unit + public abstract fun f2(): test.Basic_DisabledImprovements.G2<@org.jetbrains.annotations.Nullable kotlin.String?, @org.jetbrains.annotations.NotNull kotlin.Int>! + public abstract fun f3(/*0*/ @org.jetbrains.annotations.NotNull x: @org.jetbrains.annotations.NotNull T): kotlin.Unit + public abstract fun f4(/*0*/ p: test.Basic_DisabledImprovements.G<(@org.jetbrains.annotations.Nullable kotlin.Array<@org.jetbrains.annotations.NotNull kotlin.String!>..@org.jetbrains.annotations.Nullable kotlin.Array?)>!): kotlin.Unit + public abstract fun f5(/*0*/ p: test.Basic_DisabledImprovements.G<*>!): kotlin.Unit + public abstract fun f6(/*0*/ p: test.Basic_DisabledImprovements.G!): kotlin.Unit + public abstract fun f7(/*0*/ p: test.Basic_DisabledImprovements.G<@org.jetbrains.annotations.NotNull test.Basic_DisabledImprovements.A.B<*, *>>!): kotlin.Unit + public abstract fun f8(): test.Basic_DisabledImprovements.G!>! + public abstract fun f9(): test.Basic_DisabledImprovements.G<@org.jetbrains.annotations.Nullable test.Basic_DisabledImprovements.A.B<*, *>?>! + } +} diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterBounds.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterBounds.java index 1d6c9fadcec..481ba161f41 100644 --- a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterBounds.java +++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterBounds.java @@ -1,4 +1,5 @@ // JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/MethodReceiver.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/MethodReceiver.java index 2a43d23c233..891b7e09934 100644 --- a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/MethodReceiver.java +++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/MethodReceiver.java @@ -1,4 +1,5 @@ // JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/MethodTypeParameterBounds.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/MethodTypeParameterBounds.java index 16b4632069b..ecb6524dade 100644 --- a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/MethodTypeParameterBounds.java +++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/MethodTypeParameterBounds.java @@ -1,4 +1,5 @@ // JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.java index bad8d817886..0ebea85fe4e 100644 --- a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.java +++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.java @@ -1,4 +1,5 @@ // JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.java index bcf47a05bc3..63335caaa14 100644 --- a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.java +++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.java @@ -1,4 +1,5 @@ // JAVAC_EXPECTED_FILE +// !LANGUAGE: +ImprovementsAroundTypeEnhancement package test; diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java index 3e7d9b8e59e..65efa2b6b6a 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java @@ -41,6 +41,7 @@ import java.io.IOException; import java.util.*; import java.util.regex.Pattern; +import static org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettingsKt.parseLanguageVersionSettings; import static org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil.*; import static org.jetbrains.kotlin.test.KotlinTestUtils.compileKotlinWithJava; import static org.jetbrains.kotlin.test.KotlinTestUtils.newConfiguration; @@ -85,7 +86,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { List javaSources = FileUtil.findFilesByMask(Pattern.compile(".+\\.java"), sourcesDir); Pair binaryPackageAndContext = compileJavaAndLoadTestPackageAndBindingContextFromBinary( - javaSources, tmpdir, ConfigurationKind.JDK_ONLY + javaSources, tmpdir, ConfigurationKind.JDK_ONLY, null ); checkJavaPackage(expectedFile, binaryPackageAndContext.first, binaryPackageAndContext.second, COMPARATOR_CONFIGURATION); @@ -175,7 +176,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { public static void updateConfigurationWithDirectives(String content, CompilerConfiguration configuration) { Directives directives = KotlinTestUtils.parseDirectives(content); - LanguageVersionSettings languageVersionSettings = CompilerTestLanguageVersionSettingsKt.parseLanguageVersionSettings(directives); + LanguageVersionSettings languageVersionSettings = parseLanguageVersionSettings(directives); if (languageVersionSettings == null) { languageVersionSettings = CompilerTestLanguageVersionSettingsKt.defaultLanguageVersionSettings(); } @@ -274,9 +275,12 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { assertTrue(testPackageDir.mkdir()); FileUtil.copy(originalJavaFile, new File(testPackageDir, originalJavaFile.getName())); + Directives directives = KotlinTestUtils.parseDirectives(FileUtil.loadFile(originalJavaFile)); + LanguageVersionSettings languageVersionSettings = parseLanguageVersionSettings(directives); + Pair javaPackageAndContext = loadTestPackageAndBindingContextFromJavaRoot( tmpdir, getTestRootDisposable(), getJdkKind(), ConfigurationKind.JDK_ONLY, false, - false, useJavacWrapper(), withForeignAnnotations(), null); + false, useJavacWrapper(), withForeignAnnotations(), languageVersionSettings); checkJavaPackage( expectedFile, javaPackageAndContext.first, javaPackageAndContext.second, @@ -289,9 +293,10 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { File compiledDir = new File(tmpdir, "compiled"); assertTrue(srcDir.mkdir()); assertTrue(compiledDir.mkdir()); + String fileContent = FileUtil.loadFile(new File(javaFileName)); List srcFiles = TestFiles.createTestFiles( - new File(javaFileName).getName(), FileUtil.loadFile(new File(javaFileName), true), + new File(javaFileName).getName(), fileContent, new TestFiles.TestFileFactoryNoModules() { @NotNull @Override @@ -307,8 +312,11 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { } }); + Directives directives = KotlinTestUtils.parseDirectives(fileContent); + LanguageVersionSettings languageVersionSettings = parseLanguageVersionSettings(directives); + Pair javaPackageAndContext = compileJavaAndLoadTestPackageAndBindingContextFromBinary( - srcFiles, compiledDir, ConfigurationKind.ALL + srcFiles, compiledDir, ConfigurationKind.ALL, languageVersionSettings ); @@ -329,11 +337,12 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { private Pair compileJavaAndLoadTestPackageAndBindingContextFromBinary( @NotNull Collection javaFiles, @NotNull File outDir, - @NotNull ConfigurationKind configurationKind + @NotNull ConfigurationKind configurationKind, + @Nullable LanguageVersionSettings explicitLanguageVersionSettings ) throws IOException { compileJavaWithAnnotationsJar(javaFiles, outDir, getAdditionalJavacArgs(), getJdkHomeForJavac(), withForeignAnnotations()); return loadTestPackageAndBindingContextFromJavaRoot(outDir, getTestRootDisposable(), getJdkKind(), configurationKind, true, - usePsiClassFilesReading(), useJavacWrapper(), withForeignAnnotations(), null, + usePsiClassFilesReading(), useJavacWrapper(), withForeignAnnotations(), explicitLanguageVersionSettings, getExtraClasspath(), this::configureEnvironment); } diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 6c594382d31..c58faa1f7aa 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -145,6 +145,20 @@ enum class LanguageFeature( AllowSealedInheritorsInDifferentFilesOfSamePackage(KOTLIN_1_5), SealedInterfaces(KOTLIN_1_5), + /* + * Improvements include the following: + * - taking into account for type enhancement freshly supported type use annotations: KT-11454 + * - use annotations in the type parameter position to enhance corresponding types: KT-11454 + * - proper support of the type enhancement of the annotated java arrays: KT-24392 + * - proper support of the type enhancement of the annotated java varargs' elements: KT-18768 + * - type enhancement based on annotated bounds of type parameters + * - type enhancement within type arguments of the base classes and interfaces + * - support type enhancement based on type use annotations on java fields + * - preference of a type use annotation to annotation of another type: KT-24392 + * (if @NotNull has TYPE_USE and METHOD target, then `@NotNull Integer []` -> `Array..Array?` instead of `Array..Array`) + */ + ImprovementsAroundTypeEnhancement(KOTLIN_1_6), + // Temporarily disabled, see KT-27084/KT-22379 SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX), @@ -162,6 +176,7 @@ enum class LanguageFeature( MultiPlatformProjects(sinceVersion = null, defaultState = State.DISABLED), NewInference(sinceVersion = KOTLIN_1_4), + // In the next block, features can be enabled only along with new inference SamConversionForKotlinFunctions(sinceVersion = KOTLIN_1_4), SamConversionPerArgument(sinceVersion = KOTLIN_1_4), @@ -263,6 +278,7 @@ enum class LanguageVersion(val major: Int, val minor: Int) : DescriptionAware { KOTLIN_1_3(1, 3), KOTLIN_1_4(1, 4), KOTLIN_1_5(1, 5), + KOTLIN_1_6(1, 6), ; val isStable: Boolean diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt index 5cb7ed23fbc..08a740606b8 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt @@ -25,10 +25,11 @@ import org.jetbrains.kotlin.name.FqName class LazyJavaAnnotations( private val c: LazyJavaResolverContext, - private val annotationOwner: JavaAnnotationOwner + private val annotationOwner: JavaAnnotationOwner, + private val areAnnotationsFreshlySupported: Boolean = false ) : Annotations { private val annotationDescriptors = c.components.storageManager.createMemoizedFunctionWithNullableValues { annotation: JavaAnnotation -> - JavaAnnotationMapper.mapOrResolveJavaAnnotation(annotation, c) + JavaAnnotationMapper.mapOrResolveJavaAnnotation(annotation, c, areAnnotationsFreshlySupported) } override fun findAnnotation(fqName: FqName) = diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/context.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/context.kt index 69a032b4c6a..2b9cac7f802 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/context.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/context.kt @@ -31,8 +31,6 @@ import org.jetbrains.kotlin.load.java.components.SignaturePropagator 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.NullabilityQualifier -import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifierWithMigrationStatus import org.jetbrains.kotlin.load.java.typeEnhancement.SignatureEnhancement import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder @@ -42,7 +40,6 @@ import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker import org.jetbrains.kotlin.utils.JavaTypeEnhancementState -import java.util.* class JavaResolverComponents( val storageManager: StorageManager, @@ -84,6 +81,7 @@ class JavaResolverComponents( interface JavaResolverSettings { val isReleaseCoroutines: Boolean val correctNullabilityForNotNullTypeParameter: Boolean + val enhancementImprovements: Boolean object Default : JavaResolverSettings { override val isReleaseCoroutines: Boolean @@ -91,16 +89,21 @@ interface JavaResolverSettings { override val correctNullabilityForNotNullTypeParameter: Boolean get() = false + + override val enhancementImprovements: Boolean + get() = false } companion object { fun create( isReleaseCoroutines: Boolean, - correctNullabilityForNotNullTypeParameter: Boolean + correctNullabilityForNotNullTypeParameter: Boolean, + enhancementImprovements: Boolean, ): JavaResolverSettings = object : JavaResolverSettings { override val isReleaseCoroutines get() = isReleaseCoroutines override val correctNullabilityForNotNullTypeParameter get() = correctNullabilityForNotNullTypeParameter + override val enhancementImprovements get() = enhancementImprovements } } } @@ -172,9 +175,11 @@ private fun LazyJavaResolverContext.extractDefaultNullabilityQualifier( return null } + val areImprovementsEnabled = components.settings.typeEnhancementImprovements + val nullabilityQualifier = - components.signatureEnhancement.extractNullability(typeQualifier)?.copy(isForWarningOnly = jsr305State.isWarning) - ?: return null + components.signatureEnhancement.extractNullability(typeQualifier, areImprovementsEnabled, typeParameterBounds = false) + ?.copy(isForWarningOnly = jsr305State.isWarning) ?: return null return JavaDefaultQualifiers(nullabilityQualifier, applicability) } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt index 9658d39233b..2b69d658fcb 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt @@ -208,7 +208,11 @@ class LazyJavaClassDescriptor( for (javaType in javaTypes) { val kotlinType = c.typeResolver.transformJavaType(javaType, TypeUsage.SUPERTYPE.toAttributes()) - val enhancedKotlinType = c.components.signatureEnhancement.enhanceSuperType(kotlinType, c) + val areImprovementsEnabled = c.components.settings.typeEnhancementImprovements + val enhancedKotlinType = if (areImprovementsEnabled) { + c.components.signatureEnhancement.enhanceSuperType(kotlinType, c) + } else kotlinType + if (enhancedKotlinType.constructor.declarationDescriptor is NotFoundClasses.MockClassDescriptor) { incomplete.add(javaType) } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/JavaTypeResolver.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/JavaTypeResolver.kt index 2bdc2baecda..d7c2e039958 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/JavaTypeResolver.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/JavaTypeResolver.kt @@ -62,7 +62,7 @@ class JavaTypeResolver( fun transformArrayType(arrayType: JavaArrayType, attr: JavaTypeAttributes, isVararg: Boolean = false): KotlinType { val javaComponentType = arrayType.componentType val primitiveType = (javaComponentType as? JavaPrimitiveType)?.type - val annotations = LazyJavaAnnotations(c, arrayType) + val annotations = LazyJavaAnnotations(c, arrayType, areAnnotationsFreshlySupported = true) if (primitiveType != null) { val jetType = c.module.builtIns.getPrimitiveArrayKotlinType(primitiveType) diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt index 908c98444fc..06b40889420 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/signatureEnhancement.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.load.java.* import org.jetbrains.kotlin.load.java.descriptors.* import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.lazy.copyWithNewDefaultTypeQualifiers +import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaAnnotationDescriptor import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaTypeParameterDescriptor import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents @@ -52,21 +53,25 @@ class SignatureEnhancement( private val typeEnhancement: JavaTypeEnhancement ) { - private fun AnnotationDescriptor.extractNullabilityTypeFromArgument(): NullabilityQualifierWithMigrationStatus? { + private fun AnnotationDescriptor.extractNullabilityTypeFromArgument(isForWarningOnly: Boolean): NullabilityQualifierWithMigrationStatus? { val enumValue = firstArgument() as? EnumValue // if no argument is specified, use default value: NOT_NULL - ?: return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL) + ?: return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, isForWarningOnly) return when (enumValue.enumEntryName.asString()) { - "ALWAYS" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL) - "MAYBE", "NEVER" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE) - "UNKNOWN" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.FORCE_FLEXIBILITY) + "ALWAYS" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, isForWarningOnly) + "MAYBE", "NEVER" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE, isForWarningOnly) + "UNKNOWN" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.FORCE_FLEXIBILITY, isForWarningOnly) else -> null } } - fun extractNullability(annotationDescriptor: AnnotationDescriptor): NullabilityQualifierWithMigrationStatus? { - extractNullabilityFromKnownAnnotations(annotationDescriptor)?.let { return it } + fun extractNullability( + annotationDescriptor: AnnotationDescriptor, + areImprovementsEnabled: Boolean, + typeParameterBounds: Boolean + ): NullabilityQualifierWithMigrationStatus? { + extractNullabilityFromKnownAnnotations(annotationDescriptor, areImprovementsEnabled, typeParameterBounds)?.let { return it } val typeQualifierAnnotation = annotationTypeQualifierResolver.resolveTypeQualifierAnnotation(annotationDescriptor) @@ -75,18 +80,23 @@ class SignatureEnhancement( val jsr305State = annotationTypeQualifierResolver.resolveJsr305AnnotationState(annotationDescriptor) if (jsr305State.isIgnore) return null - return extractNullabilityFromKnownAnnotations(typeQualifierAnnotation)?.copy(isForWarningOnly = jsr305State.isWarning) + return extractNullabilityFromKnownAnnotations(typeQualifierAnnotation, areImprovementsEnabled, typeParameterBounds) + ?.copy(isForWarningOnly = jsr305State.isWarning) } private fun extractNullabilityFromKnownAnnotations( - annotationDescriptor: AnnotationDescriptor + annotationDescriptor: AnnotationDescriptor, + areImprovementsEnabled: Boolean, + typeParameterBounds: Boolean ): NullabilityQualifierWithMigrationStatus? { val annotationFqName = annotationDescriptor.fqName ?: return null + val isForWarningOnly = annotationDescriptor is LazyJavaAnnotationDescriptor + && (annotationDescriptor.isFreshlySupportedTypeUseAnnotation || typeParameterBounds) + && !areImprovementsEnabled - val migrationStatus = - jspecifyMigrationStatus(annotationFqName) - ?: commonMigrationStatus(annotationFqName, annotationDescriptor) - ?: return null + val migrationStatus = jspecifyMigrationStatus(annotationFqName) + ?: commonMigrationStatus(annotationFqName, annotationDescriptor, isForWarningOnly) + ?: return null return if (!migrationStatus.isForWarningOnly && annotationDescriptor is PossiblyExternalAnnotationDescriptor @@ -111,17 +121,18 @@ class SignatureEnhancement( private fun commonMigrationStatus( annotationFqName: FqName, - annotationDescriptor: AnnotationDescriptor + annotationDescriptor: AnnotationDescriptor, + isForWarningOnly: Boolean = false ): NullabilityQualifierWithMigrationStatus? = when { - annotationFqName in NULLABLE_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE) - annotationFqName in NOT_NULL_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL) - annotationFqName == JAVAX_NONNULL_ANNOTATION -> annotationDescriptor.extractNullabilityTypeFromArgument() + annotationFqName in NULLABLE_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE, isForWarningOnly) + annotationFqName in NOT_NULL_ANNOTATIONS -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, isForWarningOnly) + annotationFqName == JAVAX_NONNULL_ANNOTATION -> annotationDescriptor.extractNullabilityTypeFromArgument(isForWarningOnly) annotationFqName == COMPATQUAL_NULLABLE_ANNOTATION && javaTypeEnhancementState.enableCompatqualCheckerFrameworkAnnotations -> - NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE) + NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE, isForWarningOnly) annotationFqName == COMPATQUAL_NONNULL_ANNOTATION && javaTypeEnhancementState.enableCompatqualCheckerFrameworkAnnotations -> - NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL) + NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL, isForWarningOnly) annotationFqName == ANDROIDX_RECENTLY_NON_NULL_ANNOTATION -> NullabilityQualifierWithMigrationStatus( NullabilityQualifier.NOT_NULL, @@ -326,10 +337,10 @@ class SignatureEnhancement( typeParameterForArgument: TypeParameterDescriptor?, isFromStarProjection: Boolean ): JavaTypeQualifiers { + val areImprovementsEnabled = containerContext.components.settings.typeEnhancementImprovements + val composedAnnotation = - if (isHeadTypeConstructor && typeContainer is TypeParameterDescriptor) { - composeAnnotations(typeContainer.annotations, annotations) - } else if (isHeadTypeConstructor && typeContainer != null) { + if (isHeadTypeConstructor && typeContainer != null && typeContainer !is TypeParameterDescriptor && areImprovementsEnabled) { val filteredContainerAnnotations = typeContainer.annotations.filter { val (_, targets) = annotationTypeQualifierResolver.resolveAnnotation(it) ?: return@filter false /* @@ -343,6 +354,8 @@ class SignatureEnhancement( AnnotationQualifierApplicabilityType.TYPE_USE !in targets } composeAnnotations(Annotations.create(filteredContainerAnnotations), annotations) + } else if (isHeadTypeConstructor && typeContainer != null) { + composeAnnotations(typeContainer.annotations, annotations) } else annotations fun List.ifPresent(qualifier: T) = @@ -361,7 +374,8 @@ class SignatureEnhancement( val (nullabilityFromBoundsForTypeBasedOnTypeParameter, isTypeParameterWithNotNullableBounds) = nullabilityInfoBoundsForTypeParameterUsage() - val annotationsNullability = composedAnnotation.extractNullability()?.takeUnless { isFromStarProjection } + val annotationsNullability = composedAnnotation.extractNullability(areImprovementsEnabled, typeParameterBounds) + ?.takeUnless { isFromStarProjection } val nullabilityInfo = annotationsNullability ?: computeNullabilityInfoInTheAbsenceOfExplicitAnnotation( @@ -452,8 +466,11 @@ class SignatureEnhancement( } } - private fun Annotations.extractNullability(): NullabilityQualifierWithMigrationStatus? = - this.firstNotNullResult { extractNullability(it) } + private fun Annotations.extractNullability( + areImprovementsEnabled: Boolean, + typeParameterBounds: Boolean + ): NullabilityQualifierWithMigrationStatus? = + this.firstNotNullResult { extractNullability(it, areImprovementsEnabled, typeParameterBounds) } private fun computeIndexedQualifiersForOverride(): (Int) -> JavaTypeQualifiers {