[analysis api, test] rework test infrastructure, add multimodule tests

This commit is contained in:
Ilya Kirillov
2022-03-24 22:34:31 +01:00
parent 1e5cf80278
commit 4bd7fed1ea
79 changed files with 1786 additions and 510 deletions
@@ -15,12 +15,14 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreApplicationEnvironment
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.js.isJs
import org.jetbrains.kotlin.platform.jvm.isJvm
@@ -34,19 +36,25 @@ import org.jetbrains.kotlin.test.model.TestModule
import java.io.File
abstract class CompilerConfigurationProvider(val testServices: TestServices) : TestService {
abstract val testServices: TestServices
abstract val testRootDisposable: Disposable
abstract val configurators: List<AbstractEnvironmentConfigurator>
protected abstract fun getKotlinCoreEnvironment(module: TestModule): KotlinCoreEnvironment
fun getProject(module: TestModule): Project {
open fun getProject(module: TestModule): Project {
return getKotlinCoreEnvironment(module).project
}
fun getPackagePartProviderFactory(module: TestModule): (GlobalSearchScope) -> JvmPackagePartProvider {
fun registerCompilerExtensions(project: Project, module: TestModule) {
configurators.forEach { it.registerCompilerExtensions(project, module) }
}
open fun getPackagePartProviderFactory(module: TestModule): (GlobalSearchScope) -> JvmPackagePartProvider {
return getKotlinCoreEnvironment(module)::createPackagePartProvider
}
fun getCompilerConfiguration(module: TestModule): CompilerConfiguration {
open fun getCompilerConfiguration(module: TestModule): CompilerConfiguration {
return getKotlinCoreEnvironment(module).configuration
}
@@ -64,9 +72,9 @@ abstract class CompilerConfigurationProvider(val testServices: TestServices) : T
val TestServices.compilerConfigurationProvider: CompilerConfigurationProvider by TestServices.testServiceAccessor()
open class CompilerConfigurationProviderImpl(
testServices: TestServices,
override val testServices: TestServices,
override val testRootDisposable: Disposable,
val configurators: List<AbstractEnvironmentConfigurator>
override val configurators: List<AbstractEnvironmentConfigurator>
) : CompilerConfigurationProvider(testServices) {
private val cache: MutableMap<TestModule, KotlinCoreEnvironment> = mutableMapOf()
@@ -79,62 +87,70 @@ open class CompilerConfigurationProviderImpl(
@OptIn(TestInfrastructureInternals::class)
protected open fun createKotlinCoreEnvironment(module: TestModule): KotlinCoreEnvironment {
val platform = module.targetPlatform
val configFiles = when {
platform.isJvm() -> EnvironmentConfigFiles.JVM_CONFIG_FILES
platform.isJs() -> EnvironmentConfigFiles.JS_CONFIG_FILES
platform.isNative() -> EnvironmentConfigFiles.NATIVE_CONFIG_FILES
// TODO: is it correct?
platform.isCommon() -> EnvironmentConfigFiles.METADATA_CONFIG_FILES
else -> error("Unknown platform: $platform")
}
val configFiles = platform.platformToEnvironmentConfigFiles()
val applicationEnvironment = KotlinCoreEnvironment.getOrCreateApplicationEnvironmentForTests(
testServices.applicationDisposableProvider.getApplicationRootDisposable(),
CompilerConfiguration()
)
val configuration = createCompilerConfiguration(module)
val configuration = createCompilerConfiguration(module, configurators)
val projectEnv = KotlinCoreEnvironment.ProjectEnvironment(testRootDisposable, applicationEnvironment, configuration)
val project = projectEnv.project
return KotlinCoreEnvironment.createForTests(
projectEnv,
configuration,
configFiles
).also { configurators.forEach { it.registerCompilerExtensions(project, module, configuration) } }
).also { registerCompilerExtensions(projectEnv.project, module, configuration) }
}
@TestInfrastructureInternals
@OptIn(TestInfrastructureInternals::class)
fun createCompilerConfiguration(module: TestModule): CompilerConfiguration {
val configuration = CompilerConfiguration()
configuration[CommonConfigurationKeys.MODULE_NAME] = module.name
if (JsEnvironmentConfigurationDirectives.PROPERTY_LAZY_INITIALIZATION in module.directives) {
configuration.put(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION, true)
}
return createCompilerConfiguration(module, configurators)
}
}
if (module.frontendKind == FrontendKinds.FIR) {
configuration[CommonConfigurationKeys.USE_FIR] = true
}
configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY] = object : MessageCollector {
override fun clear() {}
@TestInfrastructureInternals
fun TargetPlatform.platformToEnvironmentConfigFiles() = when {
isJvm() -> EnvironmentConfigFiles.JVM_CONFIG_FILES
isJs() -> EnvironmentConfigFiles.JS_CONFIG_FILES
isNative() -> EnvironmentConfigFiles.NATIVE_CONFIG_FILES
// TODO: is it correct?
isCommon() -> EnvironmentConfigFiles.METADATA_CONFIG_FILES
else -> error("Unknown platform: ${this}")
}
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
if (severity == CompilerMessageSeverity.ERROR) {
val prefix = if (location == null) "" else "(" + location.path + ":" + location.line + ":" + location.column + ") "
throw AssertionError(prefix + message)
}
@TestInfrastructureInternals
fun createCompilerConfiguration(module: TestModule, configurators: List<AbstractEnvironmentConfigurator>): CompilerConfiguration {
val configuration = CompilerConfiguration()
configuration[CommonConfigurationKeys.MODULE_NAME] = module.name
if (JsEnvironmentConfigurationDirectives.PROPERTY_LAZY_INITIALIZATION in module.directives) {
configuration.put(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION, true)
}
if (module.frontendKind == FrontendKinds.FIR) {
configuration[CommonConfigurationKeys.USE_FIR] = true
}
configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY] = object : MessageCollector {
override fun clear() {}
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
if (severity == CompilerMessageSeverity.ERROR) {
val prefix = if (location == null) "" else "(" + location.path + ":" + location.line + ":" + location.column + ") "
throw AssertionError(prefix + message)
}
override fun hasErrors(): Boolean = false
}
configuration.languageVersionSettings = module.languageVersionSettings
configurators.forEach { it.configureCompileConfigurationWithAdditionalConfigurationKeys(configuration, module) }
return configuration
override fun hasErrors(): Boolean = false
}
configuration.languageVersionSettings = module.languageVersionSettings
private operator fun <T : Any> CompilerConfiguration.set(key: CompilerConfigurationKey<T>, value: T) {
put(key, value)
}
configurators.forEach { it.configureCompileConfigurationWithAdditionalConfigurationKeys(configuration, module) }
return configuration
}
private operator fun <T : Any> CompilerConfiguration.set(key: CompilerConfigurationKey<T>, value: T) {
put(key, value)
}
val TestModule.javaFiles: List<TestFile>