[Test] Support KOTLIN_CONFIGURATION_FLAGS directive in new tests

This commit is contained in:
Dmitriy Novozhilov
2020-12-28 11:36:53 +03:00
committed by TeamCityServer
parent e0cd830a0e
commit 9fd2800594
9 changed files with 162 additions and 97 deletions
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.test.frontend.classic.handlers.FirTestDataConsistenc
import org.jetbrains.kotlin.test.frontend.classic.handlers.OldNewInferenceMetaInfoProcessor
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.AdditionalDiagnosticsSourceFilesProvider
import org.jetbrains.kotlin.test.services.CoroutineHelpersSourceFilesProvider
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
@@ -44,6 +45,7 @@ abstract class AbstractDiagnosticTest : AbstractKotlinCompilerTest() {
enableMetaInfoHandler()
useConfigurators(
::CommonEnvironmentConfigurator,
::JvmEnvironmentConfigurator,
::ScriptingEnvironmentConfigurator
)
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.test.frontend.classic.handlers.DeclarationsDumpHandl
import org.jetbrains.kotlin.test.frontend.classic.handlers.OldNewInferenceMetaInfoProcessor
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.AdditionalDiagnosticsSourceFilesProvider
import org.jetbrains.kotlin.test.services.CoroutineHelpersSourceFilesProvider
@@ -31,6 +32,8 @@ abstract class AbstractDiagnosticsNativeTest : AbstractKotlinCompilerTest() {
enableMetaInfoHandler()
useConfigurators(::CommonEnvironmentConfigurator)
useMetaInfoProcessors(::OldNewInferenceMetaInfoProcessor)
useAdditionalSourceProviders(
::AdditionalDiagnosticsSourceFilesProvider,
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.test.frontend.classic.handlers.DynamicCallsDumpHandl
import org.jetbrains.kotlin.test.frontend.classic.handlers.OldNewInferenceMetaInfoProcessor
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.AdditionalDiagnosticsSourceFilesProvider
import org.jetbrains.kotlin.test.services.CoroutineHelpersSourceFilesProvider
import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurator
@@ -33,7 +34,10 @@ abstract class AbstractDiagnosticsTestWithJsStdLib : AbstractKotlinCompilerTest(
enableMetaInfoHandler()
useConfigurators(::JsEnvironmentConfigurator,)
useConfigurators(
::CommonEnvironmentConfigurator,
::JsEnvironmentConfigurator,
)
useMetaInfoProcessors(::OldNewInferenceMetaInfoProcessor)
useAdditionalSourceProviders(
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.test.frontend.classic.handlers.DeclarationsDumpHandl
import org.jetbrains.kotlin.test.frontend.classic.handlers.OldNewInferenceMetaInfoProcessor
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.AdditionalDiagnosticsSourceFilesProvider
import org.jetbrains.kotlin.test.services.CoroutineHelpersSourceFilesProvider
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
@@ -41,7 +42,10 @@ abstract class AbstractDiagnosticsTestWithJvmBackend : AbstractKotlinCompilerTes
enableMetaInfoHandler()
useConfigurators(::JvmEnvironmentConfigurator)
useConfigurators(
::CommonEnvironmentConfigurator,
::JvmEnvironmentConfigurator,
)
useMetaInfoProcessors(::OldNewInferenceMetaInfoProcessor)
useAdditionalSourceProviders(
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade
import org.jetbrains.kotlin.test.frontend.fir.handlers.*
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.AdditionalDiagnosticsSourceFilesProvider
import org.jetbrains.kotlin.test.services.CoroutineHelpersSourceFilesProvider
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
@@ -35,7 +36,11 @@ abstract class AbstractFirDiagnosticTest : AbstractKotlinCompilerTest() {
enableMetaInfoHandler()
useConfigurators(::JvmEnvironmentConfigurator)
useConfigurators(
::CommonEnvironmentConfigurator,
::JvmEnvironmentConfigurator,
)
useAdditionalSourceProviders(
::AdditionalDiagnosticsSourceFilesProvider,
::CoroutineHelpersSourceFilesProvider,
@@ -22,10 +22,7 @@ import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.services.AdditionalDiagnosticsSourceFilesProvider
import org.jetbrains.kotlin.test.services.CoroutineHelpersSourceFilesProvider
import org.jetbrains.kotlin.test.services.configuration.JdkForeignAnnotationType
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.configuration.JvmForeignAnnotationsAgainstCompiledJavaConfigurator
import org.jetbrains.kotlin.test.services.configuration.JvmForeignAnnotationsConfigurator
import org.jetbrains.kotlin.test.services.configuration.*
import org.jetbrains.kotlin.test.services.jvm.ForeignAnnotationAgainstCompiledJavaTestSuppressor
abstract class AbstractForeignAnnotationsTestBase : AbstractKotlinCompilerTest() {
@@ -45,6 +42,7 @@ abstract class AbstractForeignAnnotationsTestBase : AbstractKotlinCompilerTest()
enableMetaInfoHandler()
useConfigurators(
::CommonEnvironmentConfigurator,
::JvmEnvironmentConfigurator,
foreignAnnotationsConfigurator
)
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.test.services.configuration
import com.intellij.mock.MockProject
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.test.directives.ConfigurationDirectives
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.parseAnalysisFlags
import org.jetbrains.kotlin.test.services.EnvironmentConfigurator
import org.jetbrains.kotlin.test.services.TestServices
class CommonEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) {
override val directivesContainers: List<DirectivesContainer>
get() = listOf(ConfigurationDirectives)
override fun configureCompilerConfiguration(configuration: CompilerConfiguration, module: TestModule, project: MockProject) {
val rawFlags = module.directives[ConfigurationDirectives.KOTLIN_CONFIGURATION_FLAGS]
parseAnalysisFlags(rawFlags).forEach { (key, value) ->
@Suppress("UNCHECKED_CAST")
configuration.put(key as CompilerConfigurationKey<Any>, value)
}
}
}
@@ -5,12 +5,9 @@
package org.jetbrains.kotlin.test
import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.checkers.ENABLE_JVM_PREVIEW
import org.jetbrains.kotlin.checkers.parseLanguageVersionSettings
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoot
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
@@ -19,9 +16,7 @@ import org.jetbrains.kotlin.config.JvmTarget.Companion.fromString
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import org.jetbrains.kotlin.test.util.KtTestUtil
import java.io.File
import java.lang.reflect.Field
import java.util.*
import java.util.regex.Pattern
abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase() {
@Throws(Exception::class)
@@ -129,60 +124,6 @@ abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase()
}
companion object {
private val FLAG_NAMESPACE_TO_CLASS: Map<String, Class<*>> = ImmutableMap.of(
"CLI", CLIConfigurationKeys::class.java,
"JVM", JVMConfigurationKeys::class.java
)
private val FLAG_CLASSES: List<Class<*>> = ImmutableList.of(
CLIConfigurationKeys::class.java,
JVMConfigurationKeys::class.java
)
private val BOOLEAN_FLAG_PATTERN = Pattern.compile("([+-])(([a-zA-Z_0-9]*)\\.)?([a-zA-Z_0-9]*)")
private val CONSTRUCTOR_CALL_NORMALIZATION_MODE_FLAG_PATTERN = Pattern.compile(
"CONSTRUCTOR_CALL_NORMALIZATION_MODE=([a-zA-Z_\\-0-9]*)"
)
private val ASSERTIONS_MODE_FLAG_PATTERN = Pattern.compile("ASSERTIONS_MODE=([a-zA-Z_0-9-]*)")
private val STRING_CONCAT = Pattern.compile("STRING_CONCAT=([a-zA-Z_0-9-]*)")
private fun tryApplyBooleanFlag(
configuration: CompilerConfiguration,
flag: String,
flagEnabled: Boolean,
flagNamespace: String?,
flagName: String
) {
val configurationKeysClass: Class<*>?
var configurationKeyField: Field? = null
if (flagNamespace == null) {
for (flagClass in FLAG_CLASSES) {
try {
configurationKeyField = flagClass.getField(flagName)
break
} catch (ignored: java.lang.Exception) {
}
}
} else {
configurationKeysClass = FLAG_NAMESPACE_TO_CLASS[flagNamespace]
assert(configurationKeysClass != null) { "Expected [+|-][namespace.]configurationKey, got: $flag" }
configurationKeyField = try {
configurationKeysClass!!.getField(flagName)
} catch (e: java.lang.Exception) {
null
}
}
assert(configurationKeyField != null) { "Expected [+|-][namespace.]configurationKey, got: $flag" }
try {
@Suppress("UNCHECKED_CAST")
val configurationKey = configurationKeyField!![null] as CompilerConfigurationKey<Boolean>
configuration.put(configurationKey, flagEnabled)
} catch (e: java.lang.Exception) {
assert(false) { "Expected [+|-][namespace.]configurationKey, got: $flag" }
}
}
@JvmStatic
fun updateConfigurationByDirectivesInTestFiles(
testFilesWithConfigurationDirectives: List<TestFile>,
@@ -249,37 +190,10 @@ abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase()
}
private fun updateConfigurationWithFlags(configuration: CompilerConfiguration, flags: List<String>) {
for (flag in flags) {
var m = BOOLEAN_FLAG_PATTERN.matcher(flag)
if (m.matches()) {
val flagEnabled = "-" != m.group(1)
val flagNamespace = m.group(3)
val flagName = m.group(4)
tryApplyBooleanFlag(configuration, flag, flagEnabled, flagNamespace, flagName)
continue
}
m = CONSTRUCTOR_CALL_NORMALIZATION_MODE_FLAG_PATTERN.matcher(flag)
if (m.matches()) {
val flagValueString = m.group(1)
val mode = JVMConstructorCallNormalizationMode.fromStringOrNull(flagValueString)
?: error("Wrong CONSTRUCTOR_CALL_NORMALIZATION_MODE value: $flagValueString")
configuration.put(JVMConfigurationKeys.CONSTRUCTOR_CALL_NORMALIZATION_MODE, mode)
}
m = ASSERTIONS_MODE_FLAG_PATTERN.matcher(flag)
if (m.matches()) {
val flagValueString = m.group(1)
val mode = JVMAssertionsMode.fromStringOrNull(flagValueString)
?: error("Wrong ASSERTIONS_MODE value: $flagValueString")
configuration.put(JVMConfigurationKeys.ASSERTIONS_MODE, mode)
}
m = STRING_CONCAT.matcher(flag)
if (m.matches()) {
val flagValueString = m.group(1)
val mode = JvmStringConcat.fromString(flagValueString)
?: error("Wrong STRING_CONCAT value: $flagValueString")
configuration.put(JVMConfigurationKeys.STRING_CONCAT, mode)
}
val configurationFlags = parseAnalysisFlags(flags)
configurationFlags.entries.forEach { (key, value) ->
@Suppress("UNCHECKED_CAST")
configuration.put(key as CompilerConfigurationKey<Any>, value)
}
}
@@ -0,0 +1,106 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.test
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.config.*
import java.lang.reflect.Field
import java.util.regex.Pattern
private val BOOLEAN_FLAG_PATTERN = Pattern.compile("([+-])(([a-zA-Z_0-9]*)\\.)?([a-zA-Z_0-9]*)")
private val CONSTRUCTOR_CALL_NORMALIZATION_MODE_FLAG_PATTERN = Pattern.compile(
"CONSTRUCTOR_CALL_NORMALIZATION_MODE=([a-zA-Z_\\-0-9]*)"
)
private val ASSERTIONS_MODE_FLAG_PATTERN = Pattern.compile("ASSERTIONS_MODE=([a-zA-Z_0-9-]*)")
private val STRING_CONCAT = Pattern.compile("STRING_CONCAT=([a-zA-Z_0-9-]*)")
private val FLAG_CLASSES: List<Class<*>> = listOf(
CLIConfigurationKeys::class.java,
JVMConfigurationKeys::class.java
)
private val FLAG_NAMESPACE_TO_CLASS: Map<String, Class<*>> = mapOf(
"CLI" to CLIConfigurationKeys::class.java,
"JVM" to JVMConfigurationKeys::class.java
)
fun parseAnalysisFlags(rawFlags: List<String>): Map<CompilerConfigurationKey<*>, Any> {
val result = mutableMapOf<CompilerConfigurationKey<*>, Any>()
for (flag in rawFlags) {
var m = BOOLEAN_FLAG_PATTERN.matcher(flag)
if (m.matches()) {
val flagEnabled = "-" != m.group(1)
val flagNamespace = m.group(3)
val flagName = m.group(4)
tryApplyBooleanFlag(result, flag, flagEnabled, flagNamespace, flagName)
continue
}
m = CONSTRUCTOR_CALL_NORMALIZATION_MODE_FLAG_PATTERN.matcher(flag)
if (m.matches()) {
val flagValueString = m.group(1)
val mode = JVMConstructorCallNormalizationMode.fromStringOrNull(flagValueString)
?: error("Wrong CONSTRUCTOR_CALL_NORMALIZATION_MODE value: $flagValueString")
result[JVMConfigurationKeys.CONSTRUCTOR_CALL_NORMALIZATION_MODE] = mode
}
m = ASSERTIONS_MODE_FLAG_PATTERN.matcher(flag)
if (m.matches()) {
val flagValueString = m.group(1)
val mode = JVMAssertionsMode.fromStringOrNull(flagValueString)
?: error("Wrong ASSERTIONS_MODE value: $flagValueString")
result[JVMConfigurationKeys.ASSERTIONS_MODE] = mode
}
m = STRING_CONCAT.matcher(flag)
if (m.matches()) {
val flagValueString = m.group(1)
val mode = JvmStringConcat.fromString(flagValueString)
?: error("Wrong STRING_CONCAT value: $flagValueString")
result[JVMConfigurationKeys.STRING_CONCAT] = mode
}
}
return result
}
private fun tryApplyBooleanFlag(
destination: MutableMap<CompilerConfigurationKey<*>, Any>,
flag: String,
flagEnabled: Boolean,
flagNamespace: String?,
flagName: String
) {
val configurationKeysClass: Class<*>?
var configurationKeyField: Field? = null
if (flagNamespace == null) {
for (flagClass in FLAG_CLASSES) {
try {
configurationKeyField = flagClass.getField(flagName)
break
} catch (ignored: java.lang.Exception) {
}
}
} else {
configurationKeysClass = FLAG_NAMESPACE_TO_CLASS[flagNamespace]
assert(configurationKeysClass != null) { "Expected [+|-][namespace.]configurationKey, got: $flag" }
configurationKeyField = try {
configurationKeysClass!!.getField(flagName)
} catch (e: java.lang.Exception) {
null
}
}
assert(configurationKeyField != null) { "Expected [+|-][namespace.]configurationKey, got: $flag" }
try {
@Suppress("UNCHECKED_CAST")
val configurationKey = configurationKeyField!![null] as CompilerConfigurationKey<Boolean>
destination.put(configurationKey, flagEnabled)
} catch (e: java.lang.Exception) {
assert(false) { "Expected [+|-][namespace.]configurationKey, got: $flag" }
}
}