From 1f0616439cbe6a3817e9d6a6cef4314b7f389a48 Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Mon, 5 Apr 2021 18:08:01 +0300 Subject: [PATCH] Introduce special common directives for tests based on foreign annotation tests --- .../test/services/SourceFileProvider.kt | 16 ++++++ .../JvmEnvironmentConfigurationDirectives.kt | 13 +++++ .../runners/AbstractForeignAnnotationsTest.kt | 12 ++++- .../JvmEnvironmentConfigurator.kt | 53 ++++++++++++++++++- .../JvmForeignAnnotationsConfigurator.kt | 38 ++----------- 5 files changed, 95 insertions(+), 37 deletions(-) diff --git a/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt b/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt index 8078c162ea1..9148d4ada91 100644 --- a/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt +++ b/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt @@ -18,9 +18,11 @@ abstract class SourceFilePreprocessor(val testServices: TestServices) { abstract class SourceFileProvider : TestService { abstract val kotlinSourceDirectory: File abstract val javaSourceDirectory: File + abstract val javaBinaryDirectory: File abstract fun getContentOfSourceFile(testFile: TestFile): String abstract fun getRealFileForSourceFile(testFile: TestFile): File + abstract fun getRealFileForBinaryFile(testFile: TestFile): File } val TestServices.sourceFileProvider: SourceFileProvider by TestServices.testServiceAccessor() @@ -28,6 +30,7 @@ val TestServices.sourceFileProvider: SourceFileProvider by TestServices.testServ class SourceFileProviderImpl(val testServices: TestServices, val preprocessors: List) : SourceFileProvider() { override val kotlinSourceDirectory: File = testServices.createTempDirectory("kotlin-files") override val javaSourceDirectory: File = testServices.createTempDirectory("java-files") + override val javaBinaryDirectory: File = testServices.createTempDirectory("java-binary-files") private val contentOfFiles = mutableMapOf() private val realFileMap = mutableMapOf() @@ -52,6 +55,19 @@ class SourceFileProviderImpl(val testServices: TestServices, val preprocessors: } } + override fun getRealFileForBinaryFile(testFile: TestFile): File { + return realFileMap.getOrPut(testFile) { + val directory = when { + testFile.isJavaFile -> javaBinaryDirectory + else -> error("Unknown file type: ${testFile.name}") + } + directory.resolve(testFile.relativePath).also { + it.parentFile.mkdirs() + it.writeText(getContentOfSourceFile(testFile)) + } + } + } + private fun generateFinalContent(testFile: TestFile): String { return preprocessors.fold(testFile.originalContent) { content, preprocessor -> preprocessor.process(testFile, content) diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/JvmEnvironmentConfigurationDirectives.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/JvmEnvironmentConfigurationDirectives.kt index 9629da27f1c..db986d80644 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/JvmEnvironmentConfigurationDirectives.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/JvmEnvironmentConfigurationDirectives.kt @@ -31,9 +31,22 @@ object JvmEnvironmentConfigurationDirectives : SimpleDirectivesContainer() { val WITH_REFLECT by directive("Add Kotlin reflect to classpath") val NO_RUNTIME by directive("Don't add any runtime libs to classpath") + val WITH_FOREIGN_ANNOTATIONS by directive("Add foreign nullability annotations to classpath") + + val WITH_JSR305_TEST_ANNOTATIONS by directive( + description = """ + Add test nullability annotations based on JSR-305 annotations + See directory ./compiler/testData/diagnostics/helpers/jsr305_test_annotations + """.trimIndent() + ) + val USE_PSI_CLASS_FILES_READING by directive("Use a slower (PSI-based) class files reading implementation") val USE_JAVAC by directive("Enable javac integration") val SKIP_JAVA_SOURCES by directive("Don't add java sources to compile classpath") + val INCLUDE_JAVA_AS_BINARY by directive( + "Compile this java file into jar and add it to classpath instead of compiling Kotlin with Java sources", + applicability = DirectiveApplicability.File + ) val JSPECIFY_MUTE by directive( "Skip jspecify checks for compliance Kotlin diagnostics to jspecify marks", diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractForeignAnnotationsTest.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractForeignAnnotationsTest.kt index 4ca330cc6cf..da797393b20 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractForeignAnnotationsTest.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractForeignAnnotationsTest.kt @@ -5,21 +5,29 @@ package org.jetbrains.kotlin.test.runners +import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.test.Constructor +import org.jetbrains.kotlin.test.TestJdkKind import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives.REPORT_JVM_DIAGNOSTICS_ON_FRONTEND import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives.SKIP_TXT import org.jetbrains.kotlin.test.directives.ForeignAnnotationsDirectives.ANNOTATIONS_PATH +import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.JDK_KIND +import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.JVM_TARGET import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.SKIP_JAVA_SOURCES +import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.STDLIB_JDK8 import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.USE_PSI_CLASS_FILES_READING +import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.WITH_FOREIGN_ANNOTATIONS +import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.WITH_JSR305_TEST_ANNOTATIONS +import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.WITH_STDLIB import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendFacade import org.jetbrains.kotlin.test.frontend.classic.handlers.ClassicDiagnosticsHandler import org.jetbrains.kotlin.test.frontend.classic.handlers.DeclarationsDumpHandler import org.jetbrains.kotlin.test.frontend.classic.handlers.OldNewInferenceMetaInfoProcessor -import org.jetbrains.kotlin.test.model.BackendKind import org.jetbrains.kotlin.test.model.DependencyKind import org.jetbrains.kotlin.test.model.FrontendKinds +import org.jetbrains.kotlin.test.preprocessors.JspecifyTestsPreprocessor import org.jetbrains.kotlin.test.services.configuration.* import org.jetbrains.kotlin.test.services.jvm.ForeignAnnotationAgainstCompiledJavaTestSuppressor import org.jetbrains.kotlin.test.services.sourceProviders.AdditionalDiagnosticsSourceFilesProvider @@ -37,6 +45,8 @@ abstract class AbstractForeignAnnotationsTestBase : AbstractKotlinCompilerTest() defaultDirectives { +REPORT_JVM_DIAGNOSTICS_ON_FRONTEND + +WITH_FOREIGN_ANNOTATIONS + +WITH_JSR305_TEST_ANNOTATIONS } enableMetaInfoHandler() diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt index 5de55528894..650e0d52d85 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt @@ -14,10 +14,13 @@ import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.test.ConfigurationKind +import org.jetbrains.kotlin.test.MockLibraryUtil.compileJavaFilesLibraryToJar import org.jetbrains.kotlin.test.TestJdkKind +import org.jetbrains.kotlin.test.directives.ForeignAnnotationsDirectives import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.ASSERTIONS_MODE import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.CONSTRUCTOR_CALL_NORMALIZATION_MODE +import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.INCLUDE_JAVA_AS_BINARY import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.JVM_TARGET import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.LAMBDAS import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.SAM_CONVERSIONS @@ -36,12 +39,17 @@ import org.jetbrains.kotlin.test.model.DependencyDescription import org.jetbrains.kotlin.test.model.DependencyKind import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.services.* +import org.jetbrains.kotlin.test.services.configuration.JdkForeignAnnotationType.Companion.FOREIGN_ANNOTATIONS_SOURCES_PATH +import org.jetbrains.kotlin.test.services.configuration.JdkForeignAnnotationType.Companion.FOREIGN_JDK8_ANNOTATIONS_SOURCES_PATH +import org.jetbrains.kotlin.test.services.configuration.JdkForeignAnnotationType.Companion.JSR_305_TEST_ANNOTATIONS_PATH import org.jetbrains.kotlin.test.services.jvm.CompiledClassesManager import org.jetbrains.kotlin.test.services.jvm.compiledClassesManager import org.jetbrains.kotlin.test.util.KtTestUtil import org.jetbrains.kotlin.test.util.joinToArrayString import org.jetbrains.kotlin.utils.addIfNotNull import java.io.File +import kotlin.io.path.ExperimentalPathApi +import kotlin.io.path.createTempDirectory class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) { companion object { @@ -129,16 +137,59 @@ class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfig configuration.addJvmClasspathRoot(ForTestCompileRuntime.runtimeJarForTestsWithJdk8()) } + if (JvmEnvironmentConfigurationDirectives.WITH_FOREIGN_ANNOTATIONS in registeredDirectives) { + val annotationPath = registeredDirectives[ForeignAnnotationsDirectives.ANNOTATIONS_PATH].singleOrNull() + ?: JdkForeignAnnotationType.Jdk8Annotations + val javaFilesDir = createTempDirectory().toFile().also { + File(annotationPath.path).copyRecursively(it) + } + val jar = compileJavaFilesLibraryToJar( + javaFilesDir.path, + "foreign-annotations", + assertions = JUnit5Assertions, + extraClasspath = configuration.jvmClasspathRoots.map { it.absolutePath } + ) + configuration.addJvmClasspathRoot(jar) + configuration.addJvmClasspathRoot(ForTestCompileRuntime.jvmAnnotationsForTests()) + } + + if (JvmEnvironmentConfigurationDirectives.WITH_JSR305_TEST_ANNOTATIONS in registeredDirectives) { + val javaFilesDir = createTempDirectory().toFile().also { + File(JSR_305_TEST_ANNOTATIONS_PATH).copyRecursively(it) + } + val jar = compileJavaFilesLibraryToJar( + javaFilesDir.path, + "jsr-305-test-annotations", + assertions = JUnit5Assertions, + extraClasspath = configuration.jvmClasspathRoots.map { it.absolutePath } + ) + configuration.addJvmClasspathRoot(jar) + } + val isIr = module.targetBackend?.isIR == true configuration.put(JVMConfigurationKeys.IR, isIr) if (JvmEnvironmentConfigurationDirectives.SKIP_JAVA_SOURCES !in module.directives) { - module.javaFiles.takeIf { it.isNotEmpty() }?.let { javaFiles -> + val javaSourceFiles = module.javaFiles.filter { INCLUDE_JAVA_AS_BINARY !in it.directives } + javaSourceFiles.takeIf { it.isNotEmpty() }?.let { javaFiles -> javaFiles.forEach { testServices.sourceFileProvider.getRealFileForSourceFile(it) } configuration.addJavaSourceRoot(testServices.sourceFileProvider.javaSourceDirectory) } } + val javaBinaryFiles = module.javaFiles.filter { INCLUDE_JAVA_AS_BINARY in it.directives } + + javaBinaryFiles.takeIf { it.isNotEmpty() }?.let { javaFiles -> + javaFiles.forEach { testServices.sourceFileProvider.getRealFileForBinaryFile(it) } + val jar = compileJavaFilesLibraryToJar( + testServices.sourceFileProvider.javaBinaryDirectory.path, + "java-binaries", + extraClasspath = configuration.jvmClasspathRoots.map { it.absolutePath }, + assertions = JUnit5Assertions + ) + configuration.addJvmClasspathRoot(jar) + } + configuration.registerModuleDependencies(module) if (JvmEnvironmentConfigurationDirectives.USE_PSI_CLASS_FILES_READING in module.directives) { diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmForeignAnnotationsConfigurator.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmForeignAnnotationsConfigurator.kt index 41625f741e0..da3dd9280ca 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmForeignAnnotationsConfigurator.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmForeignAnnotationsConfigurator.kt @@ -30,53 +30,21 @@ open class JvmForeignAnnotationsConfigurator(testServices: TestServices) : Envir companion object { val FOREIGN_ANNOTATIONS_SOURCES_PATH = Annotations.path val FOREIGN_JDK8_ANNOTATIONS_SOURCES_PATH = Jdk8Annotations.path + val JSR_305_TEST_ANNOTATIONS_PATH = "compiler/testData/diagnostics/helpers/jsr305_test_annotations" } override val directivesContainers: List get() = listOf(ForeignAnnotationsDirectives) - @OptIn(ExperimentalStdlibApi::class) - override fun configureCompilerConfiguration(configuration: CompilerConfiguration, module: TestModule) { - val extraClassPath = buildList { - val foreignAnnotations = createJarWithForeignAnnotations(module) - addAll(foreignAnnotations) - addAll(compileTestAnnotations(foreignAnnotations)) - } - configuration.addJvmClasspathRoots(extraClassPath) - } - - protected fun createJarWithForeignAnnotations(module: TestModule): List { - val directive = ForeignAnnotationsDirectives.ANNOTATIONS_PATH - val annotationsPath = module.directives.singleOrZeroValue(directive) - ?.path - ?: error("${directive.name} should be specified in test or test runner") - - return listOf( - MockLibraryUtil.compileJavaFilesLibraryToJar(annotationsPath, "foreign-annotations", assertions = JUnit5Assertions), - ForTestCompileRuntime.jvmAnnotationsForTests() - ) - } - - protected fun compileTestAnnotations(extraClassPath: List): List = - listOf( - MockLibraryUtil.compileJavaFilesLibraryToJar( - TEST_ANNOTATIONS_SOURCE_PATH, - "test-foreign-annotations", - extraOptions = listOf("-Xallow-kotlin-package"), - extraClasspath = extraClassPath.map { it.path }, - assertions = JUnit5Assertions - ) - ) - override fun provideAdditionalAnalysisFlags(directives: RegisteredDirectives): Map, Any?> { - val globalState = directives.singleOrZeroValue(JSR305_GLOBAL_REPORT) ?: ReportLevel.STRICT + val globalState = directives.singleOrZeroValue(JSR305_GLOBAL_REPORT) ?: ReportLevel.WARN val migrationState = directives.singleOrZeroValue(JSR305_MIGRATION_REPORT) val userAnnotationsState = directives[JSR305_SPECIAL_REPORT].mapNotNull { val (name, stateDescription) = it.split(":").takeIf { it.size == 2 } ?: return@mapNotNull null val state = ReportLevel.findByDescription(stateDescription) ?: return@mapNotNull null name to state }.toMap() - val jSpecifyReportLevel = directives.singleOrZeroValue(JSPECIFY_STATE) ?: ReportLevel.STRICT + val jSpecifyReportLevel = directives.singleOrZeroValue(JSPECIFY_STATE) ?: ReportLevel.WARN return mapOf( JvmAnalysisFlags.javaTypeEnhancementState to JavaTypeEnhancementState( globalState,